Files
fe.ems.vue3/src/views/configManage/configParamTreeTable/index.vue
2023-11-27 17:19:50 +08:00

1598 lines
46 KiB
Vue

<script setup lang="ts">
import { reactive, ref, onMounted, watch, toRaw, nextTick } from 'vue';
import { PageContainer } from '@ant-design-vue/pro-layout';
import { message } from 'ant-design-vue/lib';
import useI18n from '@/hooks/useI18n';
import TableColumnsDnd from '@/components/TableColumnsDnd/index.vue';
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
import {
getParamConfigTopTab,
getParamConfigInfoForm,
updateParamConfigInfo,
delParamConfigInfo,
addParamConfigInfo,
} from '@/api/configManage/configParam';
import useNeInfoStore from '@/store/modules/neinfo';
import { regExpIPv4, regExpIPv6 } from '@/utils/regular-utils';
import { SizeType } from 'ant-design-vue/lib/config-provider';
import { DataNode } from 'ant-design-vue/lib/tree';
const { t } = useI18n();
/**网元参数 */
let neCascaderOtions = ref<Record<string, any>[]>([]);
/**网元类型选择 type,id */
let neTypeSelect = ref<string[]>(['', '']);
/**对象信息状态类型 */
type TreeStateType = {
/**网元 loading */
loading: boolean;
/**网元配置 tree */
data: DataNode[];
/**选择对应Node一级 tree */
selectNode: Record<string, any>;
/**选择 loading */
selectLoading: boolean;
};
let treeState: TreeStateType = reactive({
loading: true,
data: [],
selectNode: {
topDisplay: '' as string,
topTag: '' as string,
method: '' as string,
//
title: '' as string,
key: '' as string,
type: 'list' as 'list' | 'array',
},
selectLoading: true,
});
/**查询可选命令列表 */
function fnSelectConfigNode(_: any, info: any) {
const { title, key, method } = info.node;
treeState.selectNode.topDisplay = title;
treeState.selectNode.topTag = key;
treeState.selectNode.method = method;
treeState.selectNode.title = title;
treeState.selectNode.key = key;
fnActiveConfigNode(key);
}
/**tab标签栏标签点击监听 */
function fnActiveConfigNode(key: string | number) {
listState.data = [];
arrayState.data = [];
treeState.selectLoading = true;
if (key !== '#') {
treeState.selectNode.topTag = key as string;
}
// 获取数据
const neType = neTypeSelect.value[0];
const neId = neTypeSelect.value[1];
const topTag = treeState.selectNode.topTag;
getParamConfigInfoForm(neType, topTag, neId).then(res => {
if (res.code === RESULT_CODE_SUCCESS && res.data.type) {
treeState.selectLoading = false;
treeState.selectNode.topTag = topTag;
treeState.selectNode.type = res.data.type;
if (res.data.type === 'list') {
listState.data = res.data.data;
listEditClose();
}
if (res.data.type === 'array') {
arrayState.data = res.data.data;
arrayState.dataRule = res.data.dataRule;
// 列表数据
const columnsData: Record<string, any>[] = [];
for (const v of arrayState.data) {
const row: Record<string, any> = {};
for (const item of v.record) {
row[item.name] = item;
}
columnsData.push(row);
}
arrayState.columnsData = columnsData;
// 列表字段
const columns: Record<string, any>[] = [];
for (const rule of arrayState.dataRule.record) {
columns.push({
title: rule.display,
dataIndex: rule.name,
align: 'left',
resizable: true,
width: 150,
minWidth: 100,
maxWidth: 350,
});
}
columns.push({
title: t('common.operate'),
dataIndex: 'index',
key: 'index',
align: 'center',
fixed: 'right',
width: 100,
});
arrayState.columns = columns;
arrayEditClose();
}
} else {
message.warning({
content: t('common.noData'),
duration: 3,
});
}
});
}
/**查询配置Tag标签 */
function fnGetParamConfigTopTab() {
const neType = neTypeSelect.value[0];
if (!neType) {
message.warning({
content: t('views.configManage.configParamForm.neTypePleace'),
duration: 3,
});
return;
}
treeState.loading = true;
// 获取数据
getParamConfigTopTab(neType).then(res => {
if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.data)) {
treeState.data = res.data.map(item => ({
children: undefined,
title: item.topDisplay,
key: item.topTag,
...item,
}));
treeState.loading = false;
// 取首个tag
if (res.data.length > 0) {
const itemOne = res.data[0];
treeState.selectNode = {
title: itemOne.topDisplay,
key: itemOne.topTag,
type: 'list',
...itemOne,
};
fnActiveConfigNode(itemOne.topTag);
}
} else {
message.warning({
content: t('views.configManage.configParamForm.noConfigData'),
duration: 3,
});
}
});
}
/**单列表状态类型 */
type ListStateType = {
/**紧凑型 */
size: SizeType;
/**单列记录字段 */
columns: Record<string, any>[];
/**单列记录数据 */
data: Record<string, any>[];
/**编辑行记录 */
editRecord: Record<string, any>;
};
/**单列表状态 */
let listState: ListStateType = reactive({
size: 'middle',
columns: [
{
title: 'Key',
dataIndex: 'display',
align: 'left',
width: '30%',
},
{
title: 'Value',
dataIndex: 'value',
align: 'left',
width: '70%',
},
],
data: [],
editRecord: {},
});
/**单列表编辑 */
function listEdit(row: Record<string, any>) {
listState.editRecord = Object.assign({}, row);
}
/**单列表编辑关闭 */
function listEditClose() {
listState.editRecord = {};
}
/**单列表编辑确认 */
function listEditOk() {
const from = toRaw(listState.editRecord);
// 检查规则
const [ok, msg] = ruleVerification(from);
if (!ok) {
message.warning({
content: `${msg}`,
duration: 3,
});
return;
}
// 发送
const hide = message.loading({ content: t('common.loading') });
let data = {
[from['name']]: from['value'],
};
updateParamConfigInfo(
'list',
{
neType: neTypeSelect.value[0],
neId: neTypeSelect.value[1],
topTag: treeState.selectNode.topTag,
},
data
)
.then(res => {
if (res.code === RESULT_CODE_SUCCESS) {
message.success({
content: t('views.configManage.configParamForm.updateValue', {
num: from['display'],
}),
duration: 3,
});
// 改变表格数据
const item = listState.data.filter(
(item: Record<string, any>) => from['name'] === item['name']
)[0];
if (item) {
Object.assign(item, listState.editRecord);
}
} else {
message.warning({
content: t('views.configManage.configParamForm.updateValueErr'),
duration: 3,
});
}
})
.finally(() => {
hide();
listState.editRecord = {};
});
}
/**多列列表状态类型 */
type ArrayStateType = {
/**紧凑型 */
size: SizeType;
/**多列嵌套记录字段 */
columns: Record<string, any>[];
/**表格字段列排序 */
columnsDnd: Record<string, any>[];
/**多列记录数据 */
columnsData: Record<string, any>[];
/**多列嵌套展开key */
arrayChildExpandKeys: any[];
/**多列记录数据 */
data: Record<string, any>[];
/**多列记录规则 */
dataRule: Record<string, any>;
};
/**多列列表状态 */
let arrayState: ArrayStateType = reactive({
size: 'middle',
columns: [],
columnsDnd: [],
columnsData: [],
arrayChildExpandKeys: [],
data: [],
dataRule: {},
});
/**监听表格字段列排序变化关闭展开 */
watch(
() => arrayState.columnsDnd,
() => {
arrayEditClose();
}
);
/**多列表编辑 */
function arrayEdit(rowIndex: Record<string, any>) {
const item = arrayState.data.find((s: any) => s.key === rowIndex.value);
if (!item) return;
const row: Record<string, any> = {};
for (const v of item.record) {
row[v.name] = Object.assign({}, v);
}
modalState.from = row;
modalState.type = 'arrayEdit';
modalState.title = `${treeState.selectNode.topDisplay} ${item.title}`;
modalState.key = item.key;
modalState.data = item.record.filter((v: any) => !Array.isArray(v.array));
modalState.visible = true;
// 关闭嵌套
arrayChildExpandClose();
}
/**多列表编辑关闭 */
function arrayEditClose() {
arrayChildExpandClose();
fnModalCancel();
}
/**多列表编辑确认 */
function arrayEditOk(from: Record<string, any>) {
const loc = from['index']['value'];
const neType = neTypeSelect.value[0];
// 遍历提取属性和值
let data: Record<string, any> = {};
for (const key in from) {
// 子嵌套的不插入
if (from[key]['array']) {
continue;
}
// 检查规则
const [ok, msg] = ruleVerification(from[key]);
if (!ok) {
message.warning({
content: `${msg}`,
duration: 3,
});
return;
}
data[key] = from[key]['value'];
}
// 发送
const hide = message.loading({ content: t('common.loading') });
updateParamConfigInfo(
'array',
{
neType: neType,
neId: neTypeSelect.value[1],
topTag: treeState.selectNode.topTag,
loc,
},
data
)
.then(res => {
if (res.code === RESULT_CODE_SUCCESS) {
message.success({
content: t('views.configManage.configParamForm.updateItem', {
num: modalState.title,
}),
duration: 3,
});
fnActiveConfigNode('#');
} else {
message.warning({
content: t('views.configManage.configParamForm.updateItemErr'),
duration: 3,
});
}
})
.finally(() => {
hide();
arrayEditClose();
});
}
/**多列表删除单行 */
function arrayDelete(rowIndex: Record<string, any>) {
const index = rowIndex.value;
delParamConfigInfo({
neType: neTypeSelect.value[0],
neId: neTypeSelect.value[1],
topTag: treeState.selectNode.topTag,
loc: index,
}).then(res => {
if (res.code === RESULT_CODE_SUCCESS) {
message.success({
content: t('views.configManage.configParamForm.delItemOk', {
num: `${treeState.selectNode.topDisplay} Index-${index}`,
}),
duration: 2,
});
arrayEditClose();
fnActiveConfigNode('#');
} else {
message.error({
content: `${res.msg}`,
duration: 2,
});
}
});
}
/**多列表新增单行 */
function arrayAdd() {
const from = arrayAddInit(arrayState.data, arrayState.dataRule);
// 处理信息
const row: Record<string, any> = {};
for (const v of from.record) {
if (Array.isArray(v.array)) {
continue;
}
row[v.name] = Object.assign({}, v);
}
modalState.from = row;
modalState.type = 'arrayAdd';
modalState.title = `${treeState.selectNode.topDisplay} ${from.title}`;
modalState.key = from.key;
modalState.data = from.record.filter((v: any) => !Array.isArray(v.array));
modalState.visible = true;
}
/**多列表新增单行确认 */
function arrayAddOk(from: Record<string, any>) {
const index = from['index']['value'];
const neType = neTypeSelect.value[0];
// 遍历提取属性和值
let data: Record<string, any> = {};
for (const key in from) {
// 子嵌套的不插入
if (from[key]['array']) {
continue;
}
// 检查规则
const [ok, msg] = ruleVerification(from[key]);
if (!ok) {
message.warning({
content: `${msg}`,
duration: 3,
});
return;
}
data[key] = from[key]['value'];
}
// 发送
const hide = message.loading({ content: t('common.loading') });
addParamConfigInfo(
{
neType: neType,
neId: neTypeSelect.value[1],
topTag: treeState.selectNode.topTag,
loc: index,
},
data
)
.then(res => {
if (res.code === RESULT_CODE_SUCCESS) {
message.success({
content: t('views.configManage.configParamForm.addItemOk', {
num: modalState.title,
}),
duration: 3,
});
fnActiveConfigNode('#');
} else {
message.warning({
content: t('views.configManage.configParamForm.addItemErr'),
duration: 3,
});
}
})
.finally(() => {
hide();
arrayEditClose();
});
}
/**多列嵌套列表状态类型 */
type ArrayChildStateType = {
/**标题 */
title: string;
/**层级index */
loc: string;
/**紧凑型 */
size: SizeType;
/**多列嵌套记录字段 */
columns: Record<string, any>[];
/**表格字段列排序 */
columnsDnd: Record<string, any>[];
/**多列记录数据 */
columnsData: Record<string, any>[];
/**多列嵌套记录数据 */
data: Record<string, any>[];
/**多列嵌套记录规则 */
dataRule: Record<string, any>;
};
/**表格状态 */
let arrayChildState: ArrayChildStateType = reactive({
title: '',
loc: '',
size: 'middle',
columns: [],
columnsDnd: [],
columnsData: [],
data: [],
dataRule: {},
});
/**多列表展开嵌套行 */
function arrayChildExpand(
indexRow: Record<string, any>,
row: Record<string, any>
) {
const loc = indexRow.value;
if (arrayChildState.loc === `${loc}/${row.name}`) {
arrayChildState.loc = '';
arrayState.arrayChildExpandKeys = [];
return;
}
arrayChildState.loc = '';
arrayState.arrayChildExpandKeys = [];
const from = Object.assign({}, JSON.parse(JSON.stringify(row)));
// 无数据时
if (!Array.isArray(from.value)) {
from.value = [];
}
const dataArr = Object.freeze(from.value);
const ruleArr = Object.freeze(from.array);
// 列表项数据
const dataArray: Record<string, any>[] = [];
for (const item of dataArr) {
const index = item['index'];
let record: Record<string, any>[] = [];
for (const key of Object.keys(item)) {
// 规则为准
for (const rule of ruleArr) {
if (rule['name'] === key) {
const ruleItem = Object.assign({ optional: 'true' }, rule, {
value: item[key],
});
record.push(ruleItem);
break;
}
}
}
// dataArray.push(record);
dataArray.push({ title: `Index-${index}`, key: index, record });
}
arrayChildState.data = dataArray;
// 无数据时,用于新增
arrayChildState.dataRule = {
title: `Index-0`,
key: 0,
record: ruleArr,
};
// 列表数据
const columnsData: Record<string, any>[] = [];
for (const v of arrayChildState.data) {
const row: Record<string, any> = {};
for (const item of v.record) {
row[item.name] = item;
}
columnsData.push(row);
}
arrayChildState.columnsData = columnsData;
// 列表字段
const columns: Record<string, any>[] = [];
for (const rule of arrayChildState.dataRule.record) {
columns.push({
title: rule.display,
dataIndex: rule.name,
align: 'left',
resizable: true,
width: 50,
minWidth: 50,
maxWidth: 250,
});
}
columns.push({
title: t('common.operate'),
dataIndex: 'index',
key: 'index',
align: 'center',
fixed: 'right',
width: 100,
});
arrayChildState.columns = columns;
nextTick(() => {
// 设置展开key
arrayState.arrayChildExpandKeys = [indexRow];
// 层级标识
arrayChildState.loc = `${loc}/${from['name']}`;
// 设置展开列表标题
arrayChildState.title = `${from['display']}`;
});
}
/**多列表展开嵌套行 */
function arrayChildExpandClose() {
arrayChildState.loc = '';
arrayState.arrayChildExpandKeys = [];
}
/**多列表嵌套行编辑 */
function arrayChildEdit(rowIndex: Record<string, any>) {
const item = arrayChildState.data.find((s: any) => s.key === rowIndex.value);
if (!item) return;
const row: Record<string, any> = {};
for (const v of item.record) {
row[v.name] = Object.assign({}, v);
}
modalState.from = row;
modalState.type = 'arrayChildEdit';
modalState.title = `${arrayChildState.title} ${item.title}`;
modalState.key = item.key;
modalState.data = item.record.filter((v: any) => !Array.isArray(v.array));
modalState.visible = true;
}
/**多列表嵌套行编辑确认 */
function arrayChildEditOk(from: Record<string, any>) {
const index = from['index']['value'];
const loc = `${arrayChildState.loc}/${index}`;
const neType = neTypeSelect.value[0];
let data: Record<string, any> = {};
for (const key in from) {
// 子嵌套的不插入
if (from[key]['array']) {
continue;
}
// 检查规则
const [ok, msg] = ruleVerification(from[key]);
if (!ok) {
message.warning({
content: `${msg}`,
duration: 3,
});
return;
}
data[key] = from[key]['value'];
}
// 发送
const hide = message.loading({ content: t('common.loading') });
updateParamConfigInfo(
'array',
{
neType: neType,
neId: neTypeSelect.value[1],
topTag: treeState.selectNode.topTag,
loc,
},
data
)
.then(res => {
if (res.code === RESULT_CODE_SUCCESS) {
message.success({
content: t('views.configManage.configParamForm.updateItem', {
num: modalState.title,
}),
duration: 3,
});
fnActiveConfigNode('#');
} else {
message.warning({
content: t('views.configManage.configParamForm.updateItemErr'),
duration: 3,
});
}
})
.finally(() => {
hide();
arrayEditClose();
});
}
/**多列表嵌套行删除单行 */
function arrayChildDelete(rowIndex: Record<string, any>) {
const index = rowIndex.value;
const loc = `${arrayChildState.loc}/${index}`;
delParamConfigInfo({
neType: neTypeSelect.value[0],
neId: neTypeSelect.value[1],
topTag: treeState.selectNode.topTag,
loc,
}).then(res => {
if (res.code === RESULT_CODE_SUCCESS) {
message.success({
content: t('views.configManage.configParamForm.delItemOk', {
num: `${arrayChildState.title} Index-${index}`,
}),
duration: 2,
});
arrayEditClose();
fnActiveConfigNode('#');
} else {
message.error({
content: `${res.msg}`,
duration: 2,
});
}
});
}
/**多列表嵌套行新增单行 */
function arrayChildAdd() {
const from = arrayAddInit(arrayChildState.data, arrayChildState.dataRule);
// 处理信息
const row: Record<string, any> = {};
for (const v of from.record) {
if (Array.isArray(v.array)) {
continue;
}
row[v.name] = Object.assign({}, v);
}
modalState.from = row;
modalState.type = 'arrayChildAdd';
modalState.title = `${arrayChildState.title} ${from.title}`;
modalState.key = from.key;
modalState.data = from.record.filter((v: any) => !Array.isArray(v.array));
modalState.visible = true;
}
/**多列表新增单行确认 */
function arrayChildAddOk(from: Record<string, any>) {
const index = from['index']['value'];
const loc = `${arrayChildState.loc}/${index}`;
const neType = neTypeSelect.value[0];
let data: Record<string, any> = {};
for (const key in from) {
// 子嵌套的不插入
if (from[key]['array']) {
continue;
}
// 检查规则
const [ok, msg] = ruleVerification(from[key]);
if (!ok) {
message.warning({
content: `${msg}`,
duration: 3,
});
return;
}
data[key] = from[key]['value'];
}
// 发送
const hide = message.loading({ content: t('common.loading') });
addParamConfigInfo(
{
neType: neType,
neId: neTypeSelect.value[1],
topTag: treeState.selectNode.topTag,
loc,
},
data
)
.then(res => {
if (res.code === RESULT_CODE_SUCCESS) {
message.success({
content: t('views.configManage.configParamForm.addItemOk', {
num: modalState.title,
}),
duration: 3,
});
fnActiveConfigNode('#');
} else {
message.warning({
content: t('views.configManage.configParamForm.addItemErr'),
duration: 3,
});
}
})
.finally(() => {
hide();
arrayEditClose();
});
}
/**多列表新增行数据初始化 */
function arrayAddInit(data: any[], dataRule: any) {
const len = data.length;
let lastItme: Record<string, any> = {};
let newIndex = 0;
// 无数据时生成临时记录
if (len === 0) {
lastItme = dataRule;
} else {
lastItme = data[len - 1];
}
const from = Object.assign({}, JSON.parse(JSON.stringify(lastItme)));
for (const row of from.record) {
const value = row.value;
if (row.name === 'index') {
if (value !== '') {
newIndex = parseInt(value) + 1;
}
if (isNaN(newIndex)) {
newIndex = 0;
}
row.value = newIndex;
from.key = newIndex;
from.title = `Index-${newIndex}`;
continue;
}
// 子嵌套的不初始
if (row.array) {
row.value = null;
continue;
}
const type = row.type;
const filter = row.filter;
switch (type) {
case 'int':
if (filter && filter.indexOf('~') !== -1) {
const filterArr = filter.split('~');
const minInt = parseInt(filterArr[0]);
row.value = minInt;
} else {
row.value = 0;
}
break;
case 'enum':
if (filter && filter.indexOf('{') === 0) {
let filterJson: Record<string, any> = {};
try {
filterJson = JSON.parse(filter); //string---json
} catch (error) {
console.error(error);
}
row.value = Object.keys(filterJson)[0];
} else {
row.value = '0';
}
break;
case 'bool':
if (filter && filter.indexOf('{') === 0) {
let filterJson: Record<string, any> = {};
try {
filterJson = JSON.parse(filter); //string---json
} catch (error) {
console.error(error);
}
row.value = Object.keys(filterJson)[0];
} else {
row.value = false;
}
break;
case 'ipv4':
case 'ipv6':
case 'regex':
default:
row.value = '';
break;
}
}
return from;
}
/**规则校验 */
function ruleVerification(row: Record<string, any>): (string | boolean)[] {
let result = [true, ''];
const type = row.type;
const value = row.value;
const filter = row.filter;
const display = row.display;
// 子嵌套的不检查
if (row.array) {
return result;
}
// 可选的同时没有值不检查
if (row.optional === 'true' && !value) {
return result;
}
switch (type) {
case 'int':
if (filter && filter.indexOf('~') !== -1) {
const filterArr = filter.split('~');
const minInt = parseInt(filterArr[0]);
const maxInt = parseInt(filterArr[1]);
const valueInt = parseInt(value);
if (valueInt < minInt || valueInt > maxInt) {
return [
false,
t('views.configManage.configParamForm.requireInt', {
display,
filter,
}),
];
}
}
break;
case 'ipv4':
if (!regExpIPv4.test(value)) {
return [
false,
t('views.configManage.configParamForm.requireIpv4', { display }),
];
}
break;
case 'ipv6':
if (!regExpIPv6.test(value)) {
return [
false,
t('views.configManage.configParamForm.requireIpv6', { display }),
];
}
break;
case 'enum':
if (filter && filter.indexOf('{') === 1) {
let filterJson: Record<string, any> = {};
try {
filterJson = JSON.parse(filter); //string---json
} catch (error) {
console.error(error);
}
if (!Object.keys(filterJson).includes(`${value}`)) {
return [
false,
t('views.configManage.configParamForm.requireEnum', { display }),
];
}
}
break;
case 'bool':
if (filter && filter.indexOf('{') === 1) {
let filterJson: Record<string, any> = {};
try {
filterJson = JSON.parse(filter); //string---json
} catch (error) {
console.error(error);
}
if (!Object.values(filterJson).includes(`${value}`)) {
return [
false,
t('views.configManage.configParamForm.requireBool', { display }),
];
}
}
break;
case 'string':
if (filter && filter.indexOf('~') !== -1) {
try {
const filterArr = filter.split('~');
let rule = new RegExp(
'^\\S{' + filterArr[0] + ',' + filterArr[1] + '}$'
);
if (!rule.test(value)) {
return [
false,
t('views.configManage.configParamForm.requireString', {
display,
}),
];
}
} catch (error) {
console.error(error);
}
}
break;
case 'regex':
if (filter) {
try {
let regex = new RegExp(filter);
if (!regex.test(value)) {
return [
false,
t('views.configManage.configParamForm.requireString', {
display,
}),
];
}
} catch (error) {
console.error(error);
}
}
break;
default:
return [
false,
t('views.configManage.configParamForm.requireUn', { display }),
];
}
return result;
}
/**对话框对象信息状态类型 */
type ModalStateType = {
/**添加框是否显示 */
visible: boolean;
/**标题 */
title: string;
/**表单数据 */
from: Record<string, any>;
/**确定按钮 loading */
confirmLoading: boolean;
/**项类型 */
type: 'arrayAdd' | 'arrayEdit' | 'arrayChildAdd' | 'arrayChildEdit';
/**项Key */
key: string | number;
/**项数据 */
data: Record<string, any>[];
};
/**对话框对象信息状态 */
let modalState: ModalStateType = reactive({
visible: false,
title: 'Item',
from: {},
confirmLoading: false,
type: 'arrayAdd',
key: '',
data: [],
});
/**
* 对话框弹出确认执行函数
* 进行表达规则校验
*/
function fnModalOk() {
const from = toRaw(modalState.from);
if (modalState.type === 'arrayAdd') {
arrayAddOk(from);
}
if (modalState.type === 'arrayEdit') {
arrayEditOk(from);
}
if (modalState.type === 'arrayChildAdd') {
arrayChildAddOk(from);
}
if (modalState.type === 'arrayChildEdit') {
arrayChildEditOk(from);
}
}
/**
* 对话框弹出关闭执行函数
* 进行表达规则校验
*/
function fnModalCancel() {
modalState.visible = false;
modalState.from = {};
modalState.type = 'arrayAdd';
modalState.key = '';
modalState.data = [];
}
onMounted(() => {
// 获取网元网元列表
useNeInfoStore()
.fnNelist()
.then(res => {
if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.data)) {
if (res.data.length > 0) {
// 过滤不可用的网元
neCascaderOtions.value = useNeInfoStore().getNeCascaderOtions.filter(
(item: any) => {
return !['OMC'].includes(item.value);
}
);
// 默认选择AMF
const item = neCascaderOtions.value.find(s => s.value === 'UPF');
if (item && item.children) {
const info = item.children[0];
neTypeSelect.value = [info.neType, info.neId];
} else {
const info = neCascaderOtions.value[0].children[0];
neTypeSelect.value = [info.neType, info.neId];
}
fnGetParamConfigTopTab();
}
} else {
message.warning({
content: t('common.noData'),
duration: 2,
});
}
});
});
</script>
<template>
<PageContainer>
<a-row :gutter="16">
<a-col :span="6">
<!-- 网元类型 -->
<a-card
size="small"
:bordered="false"
:title="t('views.configManage.configParamForm.treeTitle')"
:loading="treeState.loading"
>
<a-form layout="vertical" autocomplete="off">
<a-form-item name="neId ">
<a-cascader
v-model:value="neTypeSelect"
:options="neCascaderOtions"
:allow-clear="false"
@change="fnGetParamConfigTopTab"
/>
</a-form-item>
<a-form-item name="listeningPort">
<a-tree
:tree-data="treeState.data"
:selected-keys="[treeState.selectNode.topTag]"
@select="fnSelectConfigNode"
>
</a-tree>
</a-form-item>
</a-form>
</a-card>
</a-col>
<a-col :span="18">
<a-card
size="small"
:bordered="false"
:body-style="{ maxHeight: '650px', 'overflow-y': 'scroll' }"
:loading="treeState.selectLoading"
>
<template #title>
<a-typography-text strong v-if="treeState.selectNode.topDisplay">
{{ treeState.selectNode.topDisplay }}
</a-typography-text>
<a-typography-text type="danger" v-else>
{{ t('views.configManage.configParamForm.treeSelectTip') }}
</a-typography-text>
</template>
<template #extra>
<a-space :size="8" align="center" v-show="!treeState.selectLoading">
<a-tooltip>
<template #title>{{ t('common.reloadText') }}</template>
<a-button
type="default"
@click.prevent="fnActiveConfigNode('#')"
>
<template #icon>
<ReloadOutlined />
</template>
</a-button>
</a-tooltip>
</a-space>
</template>
<!-- 单列表格列表 -->
<a-table
v-if="treeState.selectNode.type === 'list'"
class="table"
row-key="name"
:size="listState.size"
:columns="listState.columns"
:data-source="listState.data"
:pagination="false"
:bordered="true"
:scroll="{ x: true }"
>
<template #bodyCell="{ column, text, record }">
<template v-if="column.dataIndex === 'value'">
<a-tooltip placement="topLeft">
<template #title v-if="record.comment">
{{ record.comment }}
</template>
<div class="editable-cell">
<div
v-if="
listState.editRecord['display'] === record['display']
"
class="editable-cell__input-wrapper"
>
<a-input-number
v-if="record['type'] === 'int'"
v-model:value="listState.editRecord['value']"
style="width: 100%"
></a-input-number>
<a-switch
v-else-if="record['type'] === 'bool'"
v-model:checked="listState.editRecord['value']"
:checked-children="t('common.switch.open')"
:un-checked-children="t('common.switch.shut')"
></a-switch>
<a-select
v-else-if="record['type'] === 'enum'"
v-model:value="listState.editRecord['value']"
:allow-clear="true"
style="width: 100%"
>
<a-select-option
:value="+v"
:key="+v"
v-for="(k, v) in JSON.parse(record['filter'])"
>
{{ k }}
</a-select-option>
</a-select>
<a-input
v-else
v-model:value="listState.editRecord['value']"
></a-input>
<a-space :size="16" align="center" direction="horizontal">
<a-tooltip placement="bottomRight">
<template #title> {{ t('common.ok') }} </template>
<a-popconfirm
:title="
t(
'views.configManage.configParamForm.editOkTip',
{ num: record['display'] }
)
"
placement="topRight"
@confirm="listEditOk()"
>
<a-button
type="text"
class="editable-cell__icon-edit"
>
<template #icon><CheckOutlined /></template>
</a-button>
</a-popconfirm>
</a-tooltip>
<a-tooltip placement="bottomRight">
<template #title>
{{ t('common.cancel') }}
</template>
<a-button
type="text"
class="editable-cell__icon-edit"
@click.prevent="listEditClose()"
>
<template #icon><CloseOutlined /></template>
</a-button>
</a-tooltip>
</a-space>
</div>
<div v-else class="editable-cell__text-wrapper">
<template v-if="record['type'] === 'enum'">
{{ JSON.parse(record['filter'])[text] }}
</template>
<template v-else>{{ `${text}` || '&nbsp;' }}</template>
<EditOutlined
class="editable-cell__icon"
@click="listEdit(record)"
v-if="!['read-only', 'ro'].includes(record.access)"
/>
</div>
</div>
</a-tooltip>
</template>
</template>
</a-table>
<!-- array类型 -->
<template v-if="treeState.selectNode.type === 'array'">
<a-table
class="table"
row-key="index"
:columns="treeState.selectNode.method === 'get' ? arrayState.columnsDnd.filter((s:any)=>s.key !== 'index') : arrayState.columnsDnd"
:data-source="arrayState.columnsData"
:size="arrayState.size"
:pagination="false"
:bordered="true"
:scroll="{ x: arrayState.columnsDnd.length * 200, y: 450 }"
@resizeColumn="(w:number, col:any) => (col.width = w)"
:show-expand-column="false"
v-model:expanded-row-keys="arrayState.arrayChildExpandKeys"
>
<!-- 多列新增操作 -->
<template #title v-if="treeState.selectNode.method !== 'get'">
<a-space :size="16" align="center">
<a-button
type="primary"
@click.prevent="arrayAdd()"
size="small"
>
<template #icon> <PlusOutlined /> </template>
{{ t('common.addText') }}
</a-button>
<TableColumnsDnd
type="ghost"
:columns="[...arrayState.columns]"
v-model:columns-dnd="arrayState.columnsDnd"
></TableColumnsDnd>
</a-space>
</template>
<!-- 多列数据渲染 -->
<template #bodyCell="{ column, text, record }">
<template v-if="column?.key === 'index'">
<a-space
:size="16"
align="center"
v-if="!['read-only', 'ro'].includes(text.access)"
>
<a-tooltip>
<template #title>{{ t('common.editText') }}</template>
<a-button type="link" @click.prevent="arrayEdit(text)">
<template #icon><FormOutlined /></template>
</a-button>
</a-tooltip>
<a-tooltip>
<template #title>{{ t('common.deleteText') }}</template>
<a-button type="link" @click.prevent="arrayDelete(text)">
<template #icon><DeleteOutlined /></template>
</a-button>
</a-tooltip>
</a-space>
</template>
<template v-else-if="text">
<a-tooltip placement="topLeft">
<template #title v-if="text.comment">
{{ text.comment }}
</template>
<div class="editable-cell">
<template v-if="text.array">
<a-button
type="default"
size="small"
@click.prevent="
arrayChildExpand(record['index'], text)
"
>
<template #icon><BarsOutlined /></template>
{{
t('views.configManage.configParamForm.arrayMore')
}}
</a-button>
<!--特殊字段拓展显示-->
<span v-if="text.name === 'dnnList'">
({{ text.value.map((s: any) => s.dnn).join() }})
</span>
</template>
<div v-else class="editable-cell__text-wrapper">
<template v-if="text['type'] === 'enum'">
{{ JSON.parse(text['filter'])[text.value] }}
</template>
<template v-else>
{{ `${text.value}` || '&nbsp;' }}
</template>
</div>
</div>
</a-tooltip>
</template>
</template>
<!-- 多列嵌套类型 -->
<template #expandedRowRender>
<a-table
class="table"
row-key="index"
:columns="arrayChildState.columnsDnd"
:data-source="arrayChildState.columnsData"
:size="arrayChildState.size"
:pagination="false"
:bordered="true"
:scroll="{
x: arrayChildState.columnsDnd.length * 200,
y: 450,
}"
@resizeColumn="(w:number, col:any) => (col.width = w)"
>
<template #title>
<a-space :size="16" align="center">
<a-button
type="primary"
@click.prevent="arrayChildAdd"
size="small"
>
<template #icon> <PlusOutlined /> </template>
{{ t('common.addText') }} {{ arrayChildState.title }}
</a-button>
<TableColumnsDnd
type="ghost"
:columns="[...arrayChildState.columns]"
v-model:columns-dnd="arrayChildState.columnsDnd"
v-if="arrayChildState.loc"
></TableColumnsDnd>
</a-space>
</template>
<template #bodyCell="{ column, text, record }">
<template v-if="column?.key === 'index'">
<a-space
:size="8"
align="center"
v-if="!['read-only', 'ro'].includes(text.access)"
>
<a-tooltip>
<template #title>{{ t('common.editText') }}</template>
<a-button
type="link"
@click.prevent="arrayChildEdit(text)"
>
<template #icon><FormOutlined /></template>
</a-button>
</a-tooltip>
<a-tooltip>
<template #title>{{
t('common.deleteText')
}}</template>
<a-button
type="link"
@click.prevent="arrayChildDelete(text)"
>
<template #icon><DeleteOutlined /></template>
</a-button>
</a-tooltip>
</a-space>
</template>
<template v-else-if="text">
<a-tooltip placement="topLeft">
<template #title v-if="text.comment">
{{ text.comment }}
</template>
<div class="editable-cell">
<template v-if="text.array">
<a-button type="default" size="small">
<template #icon><BarsOutlined /></template>
{{
t(
'views.configManage.configParamForm.arrayMore'
)
}}
</a-button>
</template>
<div v-else>
<template v-if="text['type'] === 'enum'">
{{ JSON.parse(text['filter'])[text.value] }}
</template>
<template v-else>
{{ `${text.value}` || '&nbsp;' }}
</template>
</div>
</div>
</a-tooltip>
</template>
</template>
</a-table>
</template>
</a-table>
</template>
</a-card>
</a-col>
</a-row>
<!-- 新增框或修改框 -->
<DraggableModal
width="800px"
:body-style="{ maxHeight: '650px', 'overflow-y': 'auto' }"
:keyboard="false"
:mask-closable="false"
:visible="modalState.visible"
:title="modalState.title"
:confirm-loading="modalState.confirmLoading"
@ok="fnModalOk"
@cancel="fnModalCancel"
>
<a-form
class="form"
layout="horizontal"
autocomplete="off"
:validate-on-rule-change="false"
:validateTrigger="[]"
:label-col="{ span: 6 }"
:labelWrap="true"
>
<a-form-item
v-for="item in modalState.data"
:label="item.display"
:name="item.name"
:required="item.optional === 'false'"
style="margin-bottom: 4px"
>
<a-tooltip placement="topLeft">
<template #title v-if="item.comment">
{{ item.comment }}
</template>
<div>
<div
v-if="
!Array.isArray(item.array) &&
modalState.from[item.name] !== undefined
"
>
<a-input-number
v-if="item['type'] === 'int'"
v-model:value="modalState.from[item.name]['value']"
:disabled="item.name === 'index'"
style="width: 100%"
></a-input-number>
<a-switch
v-else-if="item['type'] === 'bool'"
v-model:checked="modalState.from[item.name]['value']"
:checked-children="t('common.switch.open')"
:un-checked-children="t('common.switch.shut')"
></a-switch>
<a-select
v-else-if="item['type'] === 'enum'"
v-model:value="modalState.from[item.name]['value']"
:allow-clear="true"
style="width: 100%"
>
<a-select-option
:value="+v"
:key="+v"
v-for="(k, v) in JSON.parse(item['filter'])"
>
{{ k }}
</a-select-option>
</a-select>
<a-input
v-else
v-model:value="modalState.from[item.name]['value']"
:disabled="item.name === 'index'"
></a-input>
</div>
<div v-else>
{{ `${item.value || '&nbsp;'}` }}
</div>
</div>
</a-tooltip>
</a-form-item>
</a-form>
</DraggableModal>
</PageContainer>
</template>
<style lang="less" scoped>
.editable-cell {
&__icon {
display: none;
cursor: pointer;
}
&__icon:hover {
color: var(--ant-primary-color);
}
&__icon-edit:hover {
color: var(--ant-primary-color);
}
&__text-wrapper {
font-size: 16px;
color: #333;
}
&__text-wrapper:hover &__icon {
display: inline-block;
}
&__input-wrapper {
display: flex;
justify-content: start;
align-items: center;
}
}
</style>