From 62410620ed5a2bcfee5a63540315526752ed8d0e Mon Sep 17 00:00:00 2001 From: TsMask <340112800@qq.com> Date: Mon, 9 Oct 2023 19:58:16 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=8F=82=E6=95=B0=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/configManage/configParam.ts | 355 +++- src/components/CodemirrorEditeDiff/index.vue | 22 +- src/views/configManage/configParam/index.vue | 1559 +++++++++++++++++- 3 files changed, 1829 insertions(+), 107 deletions(-) diff --git a/src/api/configManage/configParam.ts b/src/api/configManage/configParam.ts index 22735f9a..00fe238e 100644 --- a/src/api/configManage/configParam.ts +++ b/src/api/configManage/configParam.ts @@ -1,13 +1,18 @@ -import { RESULT_CODE_SUCCESS } from '@/constants/result-constants'; +import { + RESULT_CODE_ERROR, + RESULT_CODE_SUCCESS, + RESULT_MSG_ERROR, + RESULT_MSG_SUCCESS, +} from '@/constants/result-constants'; import { request } from '@/plugins/http-fetch'; -import { parseObjLineToHump } from '@/utils/parse-utils'; +import { parseFirstLower, parseObjLineToHump } from '@/utils/parse-utils'; /** * 查询配置参数标签栏 * @param neType 网元类型 * @returns object */ -export async function getParamConfigTopTab(neType : string ) { +export async function getParamConfigTopTab(neType: string) { // 发起请求 const result = await request({ url: `/databaseManagement/v1/elementType/omc_db/objectType/param_config`, @@ -19,8 +24,8 @@ export async function getParamConfigTopTab(neType : string ) { // 解析数据 if (result.code === RESULT_CODE_SUCCESS && Array.isArray(result.data.data)) { let data = result.data.data[0]; - data = data['param_config'] - if(Array.isArray(data)){ + data = data['param_config']; + if (Array.isArray(data)) { return Object.assign(result, { data: parseObjLineToHump(data), }); @@ -33,31 +38,355 @@ export async function getParamConfigTopTab(neType : string ) { } /** - * 查询配置参数标签栏 + * 查询配置参数标签栏对应JSON信息 * @param neType 网元类型 * @returns object */ -export async function getParamConfigInfo(neType : string ) { +export async function getParamConfigTopTabJson(neType: string, topTag: string) { // 发起请求 const result = await request({ url: `/databaseManagement/v1/elementType/omc_db/objectType/param_config`, method: 'get', params: { - SQL: `SELECT top_display,top_tag FROM param_config WHERE ne_type = '${neType}'`, + SQL: `SELECT param_json FROM param_config WHERE ne_type = '${neType}' AND top_tag='${topTag}'`, }, }); // 解析数据 if (result.code === RESULT_CODE_SUCCESS && Array.isArray(result.data.data)) { let data = result.data.data[0]; - data = data['param_config'] - if(Array.isArray(data)){ - return Object.assign(result, { - data: parseObjLineToHump(data), + data = data['param_config']; + if (Array.isArray(data)) { + const v = data[0]['param_json']; + try { + result.data = JSON.parse(v); + } catch (error) { + console.error(error); + result.data = {}; + } + } + return result; + } + return result; +} + +/** + * 查询配置参数标签栏对应信息 + * @param neType 网元类型 + * @returns object + */ +export async function getParamConfigInfo( + neType: string, + topTag: string, + neId: string +) { + const { wrRule, dataArr } = await Promise.allSettled([ + // 获取参数规则 + request({ + url: `/databaseManagement/v1/elementType/omc_db/objectType/param_config`, + method: 'get', + params: { + SQL: `SELECT param_json FROM param_config WHERE ne_type = '${neType}' AND top_tag='${topTag}'`, + }, + }), + // 获取对应信息 + request({ + url: `/systemManagement/v1/elementType/${neType.toLowerCase()}/objectType/config/${topTag}`, + method: 'get', + params: { + ne_id: neId, + }, + }), + ]).then(resArr => { + let wrRule: Record = {}; + // 规则数据 + if (resArr[0].status === 'fulfilled') { + const itemV = resArr[0].value; + // 解析数据 + if ( + itemV.code === RESULT_CODE_SUCCESS && + Array.isArray(itemV.data?.data) + ) { + let itemData = itemV.data.data; + const data = itemData[0]['param_config']; + if (Array.isArray(data)) { + const v = data[0]['param_json']; + try { + itemData = parseObjLineToHump(JSON.parse(v)); + wrRule = itemData; + } catch (error) { + console.error(error); + } + } + } + } + let dataArr: Record[] = []; + // 对应信息 + if (resArr[1].status === 'fulfilled') { + const itemV = resArr[1].value; + // 解析数据 + if ( + itemV.code === RESULT_CODE_SUCCESS && + Array.isArray(itemV.data?.data) + ) { + let itemData = itemV.data.data; + dataArr = parseObjLineToHump(itemData); + } + } + return { wrRule, dataArr }; + }); + + // UPF参数不统一 + if (neType === 'UPF') { + if (Reflect.has(wrRule, 'list')) { + for (const arr of wrRule['list']) { + arr['name'] = parseFirstLower(arr['name']); + } + for (const item of dataArr) { + for (const k in item) { + item[parseFirstLower(k)] = item[k]; + Reflect.deleteProperty(item, k); + } + } + } + if (Reflect.has(wrRule, 'array')) { + for (const arr of wrRule['array']) { + if (Array.isArray(arr['array'])) { + for (const child of arr['array']) { + child['name'] = parseFirstLower(child['name']); + } + } + arr['name'] = parseFirstLower(arr['name']); + } + for (const item of dataArr) { + for (const k in item) { + // 处理子列表 + if (Array.isArray(item[k])) { + for (const child of item[k]) { + for (const childKey in child) { + child[parseFirstLower(childKey)] = child[childKey]; + Reflect.deleteProperty(child, childKey); + } + } + } + item[parseFirstLower(k)] = item[k]; + Reflect.deleteProperty(item, k); + } + } + } + console.log(wrRule, dataArr); + } + + // 拼装数据 + const result = { + code: RESULT_CODE_SUCCESS, + msg: RESULT_MSG_SUCCESS, + data: { + type: 'list' as 'list' | 'array', + data: [] as any[], + dataRule: {}, + columns: [] as any[], + }, + }; + + // kv单列表 + if (Reflect.has(wrRule, 'list')) { + result.data.type = 'list'; + const ruleArr = Object.freeze(wrRule['list']); + + // 列表项数据 + let dataList = []; + for (const item of dataArr) { + for (const key of Object.keys(item)) { + // console.log(result.data.type, key, item[key]); + // 规则为准 + for (const rule of ruleArr) { + if (rule['name'] === key) { + const ruleItem = Object.assign({}, rule, { value: item[key] }); + dataList.push(ruleItem); + break; + } + } + } + } + result.data.data = dataList; + + // 列表字段 + result.data.columns = [ + { + title: 'Key', + dataIndex: 'display', + align: 'left', + width: '30%', + }, + { + title: 'Value', + dataIndex: 'value', + align: 'left', + width: '70%', + }, + ]; + } + // 多列表 + if (Reflect.has(wrRule, 'array')) { + result.data.type = 'array'; + const ruleArr = Object.freeze(wrRule['array']); + + // 列表项数据 + const dataArray = []; + for (const item of dataArr) { + let record: Record = {}; + for (const key of Object.keys(item)) { + // 规则为准 + for (const rule of ruleArr) { + if (rule['name'] === key) { + const ruleItem = Object.assign({}, rule, { value: item[key] }); + record[ruleItem.name] = ruleItem; + break; + } + } + } + dataArray.push(record); + } + // console.log(dataArray); + result.data.data = dataArray; + + // 无数据时,用于新增 + let dataRule: Record = {}; + for (const rule of ruleArr) { + dataRule[rule.name] = rule; + } + result.data.dataRule = dataRule; + + // 列表字段 + const columns: Record[] = []; + for (const rule of ruleArr) { + columns.push({ + title: rule.display, + dataIndex: rule.name, + align: 'left', }); } + // console.log(columns); + result.data.columns = columns; + } + return result; +} + +/** + * 查询配置参数标签栏对应信息子节点 + * @param neType 网元类型 + * @param topTag + * @param neId + * @param loc 子节点(index/字段) 1/dnnList + * @returns + */ +export async function getParamConfigInfoChild( + neType: string, + topTag: string, + neId: string, + loc: string +) { + // 发起请求 + const result = await request({ + url: `/systemManagement/v1/elementType/${neType.toLowerCase()}/objectType/config/${topTag}`, + method: 'get', + params: { + ne_id: neId, + loc: loc, + }, + }); + // 解析数据 + if (result.code === RESULT_CODE_SUCCESS && Array.isArray(result.data.data)) { return Object.assign(result, { - data: [], + data: parseObjLineToHump(result.data.data), }); } return result; } + +/** + * 修改配置参数标签栏对应信息 + * @param args 对象 {neType,neId,topTag,loc} + * @param data 对象 {修改的数据kv} + * @returns object + */ +export function updateParamConfigInfo( + type: 'list' | 'array', + args: Record, + data: Record +) { + let url = `/systemManagement/v1/elementType/${args.neType.toLowerCase()}/objectType/config/${ + args.topTag + }?ne_id=${args.neId}`; + + // 多列表需要loc + if (type === 'array') { + url += `&loc=${args.loc}`; + } + + return request({ + url, + method: 'put', + data: data, + }); +} + +/** + * 新增配置参数标签栏对应信息 + * @param args 对象 {neType,neId,topTag,loc} + * @param data 行记录对象 + * @returns object + */ +export function addParamConfigInfo( + args: Record, + data: Record +) { + return request({ + url: `/systemManagement/v1/elementType/${args.neType.toLowerCase()}/objectType/config/${ + args.topTag + }?ne_id=${args.neId}&loc=${args.loc}`, + method: 'post', + data: data, + }); +} + +/** + * 删除配置参数标签栏对应信息 + * @param args 对象 {neType,neId,topTag,loc} + * loc 多层表的定位信息{index0}/{paraName1}/{index1} + * @param data 行记录对象 + * @returns object + */ +export function delParamConfigInfo(args: Record) { + return request({ + url: `/systemManagement/v1/elementType/${args.neType.toLowerCase()}/objectType/config/${ + args.topTag + }?ne_id=${args.neId}&loc=${args.loc}`, + method: 'delete', + }); +} + +/** + * 更新网元配置重新载入 + * @param neType 网元类型 + * @param neId 网元ID + * @returns + */ +export async function updateNeConfigReload(neType: string, neId: string) { + // 发起请求 + const result = await request({ + url: `/operationManagement/v1/elementType/${neType}/objectType/mml?ne_id=${neId}`, + method: 'post', + data: { mml: ['reload'] }, + }); + // 解析数据 + if (result.code === RESULT_CODE_SUCCESS && Array.isArray(result.data.data)) { + const v = result.data.data[0]; + if (v && v.toLowerCase().includes('ok')) { + delete result.data; + } else { + return { code: RESULT_CODE_ERROR, msg: RESULT_MSG_ERROR }; + } + } + return result; +} diff --git a/src/components/CodemirrorEditeDiff/index.vue b/src/components/CodemirrorEditeDiff/index.vue index d86eeb65..0a768ade 100644 --- a/src/components/CodemirrorEditeDiff/index.vue +++ b/src/components/CodemirrorEditeDiff/index.vue @@ -8,7 +8,6 @@ @cancel="fnCronModal(false)" @ok="fnCronModal(true)" > -
@@ -61,22 +60,11 @@ watch( // 开启时等待dom完成 nextTick(() => { - console.log(mergeViewContainer.value.style); // 设置高度 mergeViewContainer.value.style.height = props.height; // 实例到dom new MergeView({ a: { - doc: props.newArea, - extensions: [ - javascript(), - oneDark, - basicSetup, - EditorView.editable.of(!props.disabled), - EditorState.readOnly.of(props.disabled), - ], - }, - b: { doc: props.oldArea, extensions: [ javascript(), @@ -86,6 +74,16 @@ watch( EditorState.readOnly.of(true), ], }, + b: { + doc: props.newArea, + extensions: [ + javascript(), + oneDark, + basicSetup, + EditorView.editable.of(!props.disabled), + EditorState.readOnly.of(props.disabled), + ], + }, parent: mergeViewContainer.value, }); }); diff --git a/src/views/configManage/configParam/index.vue b/src/views/configManage/configParam/index.vue index c0d3cda5..83a427ca 100644 --- a/src/views/configManage/configParam/index.vue +++ b/src/views/configManage/configParam/index.vue @@ -2,26 +2,31 @@ import { useRoute } from 'vue-router'; import { reactive, ref, onMounted } from 'vue'; import { PageContainer } from '@ant-design-vue/pro-layout'; -import { message } from 'ant-design-vue/lib'; +import { Modal, message } from 'ant-design-vue/lib'; import useI18n from '@/hooks/useI18n'; import { RESULT_CODE_SUCCESS } from '@/constants/result-constants'; -import { getParamConfigTopTab } from '@/api/configManage/configParam'; +import { + getParamConfigTopTab, + getParamConfigInfo, + updateParamConfigInfo, + updateNeConfigReload, + delParamConfigInfo, + addParamConfigInfo, +} from '@/api/configManage/configParam'; import { TabPosition } from 'ant-design-vue/lib/tabs/src/interface'; import useNeInfoStore from '@/store/modules/neinfo'; import CodemirrorEdite from '@/components/CodemirrorEdite/index.vue'; import CodemirrorEditeDiff from '@/components/CodemirrorEditeDiff/index.vue'; +import { SizeType } from 'ant-design-vue/lib/config-provider'; +import { toRaw } from 'vue'; +import { regExpIPv4, regExpIPv6 } from '@/utils/regular-utils'; +import { parseFirstUpper } from '@/utils/parse-utils'; const { t } = useI18n(); const route = useRoute(); /**路由标题 */ let title = ref((route.meta.title as string) ?? '标题'); -/**查询参数 */ -let queryParams = reactive({ - /**网元类型 */ - neType: [''], -}); - /**参数对象信息状态类型 */ type ParamStateType = { /**进入编辑视图 */ @@ -41,22 +46,8 @@ let paramState: ParamStateType = reactive({ visibleByEdit: false, visibleByUpdate: false, title: '参数设置', - newArea: `database: - type: mysql - user: root - password: "root@1234" - host: "192.168.2.170" - port: 3306 - name: omc_db - backup: d:/local.git/ems.agt/restagent/database`, - oldArea: `database: - type: mysql - user: root - password: "root@1234" - host: "192.168.2.170" - port: 3306 - name: omc_db - backup: d:/local.git/ems.agt/restagent/database`, + newArea: `database`, + oldArea: `dat database`, }); /** @@ -71,51 +62,995 @@ function fnModalVisible(type: 'edit' | 'update') { paramState.title = '比较参数'; paramState.visibleByUpdate = true; } -} +} + +/**网元类型选择 type,id */ +let neTypeSelect = ref(['', '']); /**tab标签栏类型 */ type TabStateType = { - /**标签项 */ - tabNames: Record[]; /**标签方向 */ tabPosition: TabPosition; - /**标签高度 */ - height: string; - /**标签选择后加载配置等待 */ - tabLoading: boolean; + /**标签项 */ + tabNames: Record[]; /**标签激活项 */ - tabActiveKey: number; + tabActiveTopTag: string; }; + +/**tab标签栏属性 */ let tabState: TabStateType = reactive({ - tabNames: [], tabPosition: 'top', - height: '800px', - tabLoading: true, - tabActiveKey: 1, + tabNames: [], + tabActiveTopTag: '', }); -/**查询网元类型 */ +/**tab标签栏标签点击监听 */ +function fnTabActiveTopTag(key: string | number) { + tableState.loading = true; + if (key !== '#') { + tabState.tabActiveTopTag = key as string; + } + + // 获取数据 + const neType = neTypeSelect.value[0]; + const neId = neTypeSelect.value[1]; + const topTag = tabState.tabActiveTopTag; + getParamConfigInfo(neType, topTag, neId) + .then(res => { + if (res.code === RESULT_CODE_SUCCESS && res.data.type) { + tableState.type = res.data.type; + if (res.data.type === 'list') { + tableState.listData = res.data.data; + tableState.listColumns = res.data.columns; + } + if (res.data.type === 'array') { + tableState.arrayData = res.data.data; + tableState.arrayDataRule = res.data.dataRule; + tableState.arrayColumns = res.data.columns; + tableState.arrayColumns.push({ + title: t('common.operate'), + key: 'index', + align: 'left', + }); + } + } else { + message.warning({ + content: `暂无配置项数据`, + duration: 3, + }); + } + }) + .finally(() => { + tableState.arrayNewIndex = -1; + tableState.editRecord = {}; + tableState.loading = false; + }); +} + +/**查询配置Tag标签 */ function fnGetParamConfigTopTab() { - if (!queryParams.neType || queryParams.neType.length != 2) { + const neType = neTypeSelect.value[0]; + if (!neType) { message.warning({ content: `请选择网元类型`, - duration: 2, + duration: 3, }); return; } - const neType = queryParams.neType[0]; + // 获取数据 getParamConfigTopTab(neType).then(res => { if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.data)) { tabState.tabNames = res.data; + // 取首个tag + if (res.data.length > 0) { + const topTag = res.data[0].topTag; + fnTabActiveTopTag(topTag); + } } else { message.warning({ content: `暂无配置项数据`, - duration: 2, + duration: 3, }); } }); } +/**表格状态类型 */ +type TabeStateType = { + /**加载等待 */ + loading: boolean; + /**紧凑型 */ + size: SizeType; + /**表格数据类型 单列还是多列 */ + type: string; + /**单列记录字段 */ + listColumns: object[]; + /**单列记录数据 */ + listData: object[]; + /**多列记录字段 */ + arrayColumns: object[]; + /**多列记录数据 */ + arrayData: object[]; + /**多列记录规则 */ + arrayDataRule: Record; + /**新增行记录Index */ + arrayNewIndex: number; + /**编辑行记录 */ + editRecord: Record; + /**多列嵌套列表标题 */ + arrayChildTitle: string; + /**多列嵌套层级index */ + arrayChildLoc: string; + /**多列嵌套记录字段 */ + arrayChildColumns: object[]; + /**多列嵌套记录数据 */ + arrayChildData: object[]; + /**多列嵌套记录规则 */ + arrayChildDataRule: Record; + /**多列嵌套展开key */ + arrayChildExpandKeys: any[]; + /**新增嵌套行记录Index */ + arrayChildNewIndex: number; + /**编辑嵌套行记录 */ + arrayChildEditRecord: Record; +}; + +/**表格状态 */ +let tableState: TabeStateType = reactive({ + loading: false, + size: 'middle', + type: 'list', + listColumns: [], + listData: [], + arrayColumns: [], + arrayData: [], + arrayDataRule: {}, + arrayNewIndex: -1, + editRecord: {}, + arrayChildTitle: '', + arrayChildLoc: '', + arrayChildColumns: [], + arrayChildData: [], + arrayChildDataRule: {}, + arrayChildExpandKeys: [], + arrayChildNewIndex: -1, + arrayChildEditRecord: {}, +}); + +/**单列表编辑 */ +function listEdit(row: Record) { + tableState.editRecord = Object.assign({}, row); +} + +/**单列表编辑关闭 */ +function listEditClose() { + tableState.editRecord = {}; +} + +/**单列表编辑确认 */ +function listEditOk() { + const from = toRaw(tableState.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'], + }; + // UPF参数不统一 + if (neTypeSelect.value[0] === 'UPF') { + data = { + [parseFirstUpper(from['name'])]: from['value'], + }; + } + + updateParamConfigInfo( + 'list', + { + neType: neTypeSelect.value[0], + neId: neTypeSelect.value[1], + topTag: tabState.tabActiveTopTag, + }, + data + ) + .then(res => { + if (res.code === RESULT_CODE_SUCCESS) { + message.success({ + content: `${from['display']} 属性值修改成功`, + duration: 3, + }); + // 改变表格数据 + const item = tableState.listData.filter( + (item: Record) => from['name'] === item['name'] + )[0]; + if (item) { + Object.assign(item, tableState.editRecord); + } + } else { + message.warning({ + content: `属性值修改失败`, + duration: 3, + }); + } + }) + .catch(err => { + console.error(err); + message.error({ + content: `非法操作属性值`, + duration: 3, + }); + }) + .finally(() => { + hide(); + tableState.editRecord = {}; + }); +} + +/**多列表编辑 */ +function arrayEdit(row: Record) { + tableState.editRecord = Object.assign({}, JSON.parse(JSON.stringify(row))); +} + +/**多列表编辑关闭 */ +function arrayEditClose() { + if (tableState.arrayNewIndex !== -1) { + tableState.arrayNewIndex = -1; + tableState.arrayData.pop(); + } + tableState.editRecord = {}; +} + +/**多列表编辑确认 */ +function arrayEditOk() { + const from = toRaw(tableState.editRecord); + const loc = from['index']['value']; + const neType = neTypeSelect.value[0]; + // 遍历提取属性和值 + 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; + } + // UPF参数不统一 + if (neType === 'UPF') { + data[parseFirstUpper(key)] = from[key]['value']; + } else { + data[key] = from[key]['value']; + } + data[key] = from[key]['value']; + } + + // 发送 + const hide = message.loading({ content: t('common.loading') }); + updateParamConfigInfo( + 'array', + { + neType: neType, + neId: neTypeSelect.value[1], + topTag: tabState.tabActiveTopTag, + loc, + }, + data + ) + .then(res => { + if (res.code === RESULT_CODE_SUCCESS) { + message.success({ + content: `Index 为 ${from['index']['value']} 记录修改成功`, + duration: 3, + }); + // 改变表格数据 + const item = tableState.arrayData.filter( + (item: Record) => + from['index']['value'] === item['index']['value'] + )[0]; + if (item) { + Object.assign(item, from); + } + } else { + message.warning({ + content: `记录修改失败`, + duration: 3, + }); + } + }) + .catch(err => { + console.error(err); + message.error({ + content: `非法操作记录参数`, + duration: 3, + }); + }) + .finally(() => { + hide(); + tableState.arrayNewIndex = -1; + tableState.editRecord = {}; + }); +} + +/**多列表删除单行 */ +function arrayDelete(row: Record) { + const from = toRaw(row); + const loc = from['index']['value']; + console.log(from, loc); + + Modal.confirm({ + title: '提示', + content: `确认删除Index为 【${from['index']['value']}】 的数据项?`, + onOk() { + const hide = message.loading({ content: t('common.loading') }); + delParamConfigInfo({ + neType: neTypeSelect.value[0], + neId: neTypeSelect.value[1], + topTag: tabState.tabActiveTopTag, + loc, + }) + .then(res => { + if (res.code === RESULT_CODE_SUCCESS) { + message.success({ + content: `删除成功`, + duration: 2, + }); + } else { + message.error({ + content: `${res.msg}`, + duration: 2, + }); + } + }) + .finally(() => { + fnTabActiveTopTag('#'); + hide(); + }); + }, + }); +} + +/**多列表新增单行 */ +function arrayAdd() { + const len = tableState.arrayData.length; + let lastItme = {}; + let newIndex = 0; + // 无数据时生成临时记录 + if (len === 0) { + lastItme = tableState.arrayDataRule; + } else { + lastItme = tableState.arrayData[len - 1]; + } + const from = Object.assign({}, JSON.parse(JSON.stringify(lastItme))); + for (const key in from) { + const row = from[key]; + if (key === 'index') { + if (from[key]['value'] !== '') { + newIndex = parseInt(from[key]['value']) + 1; + } + if (isNaN(newIndex)) { + newIndex = 0; + } + from[key]['value'] = newIndex; + tableState.arrayNewIndex = newIndex; + continue; + } + // 子嵌套的不初始 + if (row.array) { + from[key]['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]); + from[key]['value'] = minInt; + } else { + from[key]['value'] = 0; + } + break; + case 'enum': + if (filter && filter.indexOf('{') === 0) { + let filterJson: Record = {}; + try { + filterJson = JSON.parse(filter); //string---json + } catch (error) { + console.error(error); + } + + from[key]['value'] = Object.keys(filterJson)[0]; + } else { + from[key]['value'] = '0'; + } + break; + case 'bool': + if (filter && filter.indexOf('{') === 0) { + let filterJson: Record = {}; + try { + filterJson = JSON.parse(filter); //string---json + } catch (error) { + console.error(error); + } + + from[key]['value'] = Object.keys(filterJson)[0]; + } else { + from[key]['value'] = false; + } + break; + case 'ipv4': + case 'ipv6': + case 'regex': + default: + from[key]['value'] = ''; + } + } + + tableState.editRecord = from; + tableState.arrayData.push(from); +} + +/**多列表新增单行确认 */ +function arrayAddOk() { + const from = toRaw(tableState.editRecord); + const loc = from['index']['value']; + const neType = neTypeSelect.value[0]; + // 遍历提取属性和值 + 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; + } + // UPF参数不统一 + if (neType === 'UPF') { + data[parseFirstUpper(key)] = from[key]['value']; + } else { + data[key] = from[key]['value']; + } + // data[key] = from[key]['value']; + } + + // 发送 + const hide = message.loading({ content: t('common.loading') }); + addParamConfigInfo( + { + neType: neType, + neId: neTypeSelect.value[1], + topTag: tabState.tabActiveTopTag, + loc, + }, + data + ) + .then(res => { + if (res.code === RESULT_CODE_SUCCESS) { + message.success({ + content: `Index 为 ${from['index']['value']} 记录新增成功`, + duration: 3, + }); + } else { + tableState.arrayData.pop(); + message.warning({ + content: `新增失败`, + duration: 3, + }); + } + }) + .catch(err => { + console.error(err); + message.error({ + content: `非法操作记录参数`, + duration: 3, + }); + }) + .finally(() => { + hide(); + tableState.arrayNewIndex = -1; + tableState.editRecord = {}; + }); +} + +/**多列表展开嵌套行 */ +function arrayChildExpand(key: Record, row: Record) { + const loc = key['value']; + tableState.arrayChildExpandKeys = []; + tableState.arrayChildLoc = ''; + 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 = []; + for (const item of dataArr) { + let record: Record = {}; + for (const key of Object.keys(item)) { + // 规则为准 + for (const rule of ruleArr) { + if (rule['name'] === key) { + const ruleItem = Object.assign({}, rule, { value: item[key] }); + record[ruleItem.name] = ruleItem; + break; + } + } + } + dataArray.push(record); + } + // console.log(dataArray); + tableState.arrayChildData = dataArray; + + // 无数据时,需要临时数据用于新增 + if (dataArray.length === 0) { + let itemTemp: Record = {}; + for (const rule of ruleArr) { + itemTemp[rule.name] = rule; + } + tableState.arrayChildDataRule = itemTemp; + } + + // 列表字段 + const columns: Record[] = []; + for (const rule of ruleArr) { + columns.push({ + title: rule.display, + dataIndex: rule.name, + align: 'left', + }); + } + // console.log(columns); + tableState.arrayChildColumns = columns; + tableState.arrayChildColumns.push({ + title: t('common.operate'), + key: 'index', + align: 'left', + }); + + // 设置展开key + tableState.arrayChildExpandKeys = [key]; + // UPF参数不统一 + if (neTypeSelect.value[0] === 'UPF') { + tableState.arrayChildLoc = `${loc}/${parseFirstUpper(from['name'])}`; + } else { + tableState.arrayChildLoc = `${loc}/${from['name']}`; + } + // tableState.arrayChildLoc = `${loc}/${from['name']}`; + tableState.arrayChildNewIndex = -1; + // 设置展开列表标题 + tableState.arrayChildTitle = `${from['display']}`; +} + +/**多列表嵌套行编辑 */ +function arrayChildEdit(row: Record) { + tableState.arrayChildEditRecord = Object.assign( + {}, + JSON.parse(JSON.stringify(row)) + ); +} + +/**多列表嵌套行编辑关闭 */ +function arrayChildEditClose() { + if (tableState.arrayNewIndex !== -1) { + tableState.arrayChildNewIndex = -1; + tableState.arrayChildData.pop(); + } + tableState.arrayChildEditRecord = {}; +} + +/**多列表嵌套行编辑确认 */ +function arrayChildEditOk() { + const from = toRaw(tableState.arrayChildEditRecord); + const loc = `${tableState.arrayChildLoc}/${from['index']['value']}`; + const neType = neTypeSelect.value[0]; + + 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; + } + // UPF参数不统一 + if (neType === 'UPF') { + data[parseFirstUpper(key)] = from[key]['value']; + } else { + data[key] = from[key]['value']; + } + // data[key] = from[key]['value']; + } + + // 发送 + const hide = message.loading({ content: t('common.loading') }); + updateParamConfigInfo( + 'array', + { + neType: neType, + neId: neTypeSelect.value[1], + topTag: tabState.tabActiveTopTag, + loc, + }, + data + ) + .then(res => { + if (res.code === RESULT_CODE_SUCCESS) { + message.success({ + content: `Index 为 ${from['index']['value']} 记录修改成功`, + duration: 3, + }); + fnTabActiveTopTag('#'); + } else { + message.warning({ + content: `记录修改失败`, + duration: 3, + }); + } + }) + .catch(err => { + console.error(err); + message.error({ + content: `非法操作记录参数`, + duration: 3, + }); + }) + .finally(() => { + hide(); + tableState.arrayChildNewIndex = -1; + tableState.arrayChildEditRecord = {}; + }); +} + +/**多列表嵌套行删除单行 */ +function arrayChildDelete(row: Record) { + const from = toRaw(row); + const loc = `${tableState.arrayChildLoc}/${from['index']['value']}`; + console.log(from, loc); + + Modal.confirm({ + title: '提示', + content: `确认删除${tableState.arrayChildTitle} Index 为 【${from['index']['value']}】 的数据项?`, + onOk() { + const hide = message.loading({ content: t('common.loading') }); + delParamConfigInfo({ + neType: neTypeSelect.value[0], + neId: neTypeSelect.value[1], + topTag: tabState.tabActiveTopTag, + loc, + }) + .then(res => { + if (res.code === RESULT_CODE_SUCCESS) { + message.success({ + content: `删除成功`, + duration: 2, + }); + } else { + message.error({ + content: `${res.msg}`, + duration: 2, + }); + } + }) + .finally(() => { + fnTabActiveTopTag('#'); + hide(); + }); + }, + }); +} + +/**多列表嵌套行新增单行 */ +function arrayChildAdd() { + const len = tableState.arrayChildData.length; + let lastItme = {}; + let newIndex = 0; + // 无数据时生成临时记录 + if (len === 0) { + lastItme = tableState.arrayChildDataRule; + } else { + lastItme = tableState.arrayChildData[len - 1]; + } + const from = Object.assign({}, JSON.parse(JSON.stringify(lastItme))); + for (const key in from) { + const row = from[key]; + if (key === 'index') { + if (from[key]['value'] !== '') { + newIndex = parseInt(from[key]['value']) + 1; + } + if (isNaN(newIndex)) { + newIndex = 0; + } + from[key]['value'] = newIndex; + tableState.arrayChildNewIndex = newIndex; + continue; + } + // 子嵌套的不初始 + if (row.array) { + from[key]['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]); + from[key]['value'] = minInt; + } else { + from[key]['value'] = 0; + } + break; + case 'enum': + if (filter && filter.indexOf('{') === 0) { + let filterJson: Record = {}; + try { + filterJson = JSON.parse(filter); //string---json + } catch (error) { + console.error(error); + } + + from[key]['value'] = Object.keys(filterJson)[0]; + } else { + from[key]['value'] = '0'; + } + break; + case 'bool': + if (filter && filter.indexOf('{') === 0) { + let filterJson: Record = {}; + try { + filterJson = JSON.parse(filter); //string---json + } catch (error) { + console.error(error); + } + + from[key]['value'] = Object.keys(filterJson)[0]; + } else { + from[key]['value'] = false; + } + break; + case 'ipv4': + case 'ipv6': + case 'regex': + default: + from[key]['value'] = ''; + } + } + + tableState.arrayChildEditRecord = from; + tableState.arrayChildData.push(from); +} + +/**多列表新增单行确认 */ +function arrayChildAddOk() { + const from = toRaw(tableState.arrayChildEditRecord); + const loc = `${tableState.arrayChildLoc}/${from['index']['value']}`; + const neType = neTypeSelect.value[0]; + console.log(from, loc); + + 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; + } + // UPF参数不统一 + if (neType === 'UPF') { + data[parseFirstUpper(key)] = from[key]['value']; + } else { + data[key] = from[key]['value']; + } + // data[key] = from[key]['value']; + } + + // 发送 + const hide = message.loading({ content: t('common.loading') }); + addParamConfigInfo( + { + neType: neType, + neId: neTypeSelect.value[1], + topTag: tabState.tabActiveTopTag, + loc, + }, + data + ) + .then(res => { + if (res.code === RESULT_CODE_SUCCESS) { + message.success({ + content: `Index 为 ${from['index']['value']} 记录新增成功`, + duration: 3, + }); + fnTabActiveTopTag('#'); + } else { + tableState.arrayChildData.pop(); + message.warning({ + content: `新增失败`, + duration: 3, + }); + } + }) + .catch(err => { + console.error(err); + message.error({ + content: `非法操作记录参数`, + duration: 3, + }); + }) + .finally(() => { + hide(); + tableState.arrayChildNewIndex = -1; + tableState.arrayChildEditRecord = {}; + }); +} + +/**规则校验 */ +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; + } + + 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, `${display} 参数值不在合理范围 ${filter}`]; + } + } + break; + case 'ipv4': + if (!regExpIPv4.test(value)) { + return [false, `${display} 不是合法的IPV4地址`]; + } + break; + case 'ipv6': + if (!regExpIPv6.test(value)) { + return [false, `${display} 不是合法的IPV6地址`]; + } + 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, `${display} 不是合理的枚举值`]; + } + } + break; + case 'bool': + 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, `${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, `${display} 参数值不合理`]; + } + } catch (error) { + console.error(error); + } + } + + break; + case 'regex': + if (filter) { + try { + let regex = new RegExp(filter); + if (!regex.test(value)) { + return [false, `${display} 参数值不合理`]; + } + } catch (error) { + console.error(error); + } + } + break; + + default: + console.warn('未知类型', type); + return [false, `${display} 输入值是未知类型`]; + } + return result; +} + +/**网元重新加载状态 */ +let neReloadLoading = ref(false); + +/**网元重新加载 */ +function fnNeReload() { + // 获取数据 + const neType = neTypeSelect.value[0]; + const neId = neTypeSelect.value[1]; + neReloadLoading.value = true; + updateNeConfigReload(neType, neId) + .then(res => { + if (res.code === RESULT_CODE_SUCCESS) { + message.success({ + content: `网元重新加载完成`, + duration: 3, + }); + } else { + message.error({ + content: `网元重新加载失败`, + duration: 3, + }); + } + }) + .finally(() => { + neReloadLoading.value = false; + }); +} + onMounted(() => { // 获取网元网元列表 useNeInfoStore() @@ -124,7 +1059,7 @@ onMounted(() => { if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.data)) { if (res.data.length > 0) { const item = res.data[0]; - queryParams.neType = [item.neType, item.neId]; + neTypeSelect.value = [item.neType, item.neId]; fnGetParamConfigTopTab(); } } else { @@ -144,13 +1079,14 @@ onMounted(() => { :body-style="{ marginBottom: '24px', paddingBottom: 0 }" > - + - + @@ -163,7 +1099,7 @@ onMounted(() => { @click.prevent="fnGetParamConfigTopTab" > - {{ t('common.ok') }} + {{ t('common.search') }} @@ -176,58 +1112,517 @@ onMounted(() => { - - - - - + - - Content of tab {{ tab.topDisplay }} - + + + + + + + + + + + + + + + 修改 + + + + 提交 + + + + + +