diff --git a/src/api/ne/neConfig.ts b/src/api/ne/neConfig.ts new file mode 100644 index 00000000..dcd1e8dd --- /dev/null +++ b/src/api/ne/neConfig.ts @@ -0,0 +1,66 @@ +import { request } from '@/plugins/http-fetch'; + +/** + * 网元参数配置可用属性值列表指定网元类型全部无分页 + * @param query 查询参数 + * @returns object + */ +export function getAllNeConfig(neType: string) { + return request({ + url: `/ne/config/list/${neType}`, + method: 'get', + timeout: 60_000, + }); +} + +/** + * 网元参数配置数据信息 + * @param params 数据 {neType,neId,paramName} + * @returns object + */ +export function getNeConfigData(params: Record) { + return request({ + url: `/ne/config/data`, + params, + method: 'get', + }); +} + +/** + * 网元参数配置数据更新 + * @param data 数据 {neType,neId,paramName:"参数名",paramData:{参数},loc:"层级index仅array"} + * @returns object + */ +export function editNeConfigData(data: Record) { + return request({ + url: `/ne/config/data`, + method: 'put', + data: data, + }); +} + +/** + * 网元参数配置数据新增(array) + * @param data 数据 {neType,neId,paramName:"参数名",paramData:{参数},loc:"层级index"} + * @returns object + */ +export function addNeConfigData(data: Record) { + return request({ + url: `/ne/config/data`, + method: 'post', + data: data, + }); +} + +/** + * 网元参数配置数据删除(array) + * @param params 数据 {neType,neId,paramName:"参数名",loc:"层级index"} + * @returns object + */ +export function delNeConfigData(params: Record) { + return request({ + url: `/ne/config/data`, + method: 'delete', + params, + }); +} diff --git a/src/i18n/locales/en-US.ts b/src/i18n/locales/en-US.ts index ddd0ed55..9663e23a 100644 --- a/src/i18n/locales/en-US.ts +++ b/src/i18n/locales/en-US.ts @@ -770,6 +770,31 @@ export default { uploadChangeOk: 'Network Element renewed license successfully and is being calibrated in the background!', uploadChangeFail: "Some network elements failed to update the license, please check whether the service terminal environment is available!", }, + neConfig: { + treeTitle: "Navigation Configuration", + treeSelectTip: "Select configuration item information in the left configuration navigation!", + neType: 'NE Type', + neTypePleace: "Please select the network element type", + noConfigData: "No data on configuration items", + updateValue: "[ {num} ] parameter value modified successfully.", + updateValueErr: "Attribute value modification failure", + updateItem: "Modify Index to {num}.", + updateItemErr: "Record modification failure", + delItemOk: "Deleting Index as {num} succeeded", + addItemOk: "Add Index as {num} Record Succeeded", + addItemErr: "Record addition failure", + requireUn: "[ {display} ] input value is of unknown type", + requireString: "[ {display} ] parameter value is invalid.", + requireInt: "[ {display} ] parameter value not in reasonable range {filter}", + requireIpv4: "[ {display} ] not a legitimate IPV4 address", + requireIpv6: "[ {display} ] not a legitimate IPV6 address.", + requireEnum: "[ {display} ] is not a reasonable enumeration value.", + requireBool: "[ {display} ] is not a reasonable boolean value.", + editOkTip: "Confirm updating the value of this [ {num} ] attribute?", + updateItemTip: "Confirm updating the data item with Index [{num}]?", + delItemTip: "Confirm deleting the data item with Index [{num}]?", + arrayMore: "Expand", + }, neConfigBackup: { name: "Name", downTip: 'Confirmed to download the backup file [{txt}]?', diff --git a/src/i18n/locales/zh-CN.ts b/src/i18n/locales/zh-CN.ts index 51f81718..fed45b0d 100644 --- a/src/i18n/locales/zh-CN.ts +++ b/src/i18n/locales/zh-CN.ts @@ -770,6 +770,31 @@ export default { uploadChangeOk: '网元更新许可证成功,正在后台校验!', uploadChangeFail: "部分网元更新许可证失败,请检查服务终端环境是否可用!", }, + neConfig: { + treeTitle: "配置导航", + treeSelectTip: "左侧配置导航中选择配置项信息!", + neType: "网元类型", + neTypePleace: "请选择网元类型", + noConfigData: "暂无配置项数据", + updateValue: "【 {num} 】 属性值修改成功", + updateValueErr: "属性值修改失败", + updateItem: "修改 Index 为 {num} 记录成功", + updateItemErr: "记录修改失败", + delItemOk: "删除 Index 为 {num} 记录成功", + addItemOk: "新增 Index 为 {num} 记录成功", + addItemErr: "记录新增失败", + requireUn: "【 {display} 】输入值是未知类型", + requireString: "【 {display} 】参数值不合理", + requireInt: "【 {display} 】参数值不在合理范围 {filter}", + requireIpv4: "【 {display} 】不是合法的IPV4地址", + requireIpv6: "【 {display} 】不是合法的IPV6地址", + requireEnum: "【 {display} 】不是合理的枚举值", + requireBool: "【 {display} 】不是合理的布尔类型的值", + editOkTip: "确认更新该【 {num} 】属性值吗?", + updateItemTip: "确认更新Index为 【{num}】 的数据项?", + delItemTip: "确认删除Index为 【{num}】 的数据项?", + arrayMore: "展开", + }, neConfigBackup: { name: "名称", downTip: '确认要下载备份文件【{txt}】吗?', diff --git a/src/views/ne/neConfig/hooks/useConfigArray.ts b/src/views/ne/neConfig/hooks/useConfigArray.ts new file mode 100644 index 00000000..da74fd28 --- /dev/null +++ b/src/views/ne/neConfig/hooks/useConfigArray.ts @@ -0,0 +1,347 @@ +import { + addNeConfigData, + delNeConfigData, + editNeConfigData, +} from '@/api/ne/neConfig'; +import { RESULT_CODE_SUCCESS } from '@/constants/result-constants'; +import { Modal } from 'ant-design-vue/lib'; +import { SizeType } from 'ant-design-vue/lib/config-provider'; +import message from 'ant-design-vue/lib/message'; +import { reactive, watch } from 'vue'; + +/** + * 参数配置array类型 + * @param param 父级传入 { t, treeState, neTypeSelect, fnActiveConfigNode, ruleVerification, modalState, fnModalCancel} + * @returns + */ +export default function useConfigArray({ + t, + treeState, + neTypeSelect, + fnActiveConfigNode, + ruleVerification, + modalState, + fnModalCancel, +}: any) { + /**多列列表状态类型 */ + type ArrayStateType = { + /**紧凑型 */ + size: SizeType; + /**多列嵌套记录字段 */ + columns: Record[]; + /**表格字段列排序 */ + columnsDnd: Record[]; + /**多列记录数据 */ + columnsData: Record[]; + /**多列嵌套展开key */ + arrayChildExpandKeys: any[]; + + /**多列记录数据 */ + data: Record[]; + /**多列记录规则 */ + dataRule: Record; + }; + + /**多列列表状态 */ + let arrayState: ArrayStateType = reactive({ + size: 'small', + columns: [], + columnsDnd: [], + columnsData: [], + arrayChildExpandKeys: [], + data: [], + dataRule: {}, + }); + + /**多列表编辑 */ + function arrayEdit(rowIndex: Record) { + const item = arrayState.data.find((s: any) => s.key === rowIndex.value); + if (!item) return; + const from = arrayInitEdit(item, arrayState.dataRule); + // 处理信息 + const row: Record = {}; + for (const v of from.record) { + if (Array.isArray(v.array)) { + continue; + } + row[v.name] = Object.assign({}, v); + } + + modalState.from = row; + modalState.type = 'arrayEdit'; + modalState.title = `${treeState.selectNode.paramDisplay} ${from.title}`; + modalState.key = from.key; + modalState.data = from.record.filter((v: any) => !Array.isArray(v.array)); + modalState.visible = true; + + // 关闭嵌套 + arrayState.arrayChildExpandKeys = []; + } + + /**多列表编辑关闭 */ + function arrayEditClose() { + arrayState.arrayChildExpandKeys = []; + fnModalCancel(); + } + + /**多列表编辑确认 */ + function arrayEditOk(from: Record) { + const loc = `${from['index']['value']}`; + // 遍历提取属性和值 + let data: Record = {}; + 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(t('common.loading'), 0); + editNeConfigData({ + neType: neTypeSelect.value[0], + neId: neTypeSelect.value[1], + paramName: treeState.selectNode.paramName, + paramData: data, + loc: loc, + }) + .then(res => { + if (res.code === RESULT_CODE_SUCCESS) { + message.success({ + content: t('views.ne.neConfig.updateItem', { + num: modalState.title, + }), + duration: 3, + }); + fnActiveConfigNode('#'); + } else { + message.warning({ + content: t('views.ne.neConfig.updateItemErr'), + duration: 3, + }); + } + }) + .finally(() => { + hide(); + arrayEditClose(); + }); + } + + /**多列表删除单行 */ + function arrayDelete(rowIndex: Record) { + const loc = `${rowIndex.value}`; + const title = `${treeState.selectNode.paramDisplay} Index-${loc}`; + + Modal.confirm({ + title: t('common.tipTitle'), + content: t('views.ne.neConfig.delItemTip', { + num: title, + }), + onOk() { + delNeConfigData({ + neType: neTypeSelect.value[0], + neId: neTypeSelect.value[1], + paramName: treeState.selectNode.paramName, + loc: loc, + }).then(res => { + if (res.code === RESULT_CODE_SUCCESS) { + message.success({ + content: t('views.ne.neConfig.delItemOk', { + num: title, + }), + duration: 2, + }); + arrayEditClose(); + fnActiveConfigNode('#'); + } else { + message.error({ + content: `${res.msg}`, + duration: 2, + }); + } + }); + }, + }); + } + + /**多列表新增单行 */ + function arrayAdd() { + const from = arrayInitAdd(arrayState.data, arrayState.dataRule); + + // 处理信息 + const row: Record = {}; + 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.paramDisplay} ${from.title}`; + modalState.key = from.key; + modalState.data = from.record.filter((v: any) => !Array.isArray(v.array)); + modalState.visible = true; + } + + /**多列表新增单行确认 */ + function arrayAddOk(from: Record) { + // 遍历提取属性和值 + let data: Record = {}; + 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(t('common.loading'), 0); + addNeConfigData({ + neType: neTypeSelect.value[0], + neId: neTypeSelect.value[1], + paramName: treeState.selectNode.paramName, + paramData: data, + loc: `${from['index']['value']}`, + }) + .then(res => { + if (res.code === RESULT_CODE_SUCCESS) { + message.success({ + content: t('views.ne.neConfig.addItemOk', { + num: modalState.title, + }), + duration: 3, + }); + fnActiveConfigNode('#'); + } else { + message.warning({ + content: t('views.ne.neConfig.addItemErr'), + duration: 3, + }); + } + }) + .finally(() => { + hide(); + arrayEditClose(); + }); + } + + /**多列表编辑行数据初始化 */ + function arrayInitEdit(data: Record, dataRule: any) { + const dataFrom = data.record; + const ruleFrom = Object.assign({}, JSON.parse(JSON.stringify(dataRule))); + for (const row of ruleFrom.record) { + // 子嵌套的不初始 + if (row.array) { + row.value = []; + continue; + } + // 查找项的值 + const item = dataFrom.find((s: any) => s.name === row.name); + if (!item) { + continue; + } + // 可选的 + row.optional = 'true'; + // 根据规则类型转值 + if (['enum', 'int'].includes(row.type)) { + row.value = Number(item.value); + } else if ('bool' === row.type) { + row.value = Boolean(item.value); + } else { + row.value = item.value; + } + } + ruleFrom.key = data.key; + ruleFrom.title = data.title; + return ruleFrom; + } + + /**多列表新增行数据初始化 */ + function arrayInitAdd(data: any[], dataRule: any) { + // 有数据时取得最后的index + let dataLastIndex = 0; + if (data.length !== 0) { + const lastFrom = Object.assign( + {}, + JSON.parse(JSON.stringify(data.at(-1))) + ); + if (lastFrom.record.length > 0) { + dataLastIndex = parseInt(lastFrom.key); + dataLastIndex += 1; + } + } + + const ruleFrom = Object.assign({}, JSON.parse(JSON.stringify(dataRule))); + for (const row of ruleFrom.record) { + // 子嵌套的不初始 + if (row.array) { + row.value = []; + continue; + } + // 可选的 + row.optional = 'true'; + // index值 + if (row.name === 'index') { + let newIndex = + dataLastIndex !== 0 ? dataLastIndex : parseInt(row.value); + if (isNaN(newIndex)) { + newIndex = 0; + } + row.value = newIndex; + ruleFrom.key = newIndex; + ruleFrom.title = `Index-${newIndex}`; + continue; + } + // 根据规则类型转值 + if (['enum', 'int'].includes(row.type)) { + row.value = Number(row.value); + } + if ('bool' === row.type) { + row.value = Boolean(row.value); + } + } + return ruleFrom; + } + + // 监听表格字段列排序变化关闭展开 + watch( + () => arrayState.columnsDnd, + () => { + arrayEditClose(); + } + ); + + return { + arrayState, + arrayEdit, + arrayEditClose, + arrayEditOk, + arrayDelete, + arrayAdd, + arrayAddOk, + arrayInitEdit, + arrayInitAdd, + }; +} diff --git a/src/views/ne/neConfig/hooks/useConfigArrayChild.ts b/src/views/ne/neConfig/hooks/useConfigArrayChild.ts new file mode 100644 index 00000000..6d09b22e --- /dev/null +++ b/src/views/ne/neConfig/hooks/useConfigArrayChild.ts @@ -0,0 +1,353 @@ +import { + addNeConfigData, + editNeConfigData, + delNeConfigData, +} from '@/api/ne/neConfig'; +import { RESULT_CODE_SUCCESS } from '@/constants/result-constants'; +import { Modal } from 'ant-design-vue/lib'; +import { SizeType } from 'ant-design-vue/lib/config-provider'; +import message from 'ant-design-vue/lib/message'; +import { nextTick, reactive } from 'vue'; + +/** + * 参数配置array类型的嵌套array + * @param param 父级传入 { t, treeState, neTypeSelect, fnActiveConfigNode, ruleVerification, modalState, arrayState, arrayInitEdit, arrayInitAdd, arrayEditClose} + * @returns + */ +export default function useConfigArrayChild({ + t, + treeState, + neTypeSelect, + fnActiveConfigNode, + ruleVerification, + modalState, + arrayState, + arrayInitEdit, + arrayInitAdd, + arrayEditClose, +}: any) { + /**多列嵌套列表状态类型 */ + type ArrayChildStateType = { + /**标题 */ + title: string; + /**层级index */ + loc: string; + /**紧凑型 */ + size: SizeType; + /**多列嵌套记录字段 */ + columns: Record[]; + /**表格字段列排序 */ + columnsDnd: Record[]; + /**多列记录数据 */ + columnsData: Record[]; + + /**多列嵌套记录数据 */ + data: Record[]; + /**多列嵌套记录规则 */ + dataRule: Record; + }; + + /**多列嵌套表格状态 */ + let arrayChildState: ArrayChildStateType = reactive({ + title: '', + loc: '', + size: 'small', + columns: [], + columnsDnd: [], + columnsData: [], + data: [], + dataRule: {}, + }); + + /**多列表展开嵌套行 */ + function arrayChildExpand( + indexRow: Record, + row: Record + ) { + 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[] = []; + for (const item of dataArr) { + const index = item['index']; + let record: Record[] = []; + 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[] = []; + for (const v of arrayChildState.data) { + const row: Record = {}; + for (const item of v.record) { + row[item.name] = item; + } + columnsData.push(row); + } + arrayChildState.columnsData = columnsData; + + // 列表字段 + const columns: Record[] = []; + 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 arrayChildEdit(rowIndex: Record) { + const item = arrayChildState.data.find( + (s: any) => s.key === rowIndex.value + ); + if (!item) return; + const from = arrayInitEdit(item, arrayChildState.dataRule); + // 处理信息 + const row: Record = {}; + for (const v of from.record) { + if (Array.isArray(v.array)) { + continue; + } + row[v.name] = Object.assign({}, v); + } + + modalState.from = row; + modalState.type = 'arrayChildEdit'; + 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 arrayChildEditOk(from: Record) { + const loc = `${arrayChildState.loc}/${from['index']['value']}`; + + let data: Record = {}; + 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(t('common.loading'), 0); + editNeConfigData({ + neType: neTypeSelect.value[0], + neId: neTypeSelect.value[1], + paramName: treeState.selectNode.paramName, + paramData: data, + loc, + }) + .then(res => { + if (res.code === RESULT_CODE_SUCCESS) { + message.success({ + content: t('views.ne.neConfig.updateItem', { + num: modalState.title, + }), + duration: 3, + }); + fnActiveConfigNode('#'); + } else { + message.warning({ + content: t('views.ne.neConfig.updateItemErr'), + duration: 3, + }); + } + }) + .finally(() => { + hide(); + arrayEditClose(); + }); + } + + /**多列表嵌套行删除单行 */ + function arrayChildDelete(rowIndex: Record) { + const index = rowIndex.value; + const loc = `${arrayChildState.loc}/${index}`; + const title = `${arrayChildState.title} Index-${index}`; + + Modal.confirm({ + title: t('common.tipTitle'), + content: t('views.ne.neConfig.delItemTip', { + num: title, + }), + onOk() { + delNeConfigData({ + neType: neTypeSelect.value[0], + neId: neTypeSelect.value[1], + paramName: treeState.selectNode.paramName, + loc, + }).then(res => { + if (res.code === RESULT_CODE_SUCCESS) { + message.success({ + content: t('views.ne.neConfig.delItemOk', { + num: title, + }), + duration: 2, + }); + arrayEditClose(); + fnActiveConfigNode('#'); + } else { + message.error({ + content: `${res.msg}`, + duration: 2, + }); + } + }); + }, + }); + } + + /**多列表嵌套行新增单行 */ + function arrayChildAdd() { + const from = arrayInitAdd(arrayChildState.data, arrayChildState.dataRule); + // 处理信息 + const row: Record = {}; + 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) { + const loc = `${arrayChildState.loc}/${from['index']['value']}`; + + let data: Record = {}; + 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(t('common.loading'), 0); + addNeConfigData({ + neType: neTypeSelect.value[0], + neId: neTypeSelect.value[1], + paramName: treeState.selectNode.paramName, + paramData: data, + loc, + }) + .then(res => { + if (res.code === RESULT_CODE_SUCCESS) { + message.success({ + content: t('views.ne.neConfig.addItemOk', { + num: modalState.title, + }), + duration: 3, + }); + fnActiveConfigNode('#'); + } else { + message.warning({ + content: t('views.ne.neConfig.addItemErr'), + duration: 3, + }); + } + }) + .finally(() => { + hide(); + arrayEditClose(); + }); + } + + return { + arrayChildState, + arrayChildExpand, + arrayChildEdit, + arrayChildEditOk, + arrayChildDelete, + arrayChildAdd, + arrayChildAddOk, + }; +} diff --git a/src/views/ne/neConfig/hooks/useConfigList.ts b/src/views/ne/neConfig/hooks/useConfigList.ts new file mode 100644 index 00000000..ef77f5a4 --- /dev/null +++ b/src/views/ne/neConfig/hooks/useConfigList.ts @@ -0,0 +1,145 @@ +import { editNeConfigData } from '@/api/ne/neConfig'; +import { RESULT_CODE_SUCCESS } from '@/constants/result-constants'; +import { SizeType } from 'ant-design-vue/lib/config-provider'; +import message from 'ant-design-vue/lib/message'; +import { reactive, toRaw } from 'vue'; + +/** + * list类型参数处理 + * @param param 父级传入 {t, treeState, neTypeSelect, ruleVerification} + * @returns + */ +export default function useConfigList({ + t, + treeState, + neTypeSelect, + ruleVerification, +}: any) { + /**单列表状态类型 */ + type ListStateType = { + /**紧凑型 */ + size: SizeType; + /**单列记录字段 */ + columns: Record[]; + /**单列记录数据 */ + data: Record[]; + /**编辑行记录 */ + editRecord: Record; + /**确认提交等待 */ + confirmLoading: boolean; + }; + + /**单列表状态 */ + let listState: ListStateType = reactive({ + size: 'small', + columns: [ + { + title: 'Key', + dataIndex: 'display', + align: 'left', + width: '30%', + }, + { + title: 'Value', + dataIndex: 'value', + align: 'left', + width: '70%', + }, + ], + data: [], + confirmLoading: false, + editRecord: {}, + }); + + /**单列表编辑 */ + function listEdit(row: Record) { + listState.editRecord = Object.assign({}, row); + } + + /**单列表编辑关闭 */ + function listEditClose() { + listState.confirmLoading = false; + listState.editRecord = {}; + } + + /**单列表编辑确认 */ + function listEditOk() { + if (listState.confirmLoading) return; + const from = toRaw(listState.editRecord); + // 检查规则 + const [ok, msg] = ruleVerification(from); + if (!ok) { + message.warning({ + content: `${msg}`, + duration: 3, + }); + return; + } + + // 发送 + listState.confirmLoading = true; + const hide = message.loading(t('common.loading'), 0); + editNeConfigData({ + neType: neTypeSelect.value[0], + neId: neTypeSelect.value[1], + paramName: treeState.selectNode.paramName, + paramData: { + [from['name']]: from['value'], + }, + }) + .then(res => { + if (res.code === RESULT_CODE_SUCCESS) { + message.success({ + content: t('views.ne.neConfig.updateValue', { + num: from['display'], + }), + duration: 3, + }); + // 改变表格数据 + const item = listState.data.find( + (item: Record) => from['name'] === item['name'] + ); + if (item) { + Object.assign(item, listState.editRecord); + } + } else { + message.warning({ + content: t('views.ne.neConfig.updateValueErr'), + duration: 3, + }); + } + }) + .finally(() => { + hide(); + listState.confirmLoading = false; + listState.editRecord = {}; + }); + } + + /**表格分页器参数 */ + let tablePagination = reactive({ + /**当前页数 */ + current: 1, + /**每页条数 */ + pageSize: 10, + /**默认的每页条数 */ + defaultPageSize: 10, + /**指定每页可以显示多少条 */ + pageSizeOptions: ['10', '20', '50', '100'], + /**只有一页时是否隐藏分页器 */ + hideOnSinglePage: true, + /**是否可以快速跳转至某页 */ + showQuickJumper: true, + /**是否可以改变 pageSize */ + showSizeChanger: true, + /**数据总数 */ + total: 0, + showTotal: (total: number) => t('common.tablePaginationTotal', { total }), + onChange: (page: number, pageSize: number) => { + tablePagination.current = page; + tablePagination.pageSize = pageSize; + }, + }); + + return { tablePagination, listState, listEdit, listEditClose, listEditOk }; +} diff --git a/src/views/ne/neConfig/hooks/useOptions.ts b/src/views/ne/neConfig/hooks/useOptions.ts new file mode 100644 index 00000000..8c88fde8 --- /dev/null +++ b/src/views/ne/neConfig/hooks/useOptions.ts @@ -0,0 +1,192 @@ +import { getNeConfigData } from '@/api/ne/neConfig'; +import { regExpIPv4, regExpIPv6, validURL } from '@/utils/regular-utils'; +import { ref } from 'vue'; + +/** + * 参数公共函数 + * @param param 父级传入 {t} + * @returns + */ +export default function useOptions({ t }: any) { + /**规则校验 */ + function ruleVerification(row: Record): (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': + // filter: "0~128" + + 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.ne.neConfig.requireInt', { + display, + filter, + }), + ]; + } + } + break; + case 'ipv4': + if (!regExpIPv4.test(value)) { + return [ + false, + t('views.ne.neConfig.requireIpv4', { display }), + ]; + } + break; + case 'ipv6': + if (!regExpIPv6.test(value)) { + return [ + false, + t('views.ne.neConfig.requireIpv6', { display }), + ]; + } + break; + case 'enum': + if (filter && filter.indexOf('{') === 1) { + let filterJson: Record = {}; + try { + filterJson = JSON.parse(filter); //string---json + } catch (error) { + console.error(error); + } + + if (!Object.keys(filterJson).includes(`${value}`)) { + return [ + false, + t('views.ne.neConfig.requireEnum', { display }), + ]; + } + } + break; + case 'bool': + // filter: '{"0":"false", "1":"true"}' + + if (filter && filter.indexOf('{') === 1) { + let filterJson: Record = {}; + try { + filterJson = JSON.parse(filter); //string---json + } catch (error) { + console.error(error); + } + + if (!Object.values(filterJson).includes(`${value}`)) { + return [ + false, + t('views.ne.neConfig.requireBool', { display }), + ]; + } + } + break; + case 'string': + // filter: "0~128" + + // 字符串长度判断 + 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.ne.neConfig.requireString', { + display, + }), + ]; + } + } catch (error) { + console.error(error); + } + } + // 字符串http判断 + if (value.startsWith('http')) { + try { + if (!validURL(value)) { + return [ + false, + t('views.ne.neConfig.requireString', { + display, + }), + ]; + } + } catch (error) { + console.error(error); + } + } + + break; + case 'regex': + // filter: "^[0-9]{3}$" + + if (filter) { + try { + let regex = new RegExp(filter); + if (!regex.test(value)) { + return [ + false, + t('views.ne.neConfig.requireString', { + display, + }), + ]; + } + } catch (error) { + console.error(error); + } + } + break; + + default: + return [ + false, + t('views.ne.neConfig.requireUn', { display }), + ]; + } + return result; + } + + /**upfId可选择 */ + const smfByUPFIdOptions = ref<{ value: string; label: string }[]>([]); + /**加载smf配置的upfId */ + function smfByUPFIdLoadData(neId: string) { + getNeConfigData({ + neType: 'SMF', + neId: neId, + paramName: 'upfConfig', + }).then(res => { + smfByUPFIdOptions.value = []; + for (const s of res.data) { + smfByUPFIdOptions.value.push({ + value: s.id, + label: s.id, + }); + } + }); + } + + return { + ruleVerification, + smfByUPFIdLoadData, + smfByUPFIdOptions, + }; +} diff --git a/src/views/ne/neConfig/index.vue b/src/views/ne/neConfig/index.vue new file mode 100644 index 00000000..39cd8a20 --- /dev/null +++ b/src/views/ne/neConfig/index.vue @@ -0,0 +1,942 @@ + + + + +