-
+
{{ skimState.udmSubNum }}
- {{ t('views.dashboard.overview.skim.users') }}
+
+
+ {{ t('views.dashboard.overview.skim.users') }}
+
+
+
+
+
+ {{ v.label }}
+
+
+
+
{
.toDeep :deep(.ant-select-selection-item) {
color: #fff;
}
+
+.toDeep-text {
+ color: #4c9bfd !important;
+ font-size: 0.844rem !important;
+ position: relative !important;
+ line-height: 2rem !important;
+ white-space: nowrap !important;
+ text-align: start !important;
+ text-overflow: ellipsis !important;
+ overflow: hidden !important;
+}
From 1514e65df4bd253de4c0f53fd0a7933eddbeb629 Mon Sep 17 00:00:00 2001
From: TsMask <340112800@qq.com>
Date: Wed, 26 Mar 2025 16:32:26 +0800
Subject: [PATCH 11/54] =?UTF-8?q?fix:=20KPI=E6=80=BB=E8=A7=88=E8=B0=83?=
=?UTF-8?q?=E6=95=B4=E6=8C=87=E6=A0=87?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/views/perfManage/kpiOverView/index.vue | 54 +++++++++++++++-------
1 file changed, 37 insertions(+), 17 deletions(-)
diff --git a/src/views/perfManage/kpiOverView/index.vue b/src/views/perfManage/kpiOverView/index.vue
index 5c43a449..1788706f 100644
--- a/src/views/perfManage/kpiOverView/index.vue
+++ b/src/views/perfManage/kpiOverView/index.vue
@@ -42,7 +42,7 @@ interface ChartDataItem {
const tableLoading = ref(false);
const rangeLoading = ref(false);
//网元类型定义
-const ALL_NE_TYPES = ['AMF', 'SMF', 'UPF', 'MME', 'IMS', 'SMSC'] as const;
+const ALL_NE_TYPES = ['AMF', 'UPF', 'IMS'] as const;
type NeType = (typeof ALL_NE_TYPES)[number];
echarts.use([
@@ -119,12 +119,16 @@ const toggleRealtime = () => {
// 定义要筛选的指标 ID,按网元类型组织
const TARGET_KPI_IDS: Record = {
- AMF: ['AMF.02', 'AMF.03', 'AMF.A.07', 'AMF.A.08'],
- SMF: ['SMF.02', 'SMF.03', 'SMF.04', 'SMF.05'],
- UPF: ['UPF.03', 'UPF.04', 'UPF.05', 'UPF.06'],
- MME: ['MME.A.01', 'MME.A.02', 'MME.A.03'],
- IMS: ['SCSCF.01', 'SCSCF.02', 'SCSCF.05', 'SCSCF.06'],
- SMSC: ['SMSC.A.01', 'SMSC.A.02', 'SMSC.A.03'],
+ AMF: ['AMF.02', 'AMF.03'],
+ UPF: ['UPF.04', 'UPF.05'],
+ IMS: ['SCSCF.03', 'SCSCF.04', 'SCSCF.05', 'SCSCF.06', 'SCSCF.07', 'SCSCF.08'],
+
+ // AMF: ['AMF.02', 'AMF.03', 'AMF.A.07', 'AMF.A.08'],
+ // SMF: ['SMF.02', 'SMF.03', 'SMF.04', 'SMF.05'],
+ // UPF: ['UPF.03', 'UPF.04', 'UPF.05', 'UPF.06'],
+ // MME: ['MME.A.01', 'MME.A.02', 'MME.A.03'],
+ // IMS: ['SCSCF.01', 'SCSCF.02', 'SCSCF.05', 'SCSCF.06'],
+ // SMSC: ['SMSC.A.01', 'SMSC.A.02', 'SMSC.A.03'],
};
// 实时数据开关函数
@@ -186,13 +190,15 @@ const wsMessage = (res: Record) => {
return;
}
const { code, data } = res;
- if (code === RESULT_CODE_ERROR || !data?.groupId) return;
+ if (code === RESULT_CODE_ERROR || !data?.groupId) {
+ tableLoading.value = false;
+ return;
+ }
handleWebSocketMessage(data.data);
};
// 添加数据处理函数
const processChartData = (rawData: any[]) => {
const groupedData = new Map(); //数据按时间分组
-
rawData.forEach(item => {
//合并相同时间点的数据
const timeKey = item.timeGroup;
@@ -755,7 +761,22 @@ const kpiStats = ref([]);
// 添加一个计算函数来更新统计数据
const updateKpiStats = () => {
if (!chartData.value.length || !kpiColumns.value.length) {
- kpiStats.value = [];
+ kpiStats.value = selectedKPIs.value.map(kpiId => {
+ // 找到对应的KPI标题
+ let title = kpiId;
+ const kpi = kpiColumns.value.find(col => col.kpiId === kpiId);
+ if (kpi) {
+ title = kpi.title;
+ }
+ return {
+ kpiId: kpiId,
+ title: title,
+ max: 0,
+ min: 0,
+ avg: 0,
+ total: 0,
+ };
+ });
return;
}
kpiStats.value = selectedKPIs.value
@@ -983,6 +1004,7 @@ const tableRowConfig = computed(() => {
From d8778d2632798aac82e9951fc671c2fe8482a43b Mon Sep 17 00:00:00 2001
From: TsMask <340112800@qq.com>
Date: Wed, 26 Mar 2025 16:32:34 +0800
Subject: [PATCH 12/54] =?UTF-8?q?fix:=20KPI=E6=80=BB=E8=A7=88=E6=97=A0?=
=?UTF-8?q?=E6=95=B0=E6=8D=AE=E6=97=B6=E5=B1=95=E7=A4=BAtitle?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/views/perfManage/kpiCReport/index.vue | 87 ++++++++++++++++++-----
1 file changed, 70 insertions(+), 17 deletions(-)
diff --git a/src/views/perfManage/kpiCReport/index.vue b/src/views/perfManage/kpiCReport/index.vue
index dc43bdbd..d09a7b8a 100644
--- a/src/views/perfManage/kpiCReport/index.vue
+++ b/src/views/perfManage/kpiCReport/index.vue
@@ -240,27 +240,33 @@ const statsColumns: TableColumnType
[] = [
title: t('views.perfManage.kpiOverView.kpiName'),
dataIndex: 'title',
key: 'title',
- width: '65%',
- },
- {
- title: t('views.perfManage.kpiOverView.avgValue'),
- dataIndex: 'avg',
- key: 'avg',
- width: '24%',
- sortDirections: ['ascend', 'descend'],
},
+ // {
+ // title: t('views.perfManage.kpiOverView.totalValue'),
+ // dataIndex: 'total',
+ // key: 'total',
+ // width: '12%',
+ // sortDirections: ['ascend', 'descend'],
+ // },
+ // {
+ // title: t('views.perfManage.kpiOverView.avgValue'),
+ // dataIndex: 'avg',
+ // key: 'avg',
+ // width: '24%',
+ // sortDirections: ['ascend', 'descend'],
+ // },
{
title: t('views.perfManage.kpiOverView.maxValue'),
dataIndex: 'max',
key: 'max',
- width: '17%',
+ width: '200px',
sortDirections: ['ascend', 'descend'],
},
{
title: t('views.perfManage.kpiOverView.minValue'),
dataIndex: 'min',
key: 'min',
- width: '17%',
+ width: '200px',
sortDirections: ['ascend', 'descend'],
},
];
@@ -356,6 +362,7 @@ function fnGetListTitle() {
dataIndex: kpiValue,
align: 'left',
key: kpiValue,
+ unit: item[`unit`],
resizable: true,
width: 100,
minWidth: 150,
@@ -416,8 +423,8 @@ function fnGetList() {
duration: 2,
});
tableState.data = [];
- tableColumns.value = [];
- tableColumnsDnd.value = [];
+ // tableColumns.value = [];
+ // tableColumnsDnd.value = [];
kpiStats.value = []; //清空数据
fnRanderChartData();
return false;
@@ -448,16 +455,37 @@ function fnGetList() {
const total = Number(
values.reduce((sum, val) => sum + val, 0).toFixed(2)
);
-
// 计算平均值
const avg =
values.length > 0 ? Number((total / values.length).toFixed(2)) : 0;
kpiStats.value.push({
kpiId: columns.key,
title: columns.title,
+ unit: columns.unit,
max: values.length > 0 ? Math.max(...values) : 0,
min: values.length > 0 ? Math.min(...values) : 0,
avg,
+ total: total,
+ });
+ }
+ } else {
+ kpiStats.value = [];
+ for (const columns of tableColumns.value) {
+ if (
+ columns.key === 'neName' ||
+ columns.key === 'startIndex' ||
+ columns.key === 'timeGroup'
+ ) {
+ continue;
+ }
+ kpiStats.value.push({
+ kpiId: columns.key,
+ title: columns.title,
+ unit: columns.unit,
+ max: 0,
+ min: 0,
+ avg: 0,
+ total: 0,
});
}
}
@@ -606,7 +634,7 @@ function fnRanderChartData() {
for (const item of orgData) {
const keys = Object.keys(item);
- //console.log(keys,item);//
+ //console.log(keys,item);
for (const y of chartDataYSeriesData) {
for (const key of keys) {
if (y.key === key) {
@@ -744,6 +772,7 @@ function wsMessage(res: Record) {
// 添加一个变量来跟踪当前选中的行
const selectedRow = ref([]);
+const selectedUnit = ref(null);
// 添加处理行点击的方法
function handleRowClick(record: any) {
const index = selectedRow.value.indexOf(record.kpiId);
@@ -752,17 +781,33 @@ function handleRowClick(record: any) {
if (index > -1) {
selectedRow.value.splice(index, 1);
chartLegendSelected[record.title] = false;
+ // 如果取消选中的是最后一个,重置 selectedUnit
+ if (selectedRow.value.length === 0) {
+ selectedUnit.value = null;
+ }
} else {
+ // 检查单位是否一致
+ if (selectedUnit.value && selectedUnit.value !== record.unit) {
+ message.error(
+ `${t('views.perfManage.customTarget.unitSelect')} ${selectedUnit.value}`
+ );
+ return;
+ }
+
// 添加新的选中项
selectedRow.value.push(record.kpiId);
+ // 设置选中的单位
+ if (!selectedUnit.value) {
+ selectedUnit.value = record.unit;
+ }
+
// 如果只有一个选中项,重置为 false
if (selectedRow.value.length === 1) {
Object.keys(chartLegendSelected).forEach(key => {
chartLegendSelected[key] = false;
});
}
-
chartLegendSelected[record.title] = true;
}
@@ -928,6 +973,7 @@ onBeforeUnmount(() => {
v-model:value="state.neType"
:options="neCascaderOptions"
:allow-clear="false"
+ @change="fnGetListTitle()"
:placeholder="t('common.selectPlease')"
/>
@@ -1015,7 +1061,6 @@ onBeforeUnmount(() => {
@@ -1103,7 +1148,7 @@ onBeforeUnmount(() => {
From 0ff899b40b5ef637164782a7dc15803c201cd69f Mon Sep 17 00:00:00 2001
From: TsMask <340112800@qq.com>
Date: Wed, 26 Mar 2025 16:32:46 +0800
Subject: [PATCH 13/54] =?UTF-8?q?fix:=20=E9=85=8D=E7=BD=AE=E6=96=87?=
=?UTF-8?q?=E4=BB=B6config.js=E5=8F=98=E6=9B=B4?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
public/default/config.js | 6 ++++--
src/views/perfManage/goldTarget/index.vue | 1 -
2 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/public/default/config.js b/public/default/config.js
index 5c85eb72..7eeaca4c 100644
--- a/public/default/config.js
+++ b/public/default/config.js
@@ -13,14 +13,16 @@
// baseUrl = protocol://ip:port
// baseUrl = 'http://192.168.8.100:33030';
const protocol = window.location.protocol
+ let wsprotocol = "ws:"
const hostname = window.location.hostname
let host = `${hostname}:33030`;
if (protocol === 'https:') {
host = `${hostname}:33443`;
+ wsprotocol = "wss:"
}
// Service Address
sessionStorage.setItem('baseUrl', `${protocol}//${host}`);
// websocket Address
- sessionStorage.setItem('wsUrl', `ws://${host}`);
-})();
+ sessionStorage.setItem('wsUrl', `${wsprotocol}//${host}`);
+})();
\ No newline at end of file
diff --git a/src/views/perfManage/goldTarget/index.vue b/src/views/perfManage/goldTarget/index.vue
index 3a97da41..bf54e686 100644
--- a/src/views/perfManage/goldTarget/index.vue
+++ b/src/views/perfManage/goldTarget/index.vue
@@ -996,7 +996,6 @@ onBeforeUnmount(() => {
From cfc56ca4ea483c45ac7140bb3103cd3f5f06bbe0 Mon Sep 17 00:00:00 2001
From: TsMask <340112800@qq.com>
Date: Thu, 27 Mar 2025 15:54:51 +0800
Subject: [PATCH 14/54] =?UTF-8?q?fix:=20=E5=AF=86=E7=A0=81=E6=A0=A1?=
=?UTF-8?q?=E9=AA=8C=E6=A0=BC=E5=BC=8F=E7=94=B1=E5=90=8E=E7=AB=AF=E5=A4=84?=
=?UTF-8?q?=E7=90=86?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/i18n/locales/en-US.ts | 6 +++---
src/i18n/locales/zh-CN.ts | 6 +++---
src/utils/regular-utils.ts | 10 ++++++----
3 files changed, 12 insertions(+), 10 deletions(-)
diff --git a/src/i18n/locales/en-US.ts b/src/i18n/locales/en-US.ts
index 7f541799..0cd80c73 100644
--- a/src/i18n/locales/en-US.ts
+++ b/src/i18n/locales/en-US.ts
@@ -163,7 +163,7 @@ export default {
userNameReg: 'The account cannot start with a number and can contain uppercase and lowercase letters, numbers, and no less than 5 digits.',
userNamePlease: 'Please enter the correct login account',
userNameHit: 'Login account',
- passwordReg: 'The password should contain at least uppercase and lowercase letters, numbers, special symbols, and no less than 6 digits.',
+ passwordReg: 'Please enter the correct password format',
passwordPlease: 'Please enter the correct login password',
passwordHit: 'Login password',
passwordConfirmHit: 'Confirm login password',
@@ -295,7 +295,7 @@ export default {
oldPasswordTip: "The old password must not be empty and must be at least 6 digits long",
oldPasswordPleace: "Please enter the old password",
newPassword: "New Password",
- newPasswordTip: "Password contains at least upper and lower case letters, numbers, special symbols, and not less than 6 digits",
+ newPasswordTip: "Please enter the correct password format",
newPassworddPleace: "Please enter a new password",
confirmPassword: "Confirm new password",
confirmPasswordPleace: "Please confirm the new password",
@@ -1594,7 +1594,7 @@ export default {
loginTime: 'Login Time',
status: 'Status',
userNameTip:'The account number can only contain strings of uppercase letters, lowercase letters and numbers with a minimum length of 6 digits',
- passwdTip:'The password should contain at least uppercase and lowercase letters, numbers, special symbols, and no less than 6 digits',
+ passwdTip:'Please enter the correct password format',
nickNameTip:'Nicknames no less than 2 digits',
emailTip:'Please enter the correct email address',
phoneTip:'Please enter the correct phone number',
diff --git a/src/i18n/locales/zh-CN.ts b/src/i18n/locales/zh-CN.ts
index bdcd1688..5a75cc1a 100644
--- a/src/i18n/locales/zh-CN.ts
+++ b/src/i18n/locales/zh-CN.ts
@@ -163,7 +163,7 @@ export default {
userNameReg: '账号不能以数字开头,可包含大写小写字母,数字,且不少于5位',
userNamePlease: '请输入正确登录账号',
userNameHit: '登录账号',
- passwordReg: '密码至少包含大小写字母、数字、特殊符号,且不少于6位',
+ passwordReg: '请输入正确的密码格式',
passwordPlease: '请输入正确登录密码',
passwordHit: '登录密码',
passwordConfirmHit: '确认登录密码',
@@ -295,7 +295,7 @@ export default {
oldPasswordTip: "旧密码不能为空,且不少于6位",
oldPasswordPleace: "请输入旧密码",
newPassword: "新密码",
- newPasswordTip: "密码至少包含大小写字母、数字、特殊符号,且不少于6位",
+ newPasswordTip: "请输入正确的密码格式",
newPassworddPleace: "请输入新密码",
confirmPassword: "确认新密码",
confirmPasswordPleace: "请确认新密码",
@@ -1594,7 +1594,7 @@ export default {
loginTime: '登录时间',
status: '用户状态',
userNameTip:'账号只能包含大写字母、小写字母和数字的字符串,长度至少为6位',
- passwdTip:'密码至少包含大小写字母、数字、特殊符号,且不少于6位',
+ passwdTip:'请输入正确的密码格式',
nickNameTip:'昵称不少于2位',
emailTip:'请输入正确的邮箱地址',
phoneTip:'请输入正确的手机号码',
diff --git a/src/utils/regular-utils.ts b/src/utils/regular-utils.ts
index f04c447e..83f5b3fa 100644
--- a/src/utils/regular-utils.ts
+++ b/src/utils/regular-utils.ts
@@ -27,14 +27,15 @@ export const regExpUserName = /^[A-Za-z0-9]{6,}$/;
* 有效密码格式
*
* 密码至少包含大小写字母、数字、特殊符号,且不少于6位
+ * /^(?![A-Za-z0-9]+$)(?![a-z0-9\W]+$)(?![A-Za-z\W]+$)(?![A-Z0-9\W]+$)[a-zA-Z0-9\W]{6,}$/
*/
-export const regExpPasswd =
- /^(?![A-Za-z0-9]+$)(?![a-z0-9\W]+$)(?![A-Za-z\W]+$)(?![A-Z0-9\W]+$)[a-zA-Z0-9\W]{6,}$/;
+export const regExpPasswd = /^.{6,}$/;
/**
* 有效手机号格式
+ * /^1[3|4|5|6|7|8|9][0-9]\d{8}$/
*/
-export const regExpMobile = /^.{3,}$/; // /^1[3|4|5|6|7|8|9][0-9]\d{8}$/;
+export const regExpMobile = /^.{3,}$/;
/**
* 有效邮箱格式
@@ -46,8 +47,9 @@ export const regExpEmail =
* 有效用户昵称格式
*
* 用户昵称只能包含字母、数字、中文和下划线,且不少于2位
+ * /^[\w\u4e00-\u9fa5-]{2,}$/
*/
-export const regExpNick = /^.{2,}$/; // /^[\w\u4e00-\u9fa5-]{2,}$/;
+export const regExpNick = /^.{2,}$/;
/**
* 是否为http(s)://开头
From e4234dd1f44be7cc8f4d67a0145126af5692e75c Mon Sep 17 00:00:00 2001
From: TsMask <340112800@qq.com>
Date: Thu, 27 Mar 2025 15:57:37 +0800
Subject: [PATCH 15/54] =?UTF-8?q?fix:=20=E7=BB=88=E7=AB=AFredis=E8=BF=9E?=
=?UTF-8?q?=E6=8E=A5=E5=90=8E=E9=BB=98=E8=AE=A4=E5=8F=91=E9=80=81PING?=
=?UTF-8?q?=E7=A1=AE=E8=AE=A4=E6=98=AF=E5=90=A6=E8=BF=9E=E6=8E=A5?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/views/tool/terminal/index.vue | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/views/tool/terminal/index.vue b/src/views/tool/terminal/index.vue
index 7f4c18cb..01dfdb11 100644
--- a/src/views/tool/terminal/index.vue
+++ b/src/views/tool/terminal/index.vue
@@ -259,6 +259,7 @@ function fnTabClose(id: string) {
v-if="pane.id !== '0' && pane.host.hostType === 'redis'"
:id="pane.id"
:hostId="pane.host.id"
+ init-cmd="PING"
@connect="fnTerminalConnect"
@close="fnTerminalClose"
>
From 6093a234cc12c83eabb12e7b07fdb2121b2b7747 Mon Sep 17 00:00:00 2001
From: TsMask <340112800@qq.com>
Date: Mon, 31 Mar 2025 18:59:47 +0800
Subject: [PATCH 16/54] =?UTF-8?q?fix:=20=E4=BF=AE=E6=AD=A3=E8=A7=A3?=
=?UTF-8?q?=E9=94=81=E6=88=90=E5=8A=9F=E6=8F=90=E7=A4=BA=E4=B8=AD=E7=9A=84?=
=?UTF-8?q?=E6=8B=BC=E5=86=99=E9=94=99=E8=AF=AF?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/views/system/log/login/index.vue | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/views/system/log/login/index.vue b/src/views/system/log/login/index.vue
index a0cf877c..4527687c 100644
--- a/src/views/system/log/login/index.vue
+++ b/src/views/system/log/login/index.vue
@@ -272,7 +272,7 @@ function fnUnlock() {
hide();
if (res.code === RESULT_CODE_SUCCESS) {
message.success({
- content: t('views.system.log.login.unlockSure', {
+ content: t('views.system.log.login.unlockSuss', {
userName: username,
}),
duration: 3,
From c72f0290fd1bb5280efafc7a2764b67cd7eaa2e4 Mon Sep 17 00:00:00 2001
From: TsMask <340112800@qq.com>
Date: Mon, 31 Mar 2025 19:00:04 +0800
Subject: [PATCH 17/54] =?UTF-8?q?fix:=20=E4=BD=BF=E7=94=A8=E5=B8=B8?=
=?UTF-8?q?=E9=87=8F=E6=9B=BF=E4=BB=A3=E9=AA=8C=E8=AF=81=E7=A0=81=E6=88=90?=
=?UTF-8?q?=E5=8A=9F=E8=BF=94=E5=9B=9E=E7=A0=81=EF=BC=8C=E5=B9=B6=E6=B7=BB?=
=?UTF-8?q?=E5=8A=A0=E9=AA=8C=E8=AF=81=E7=A0=81=E6=96=87=E6=9C=AC=E5=A4=84?=
=?UTF-8?q?=E7=90=86?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/views/login.vue | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/src/views/login.vue b/src/views/login.vue
index b5ad5b90..18adece3 100644
--- a/src/views/login.vue
+++ b/src/views/login.vue
@@ -77,7 +77,7 @@ function fnGetCaptcha() {
state.captchaClick = true;
getCaptchaImage().then(res => {
state.captchaClick = false;
- if (res.code != 1) {
+ if (res.code != RESULT_CODE_SUCCESS) {
message.warning(`${res.msg}`, 3);
return;
}
@@ -85,6 +85,9 @@ function fnGetCaptcha() {
if (state.captcha.enabled) {
state.captcha.codeImg = res.img;
state.from.uuid = res.uuid;
+ if (res.text) {
+ state.from.code = res.text;
+ }
}
});
}
From d037a768560fa55104a465a1d335514803aaca42 Mon Sep 17 00:00:00 2001
From: TsMask <340112800@qq.com>
Date: Mon, 31 Mar 2025 19:00:34 +0800
Subject: [PATCH 18/54] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E5=BC=BA?=
=?UTF-8?q?=E5=88=B6=E5=AF=86=E7=A0=81=E9=87=8D=E7=BD=AE=E5=8A=9F=E8=83=BD?=
=?UTF-8?q?=E5=8F=8A=E7=9B=B8=E5=85=B3=E7=BB=84=E4=BB=B6?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/api/profile.ts | 13 ++
src/components/ForcePasswdChange/index.vue | 198 +++++++++++++++++++++
src/layouts/BasicLayout.vue | 3 +
src/store/modules/user.ts | 10 ++
4 files changed, 224 insertions(+)
create mode 100644 src/components/ForcePasswdChange/index.vue
diff --git a/src/api/profile.ts b/src/api/profile.ts
index 63295ed3..3e52e664 100644
--- a/src/api/profile.ts
+++ b/src/api/profile.ts
@@ -37,3 +37,16 @@ export function updateUserPassword(oldPassword: string, newPassword: string) {
data: { oldPassword, newPassword },
});
}
+
+/**
+ * 用户强制重置密码
+ * @param password 密码
+ * @returns object
+ */
+export function updateUserPasswordForce(password: string) {
+ return request({
+ url: '/system/user/profile/password-force',
+ method: 'PUT',
+ data: { password },
+ });
+}
diff --git a/src/components/ForcePasswdChange/index.vue b/src/components/ForcePasswdChange/index.vue
new file mode 100644
index 00000000..bd9c0ec4
--- /dev/null
+++ b/src/components/ForcePasswdChange/index.vue
@@ -0,0 +1,198 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('common.ok') }}
+
+
+
+
+
+
+
+ 1. {{ t('components.ForcePasswdChange.passwordPolicy') }}
+ {{
+ t(
+ 'components.ForcePasswdChange.passwordPolicyMsg',
+ modalState.passwordPolicy
+ )
+ }}
+
+
+ 2. {{ t('components.ForcePasswdChange.passwdExpire') }}
+ {{
+ t('components.ForcePasswdChange.passwdExpireMsg', {
+ expDay: (modalState.passwdExpire.expHours / 24).toFixed(2),
+ alertDay: (modalState.passwdExpire.alertHours / 24).toFixed(2),
+ })
+ }}
+
+
+
+
+
+
+
+
diff --git a/src/layouts/BasicLayout.vue b/src/layouts/BasicLayout.vue
index 2d5dddcc..f9bd2e0d 100644
--- a/src/layouts/BasicLayout.vue
+++ b/src/layouts/BasicLayout.vue
@@ -8,6 +8,7 @@ import {
import RightContent from './components/RightContent.vue';
import Tabs from './components/Tabs.vue';
import GlobalMask from '@/components/GlobalMask/index.vue';
+import ForcePasswdChange from '@/components/ForcePasswdChange/index.vue';
import { scriptUrl } from '@/assets/js/icon_font_8d5l8fzk5b87iudi';
import {
computed,
@@ -362,6 +363,8 @@ onUnmounted(() => {
+
+
diff --git a/src/store/modules/user.ts b/src/store/modules/user.ts
index 14a3011a..003ac7e9 100644
--- a/src/store/modules/user.ts
+++ b/src/store/modules/user.ts
@@ -9,6 +9,8 @@ import { parseUrlPath } from '@/plugins/file-static-url';
/**用户信息类型 */
type UserInfo = {
+ /**用户ID */
+ forcePasswdChange: boolean;
/**用户ID */
userId: string;
/**登录账号 */
@@ -33,6 +35,7 @@ type UserInfo = {
const useUserStore = defineStore('user', {
state: (): UserInfo => ({
+ forcePasswdChange: false,
userId: '',
userName: '',
roles: [],
@@ -104,6 +107,9 @@ const useUserStore = defineStore('user', {
if (res.code === RESULT_CODE_SUCCESS && res.data) {
const token = res.data[TOKEN_RESPONSE_FIELD];
setToken(token);
+ if (res.data?.forcePasswdChange) {
+ this.forcePasswdChange = true;
+ }
}
return res;
},
@@ -139,6 +145,10 @@ const useUserStore = defineStore('user', {
// }
// useLayoutStore().changeWaterMark(waterMarkContent);
useLayoutStore().changeWaterMark('');
+ // 强制修改密码
+ if (res.data?.forcePasswdChange) {
+ this.forcePasswdChange = true;
+ }
}
// 网络错误时退出登录状态
if (res.code === 0) {
From 45771aba1eadf60145112e3a1b49c45d56b49bf1 Mon Sep 17 00:00:00 2001
From: TsMask <340112800@qq.com>
Date: Mon, 31 Mar 2025 19:00:48 +0800
Subject: [PATCH 19/54] =?UTF-8?q?fix:=20=E5=9C=A8=E5=AF=86=E7=A0=81?=
=?UTF-8?q?=E9=87=8D=E7=BD=AE=E6=88=90=E5=8A=9F=E5=90=8E=E6=B7=BB=E5=8A=A0?=
=?UTF-8?q?=E7=94=A8=E6=88=B7=E7=99=BB=E5=87=BA=E5=8A=9F=E8=83=BD?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/views/account/components/reset-passwd.vue | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/views/account/components/reset-passwd.vue b/src/views/account/components/reset-passwd.vue
index 2d381cce..b17e3133 100644
--- a/src/views/account/components/reset-passwd.vue
+++ b/src/views/account/components/reset-passwd.vue
@@ -52,6 +52,7 @@ function fnFinish() {
updateUserPassword(state.form.oldPassword, state.form.confirmPassword)
.then(res => {
if (res.code === RESULT_CODE_SUCCESS) {
+ fnLogOut();
Modal.success({
title: t('common.tipTitle'),
content: t('views.account.settings.submitOkTip', {
@@ -59,7 +60,7 @@ function fnFinish() {
}),
okText: t('views.account.settings.submitOk'),
onOk() {
- fnLogOut().finally(() => router.push({ name: 'Login' }));
+ router.push({ name: 'Login' });
},
});
} else {
From 2c31da625dc35fba18ac738bbdd6aed31f073e41 Mon Sep 17 00:00:00 2001
From: TsMask <340112800@qq.com>
Date: Mon, 31 Mar 2025 19:01:16 +0800
Subject: [PATCH 20/54] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E5=BC=BA?=
=?UTF-8?q?=E5=88=B6=E5=AF=86=E7=A0=81=E4=BF=AE=E6=94=B9=E5=8A=9F=E8=83=BD?=
=?UTF-8?q?=E7=9A=84=E5=9B=BD=E9=99=85=E5=8C=96=E6=94=AF=E6=8C=81?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/i18n/locales/en-US.ts | 8 ++++++++
src/i18n/locales/zh-CN.ts | 8 ++++++++
2 files changed, 16 insertions(+)
diff --git a/src/i18n/locales/en-US.ts b/src/i18n/locales/en-US.ts
index 0cd80c73..073f468e 100644
--- a/src/i18n/locales/en-US.ts
+++ b/src/i18n/locales/en-US.ts
@@ -139,6 +139,14 @@ export default {
systemReset:'Resetting now, please wait...',
systemReset2:'Data information is being reset.',
},
+ ForcePasswdChange: {
+ title: 'Password Change',
+ desc: 'Instruction',
+ passwordPolicy: 'Password policy strength',
+ passwordPolicyMsg: 'At least {minLength} bits, containing at least {specialChars} special characters and at least {uppercase} uppercase and at least {lowercase} lowercase letters.',
+ passwdExpire: 'Password expiration date',
+ passwdExpireMsg: 'Valid for {expDay} days, please change your password {alertDay} days before expiration.',
+ },
},
// 静态路由
diff --git a/src/i18n/locales/zh-CN.ts b/src/i18n/locales/zh-CN.ts
index 5a75cc1a..361767c3 100644
--- a/src/i18n/locales/zh-CN.ts
+++ b/src/i18n/locales/zh-CN.ts
@@ -139,6 +139,14 @@ export default {
systemReset:'正在重置,请稍等...',
systemReset2:'数据信息正在重置',
},
+ ForcePasswdChange: {
+ title: '密码修改',
+ desc: '说明',
+ passwordPolicy: '密码策略强度',
+ passwordPolicyMsg: '至少{minLength}位,至少包含{specialChars}个特殊字符和至少{uppercase}大写字母和至少{lowercase}小写字母',
+ passwdExpire: '密码有效期',
+ passwdExpireMsg: '有效期为{expDay}天,请在过期前{alertDay}天进行密码修改',
+ },
},
// 静态路由
From e10a6b5202a3a93b34bc6697dd59f5d5a6beb757 Mon Sep 17 00:00:00 2001
From: TsMask <340112800@qq.com>
Date: Mon, 31 Mar 2025 19:01:50 +0800
Subject: [PATCH 21/54] =?UTF-8?q?chore:=20=E6=9B=B4=E6=96=B0=E7=89=88?=
=?UTF-8?q?=E6=9C=AC=E5=8F=B7=202.250321?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.env.development | 2 +-
.env.production | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/.env.development b/.env.development
index 90fc9249..7cc34569 100644
--- a/.env.development
+++ b/.env.development
@@ -11,7 +11,7 @@ VITE_APP_NAME = "Core Network OMC"
VITE_APP_CODE = "OMC"
# 应用版本
-VITE_APP_VERSION = "2.250321"
+VITE_APP_VERSION = "2.250331"
# 接口基础URL地址-不带/后缀
VITE_API_BASE_URL = "/omc-api"
diff --git a/.env.production b/.env.production
index 90fc9249..7cc34569 100644
--- a/.env.production
+++ b/.env.production
@@ -11,7 +11,7 @@ VITE_APP_NAME = "Core Network OMC"
VITE_APP_CODE = "OMC"
# 应用版本
-VITE_APP_VERSION = "2.250321"
+VITE_APP_VERSION = "2.250331"
# 接口基础URL地址-不带/后缀
VITE_API_BASE_URL = "/omc-api"
From 7973b179afdb095bbb1df56a906ac0588bb25d32 Mon Sep 17 00:00:00 2001
From: TsMask <340112800@qq.com>
Date: Tue, 1 Apr 2025 17:34:27 +0800
Subject: [PATCH 22/54] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E5=AF=86?=
=?UTF-8?q?=E7=A0=81=E8=BF=87=E6=9C=9F=E5=8A=9F=E8=83=BD=E6=94=AF=E6=8C=81?=
=?UTF-8?q?=EF=BC=8C=E5=AF=86=E7=A0=81=E6=9C=89=E6=95=88=E6=9C=9F=E6=97=B6?=
=?UTF-8?q?=E9=97=B4=E5=A4=A9?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/components/ForcePasswdChange/index.vue | 35 +++++++++++++++++-----
1 file changed, 28 insertions(+), 7 deletions(-)
diff --git a/src/components/ForcePasswdChange/index.vue b/src/components/ForcePasswdChange/index.vue
index bd9c0ec4..52d65f2f 100644
--- a/src/components/ForcePasswdChange/index.vue
+++ b/src/components/ForcePasswdChange/index.vue
@@ -23,6 +23,7 @@ type ModalStateType = {
/**密码策略 */
passwordPolicy: Record
;
/**密码有效期 */
+ passwdExpireEnable: boolean;
passwdExpire: Record;
};
@@ -37,6 +38,7 @@ let modalState: ModalStateType = reactive({
},
confirmLoading: false,
passwordPolicy: { minLength: 8, specialChars: 2, uppercase: 1, lowercase: 1 },
+ passwdExpireEnable: false,
passwdExpire: { expHours: 2, alertHours: 1 },
});
@@ -74,6 +76,7 @@ function fnModalOk() {
updateUserPasswordForce(password).then(res => {
if (res.code === RESULT_CODE_SUCCESS) {
userStore.fnLogOut();
+ modalState.confirmLoading = true;
Modal.success({
title: t('common.tipTitle'),
content: t('views.account.settings.submitOkTip', {
@@ -108,7 +111,20 @@ onMounted(() => {
}
if (resArr[1].code === RESULT_CODE_SUCCESS) {
try {
- modalState.passwdExpire = JSON.parse(resArr[1].data);
+ const data = JSON.parse(resArr[1].data);
+ if (data.expHours % 24 === 0) {
+ data.expHours = data.expHours / 24;
+ } else {
+ data.expHours = (data.expHours / 24).toFixed(2);
+ }
+ if (data.alertHours % 24 === 0) {
+ data.alertHours = data.alertHours / 24;
+ } else {
+ data.alertHours = (data.alertHours / 24).toFixed(2);
+ }
+ console.log(data);
+ modalState.passwdExpire = data;
+ modalState.passwdExpireEnable = data.expHours > 0;
} catch (error) {
console.error('passwdExpire', error);
}
@@ -155,6 +171,7 @@ onUnmounted(() => {});
>
@@ -163,7 +180,11 @@ onUnmounted(() => {});
-
+
{{ t('common.ok') }}
@@ -172,7 +193,7 @@ onUnmounted(() => {});
- 1. {{ t('components.ForcePasswdChange.passwordPolicy') }}
+ {{ t('components.ForcePasswdChange.passwordPolicy') }}
{{
t(
'components.ForcePasswdChange.passwordPolicyMsg',
@@ -180,12 +201,12 @@ onUnmounted(() => {});
)
}}
-
- 2. {{ t('components.ForcePasswdChange.passwdExpire') }}
+
+ {{ t('components.ForcePasswdChange.passwdExpire') }}
{{
t('components.ForcePasswdChange.passwdExpireMsg', {
- expDay: (modalState.passwdExpire.expHours / 24).toFixed(2),
- alertDay: (modalState.passwdExpire.alertHours / 24).toFixed(2),
+ expDay: modalState.passwdExpire.expHours,
+ alertDay: modalState.passwdExpire.alertHours,
})
}}
From 5b6520ef5e803a8286309fe8b491ae3669782532 Mon Sep 17 00:00:00 2001
From: TsMask <340112800@qq.com>
Date: Thu, 10 Apr 2025 20:34:15 +0800
Subject: [PATCH 23/54] =?UTF-8?q?fix:=20=E7=BD=91=E5=85=83=E6=8E=88?=
=?UTF-8?q?=E6=9D=83=E4=B8=8A=E4=BC=A0=E5=90=8E=E7=82=B9=E5=87=BBok?=
=?UTF-8?q?=E6=A3=80=E6=9F=A5=E7=8A=B6=E6=80=81?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/views/ne/neHost/index.vue | 1 -
.../ne/neLicense/components/EditModal.vue | 1 -
src/views/ne/neLicense/index.vue | 24 ++++++++++++++++---
3 files changed, 21 insertions(+), 5 deletions(-)
diff --git a/src/views/ne/neHost/index.vue b/src/views/ne/neHost/index.vue
index 19847a52..607904cf 100644
--- a/src/views/ne/neHost/index.vue
+++ b/src/views/ne/neHost/index.vue
@@ -10,7 +10,6 @@ import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
import { delNeHost, listNeHost } from '@/api/ne/neHost';
import useDictStore from '@/store/modules/dict';
import useI18n from '@/hooks/useI18n';
-import { number } from 'echarts';
const { getDict } = useDictStore();
const { t } = useI18n();
const EditModal = defineAsyncComponent(
diff --git a/src/views/ne/neLicense/components/EditModal.vue b/src/views/ne/neLicense/components/EditModal.vue
index c1e8af42..768f0cea 100644
--- a/src/views/ne/neLicense/components/EditModal.vue
+++ b/src/views/ne/neLicense/components/EditModal.vue
@@ -14,7 +14,6 @@ import { FileType } from 'ant-design-vue/es/upload/interface';
import { uploadFile } from '@/api/tool/file';
import { useClipboard } from '@vueuse/core';
import saveAs from 'file-saver';
-import { number } from 'echarts';
const { copy } = useClipboard({ legacy: true });
const { t } = useI18n();
const emit = defineEmits(['ok', 'cancel', 'update:open']);
diff --git a/src/views/ne/neLicense/index.vue b/src/views/ne/neLicense/index.vue
index 70f0f148..9876d314 100644
--- a/src/views/ne/neLicense/index.vue
+++ b/src/views/ne/neLicense/index.vue
@@ -186,10 +186,10 @@ function fnGetList(pageNum?: number) {
queryParams.pageNum = pageNum;
}
listNeLicense(toRaw(queryParams)).then(res => {
- if (res.code === RESULT_CODE_SUCCESS) {
+ if (res.code === RESULT_CODE_SUCCESS) {
const { total, rows } = res.data;
tablePagination.total = total;
- tableState.data = rows.filter((s:any) => s.neType !== 'OMC');
+ tableState.data = rows.filter((s: any) => s.neType !== 'OMC');
if (
tablePagination.total <=
(queryParams.pageNum - 1) * tablePagination.pageSize &&
@@ -236,9 +236,27 @@ function fnModalVisibleByEdit(licenseId: number) {
* 对话框弹出确认执行函数
* 进行表达规则校验
*/
-function fnModalOk() {
+function fnModalOk(e: any) {
// 获取列表数据
fnGetList();
+ // 获取当前行数据
+ const item = tableState.data.find(
+ (item: any) => e.neType === item.neType && e.neId === item.neId
+ );
+ if (item) {
+ stateNeLicense(e.neType, e.neId).then(res => {
+ const row = tableState.data.find(
+ (item: any) => e.neType === item.neType && e.neId === item.neId
+ );
+ if (res.code === RESULT_CODE_SUCCESS) {
+ row.status = '1';
+ row.serialNum = res.data.sn;
+ row.expiryDate = res.data.expire;
+ } else {
+ row.status = '0';
+ }
+ });
+ }
}
/**
From c926da4f2e7a617bba99af3c2c480507702b10be Mon Sep 17 00:00:00 2001
From: TsMask <340112800@qq.com>
Date: Thu, 10 Apr 2025 21:00:17 +0800
Subject: [PATCH 24/54] =?UTF-8?q?feat:=20UE=E6=B7=BB=E5=8A=A0=E5=AF=BC?=
=?UTF-8?q?=E5=85=A5=E6=A8=A1=E6=9D=BF=E4=B8=8B=E8=BD=BD=E5=8A=9F=E8=83=BD?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
public/neDataImput/pcf_template.txt | 2 ++
public/neDataImput/udm_auth_template.txt | 2 ++
public/neDataImput/udm_sub_template.txt | 2 ++
src/i18n/locales/en-US.ts | 3 ++
src/i18n/locales/zh-CN.ts | 3 ++
src/views/neUser/auth/index.vue | 43 +++++++++++++++++++++---
src/views/neUser/pcf/index.vue | 32 ++++++++++++++++++
src/views/neUser/sub/index.vue | 34 ++++++++++++++++++-
8 files changed, 115 insertions(+), 6 deletions(-)
create mode 100644 public/neDataImput/pcf_template.txt
create mode 100644 public/neDataImput/udm_auth_template.txt
create mode 100644 public/neDataImput/udm_sub_template.txt
diff --git a/public/neDataImput/pcf_template.txt b/public/neDataImput/pcf_template.txt
new file mode 100644
index 00000000..1935f253
--- /dev/null
+++ b/public/neDataImput/pcf_template.txt
@@ -0,0 +1,2 @@
+imsi,msisdn,sess_rules,pcc_rules,hdr_enrich,rfsp,sar,qos_audio,qos_video,online,offline
+460996650000580,86755900103,internet|ims_sig,internet|ims_sig,dnn,1,def_sar,qos_audio,qos_video,0,0
diff --git a/public/neDataImput/udm_auth_template.txt b/public/neDataImput/udm_auth_template.txt
new file mode 100644
index 00000000..1a2ba5d3
--- /dev/null
+++ b/public/neDataImput/udm_auth_template.txt
@@ -0,0 +1,2 @@
+460996650000580,1234567890ABCDEF1234567890ABCDEF,0,8000
+460996650000581,1234567890ABCDEF1234567890ABCDEF,0,8000
diff --git a/public/neDataImput/udm_sub_template.txt b/public/neDataImput/udm_sub_template.txt
new file mode 100644
index 00000000..b9762168
--- /dev/null
+++ b/public/neDataImput/udm_sub_template.txt
@@ -0,0 +1,2 @@
+460996650000580,62357000583,def_ambr,def_nssai,def_arfb,def_sar,0,3,def_snssai,1-000001&content&ims,1,64,24,65,def_eps,1,010200000000,-
+460996650000581,62357000585,def_ambr,def_nssai,def_arfb,def_sar,0,3,def_snssai,1-000001&content&ims,1,64,24,65,def_eps,1,010200000000,-
diff --git a/src/i18n/locales/en-US.ts b/src/i18n/locales/en-US.ts
index 073f468e..6d2257f6 100644
--- a/src/i18n/locales/en-US.ts
+++ b/src/i18n/locales/en-US.ts
@@ -716,6 +716,9 @@ export default {
},
},
neData: {
+ common: {
+ importTemplate: 'Download Template',
+ },
baseStation: {
list: "List",
topology: "Topology",
diff --git a/src/i18n/locales/zh-CN.ts b/src/i18n/locales/zh-CN.ts
index 361767c3..37d5808e 100644
--- a/src/i18n/locales/zh-CN.ts
+++ b/src/i18n/locales/zh-CN.ts
@@ -716,6 +716,9 @@ export default {
},
},
neData: {
+ common: {
+ importTemplate: '导入模板',
+ },
baseStation: {
list: "列表",
topology: "拓扑图",
diff --git a/src/views/neUser/auth/index.vue b/src/views/neUser/auth/index.vue
index 9bf360fe..2e14e3a1 100644
--- a/src/views/neUser/auth/index.vue
+++ b/src/views/neUser/auth/index.vue
@@ -717,6 +717,26 @@ function fnModalUploadImportUpload(file: File) {
});
}
+/**对话框表格信息导入模板 */
+function fnModalDownloadImportTemplate() {
+ const hide = message.loading(t('common.loading'), 0);
+
+ const baseUrl = import.meta.env.VITE_HISTORY_BASE_URL;
+ const templateUrl = `${
+ baseUrl.length === 1 && baseUrl.indexOf('/') === 0
+ ? ''
+ : baseUrl.indexOf('/') === -1
+ ? '/' + baseUrl
+ : baseUrl
+ }/neDataImput`;
+ saveAs(
+ `${templateUrl}/udm_auth_template.txt`,
+ `import_udmauth_template_${Date.now()}.txt`
+ );
+
+ hide();
+}
+
onMounted(() => {
// 获取网元网元列表
useNeInfoStore()
@@ -1230,11 +1250,24 @@ onMounted(() => {
:size="10"
>
-
+
+
+
+
+
+
+ {{ t('views.neData.common.importTemplate') }}
+
+
+
= 0;
}
+/**对话框表格信息导入模板 */
+function fnModalDownloadImportTemplate() {
+ const hide = message.loading(t('common.loading'), 0);
+
+ const baseUrl = import.meta.env.VITE_HISTORY_BASE_URL;
+ const templateUrl = `${
+ baseUrl.length === 1 && baseUrl.indexOf('/') === 0
+ ? ''
+ : baseUrl.indexOf('/') === -1
+ ? '/' + baseUrl
+ : baseUrl
+ }/neDataImput`;
+ saveAs(
+ `${templateUrl}/pcf_template.txt`,
+ `import_pcfrule_template_${Date.now()}.txt`
+ );
+
+ hide();
+}
+
onMounted(() => {
// 获取网元网元列表
useNeInfoStore()
@@ -1158,6 +1178,18 @@ onMounted(() => {
:ext="['.txt']"
>
+
+
+
+
+ {{ t('views.neData.common.importTemplate') }}
+
+
+
{
- if (res.code === RESULT_CODE_SUCCESS) {
+ if (res.code === RESULT_CODE_SUCCESS) {
// 取消勾选
if (tableState.selectedRowKeys.length > 0) {
tableState.selectedRowKeys = [];
@@ -1108,6 +1108,26 @@ function delBigRow(bigIndex: any) {
bigRows.value.splice(bigIndex, 1);
}
+/**对话框表格信息导入模板 */
+async function fnModalDownloadImportTemplate() {
+ const hide = message.loading(t('common.loading'), 0);
+
+ const baseUrl = import.meta.env.VITE_HISTORY_BASE_URL;
+ const templateUrl = `${
+ baseUrl.length === 1 && baseUrl.indexOf('/') === 0
+ ? ''
+ : baseUrl.indexOf('/') === -1
+ ? '/' + baseUrl
+ : baseUrl
+ }/neDataImput`;
+ saveAs(
+ `${templateUrl}/udm_sub_template.txt`,
+ `import_udmsub_template_${Date.now()}.txt`
+ );
+
+ hide();
+}
+
onMounted(() => {
// 获取网元网元列表
useNeInfoStore()
@@ -2107,6 +2127,18 @@ onMounted(() => {
:size="10"
>
+
+
+
+
+ {{ t('views.neData.common.importTemplate') }}
+
+
+
Date: Thu, 10 Apr 2025 21:01:35 +0800
Subject: [PATCH 25/54] =?UTF-8?q?fix:=20mml=E8=A1=A5=E5=85=85UDM=E7=89=B9?=
=?UTF-8?q?=E6=AE=8A=E5=91=BD=E4=BB=A4=E5=A4=84=E7=90=86?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/views/mmlManage/neOperate/index.vue | 4 ++--
src/views/mmlManage/omcOperate/index.vue | 4 ++--
src/views/mmlManage/udmOperate/index.vue | 4 ++--
3 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/src/views/mmlManage/neOperate/index.vue b/src/views/mmlManage/neOperate/index.vue
index b09077b2..611fada7 100644
--- a/src/views/mmlManage/neOperate/index.vue
+++ b/src/views/mmlManage/neOperate/index.vue
@@ -181,9 +181,9 @@ function fnSendMML() {
if (res.code === RESULT_CODE_SUCCESS) {
let resultArr = res.data;
for (let i = 0; i < resultArr.length; i++) {
- const str = resultArr[i];
+ const str = resultArr[i] || '';
const logStr = str.replace(/(\r\n|\n)/g, '\n');
- const cmdStr = cmdArr[i];
+ const cmdStr = cmdArr[i] || '';
state.mmlCmdLog += `${cmdStr}\n${logStr}\n`;
}
} else {
diff --git a/src/views/mmlManage/omcOperate/index.vue b/src/views/mmlManage/omcOperate/index.vue
index 7f094110..6741f289 100644
--- a/src/views/mmlManage/omcOperate/index.vue
+++ b/src/views/mmlManage/omcOperate/index.vue
@@ -183,9 +183,9 @@ function fnSendMML() {
if (res.code === RESULT_CODE_SUCCESS) {
let resultArr = res.data;
for (let i = 0; i < resultArr.length; i++) {
- const str = resultArr[i];
+ const str = resultArr[i] || '';
const logStr = str.replace(/(\r\n|\n)/g, '\n');
- const cmdStr = cmdArr[i];
+ const cmdStr = cmdArr[i] || '';
state.mmlCmdLog += `${cmdStr}\n${logStr}\n`;
}
} else {
diff --git a/src/views/mmlManage/udmOperate/index.vue b/src/views/mmlManage/udmOperate/index.vue
index 25645ed1..3070e3de 100644
--- a/src/views/mmlManage/udmOperate/index.vue
+++ b/src/views/mmlManage/udmOperate/index.vue
@@ -183,9 +183,9 @@ function fnSendMML() {
if (res.code === RESULT_CODE_SUCCESS) {
let resultArr = res.data;
for (let i = 0; i < resultArr.length; i++) {
- const str = resultArr[i];
+ const str = resultArr[i] || '';
const logStr = str.replace(/(\r\n|\n)/g, '\n');
- const cmdStr = cmdArr[i];
+ const cmdStr = cmdArr[i] || '';
state.mmlCmdLog += `${cmdStr}\n${logStr}\n`;
}
} else {
From fc233c38ea886ce22360c3515c7c0af613191345 Mon Sep 17 00:00:00 2001
From: TsMask <340112800@qq.com>
Date: Thu, 10 Apr 2025 21:07:29 +0800
Subject: [PATCH 26/54] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E7=BD=91?=
=?UTF-8?q?=E5=85=83=E9=85=8D=E7=BD=AE=E6=96=87=E4=BB=B6=E5=A4=87=E4=BB=BD?=
=?UTF-8?q?=E7=9A=84FTP=E9=85=8D=E7=BD=AE=E7=AE=A1=E7=90=86=E5=8A=9F?=
=?UTF-8?q?=E8=83=BD?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/api/ne/neConfigBackup.ts | 44 ++++-
src/views/ne/neConfigBackup/index.vue | 251 ++++++++++++++++++++++++--
2 files changed, 279 insertions(+), 16 deletions(-)
diff --git a/src/api/ne/neConfigBackup.ts b/src/api/ne/neConfigBackup.ts
index 56e12ec0..e6b8c817 100644
--- a/src/api/ne/neConfigBackup.ts
+++ b/src/api/ne/neConfigBackup.ts
@@ -1,4 +1,6 @@
+import { CACHE_SESSION_CRYPTO_API } from '@/constants/cache-keys-constants';
import { request } from '@/plugins/http-fetch';
+import { sessionGet } from '@/utils/cache-session-utils';
/**
* 网元配置文件备份记录列表
@@ -80,4 +82,44 @@ export function importNeConfigBackup(data: Record) {
method: 'POST',
data: data,
});
-}
\ No newline at end of file
+}
+
+/**
+ * 更新FTP信息
+ * @param data 数据
+ * @returns object
+ */
+export function updateFTPInfo(data: Record) {
+ return request({
+ url: `/ne/config/backup/ftp`,
+ method: 'POST',
+ data: data,
+ crypto: sessionGet(CACHE_SESSION_CRYPTO_API) !== 'false',
+ });
+}
+
+/**
+ * 获取FTP信息
+ * @param data 数据
+ * @returns object
+ */
+export function getFTPInfo() {
+ return request({
+ url: `/ne/config/backup/ftp`,
+ method: 'GET',
+ crypto: sessionGet(CACHE_SESSION_CRYPTO_API) !== 'false',
+ });
+}
+
+/**
+ * 发送FTP文件
+ * @param data 数据
+ * @returns object
+ */
+export function putFTPInfo(path: string) {
+ return request({
+ url: `/ne/config/backup/ftp`,
+ method: 'PUT',
+ data: { path },
+ });
+}
diff --git a/src/views/ne/neConfigBackup/index.vue b/src/views/ne/neConfigBackup/index.vue
index 66cd6865..3cd1e855 100644
--- a/src/views/ne/neConfigBackup/index.vue
+++ b/src/views/ne/neConfigBackup/index.vue
@@ -11,11 +11,15 @@ import useDictStore from '@/store/modules/dict';
import { NE_TYPE_LIST } from '@/constants/ne-constants';
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
import { parseDateToStr } from '@/utils/date-utils';
+import { regExpIPv4 } from '@/utils/regular-utils';
import {
delNeConfigBackup,
downNeConfigBackup,
listNeConfigBackup,
updateNeConfigBackup,
+ getFTPInfo,
+ putFTPInfo,
+ updateFTPInfo,
} from '@/api/ne/neConfigBackup';
import saveAs from 'file-saver';
const { t } = useI18n();
@@ -58,8 +62,6 @@ type TabeStateType = {
loading: boolean;
/**紧凑型 */
size: SizeType;
- /**搜索栏 */
- seached: boolean;
/**记录数据 */
data: any[];
/**勾选记录 */
@@ -70,7 +72,6 @@ type TabeStateType = {
let tableState: TabeStateType = reactive({
loading: false,
size: 'middle',
- seached: false,
data: [],
selectedRowKeys: [],
});
@@ -98,12 +99,12 @@ let tableColumns = ref([
{
title: t('common.createTime'),
dataIndex: 'createTime',
- align: 'center',
+ align: 'left',
customRender(opt) {
if (!opt.value) return '';
return parseDateToStr(opt.value);
},
- width: 150,
+ width: 200,
},
{
title: t('views.ne.neConfigBackup.name'),
@@ -179,7 +180,7 @@ function fnGetList(pageNum?: number) {
queryParams.pageNum = pageNum;
}
listNeConfigBackup(toRaw(queryParams)).then(res => {
- if (res.code === RESULT_CODE_SUCCESS) {
+ if (res.code === RESULT_CODE_SUCCESS) {
const { total, rows } = res.data;
tablePagination.total = total;
tableState.data = rows;
@@ -387,12 +388,125 @@ onMounted(() => {
fnGetList();
});
});
+
+/**FTP日志对象信息状态 */
+let modalStateFTP: ModalStateType = reactive({
+ openByEdit: false,
+ title: '设置远程备份配置',
+ from: {
+ username: '',
+ password: '',
+ toIp: '',
+ toPort: 22,
+ enable: false,
+ dir: '',
+ },
+ confirmLoading: false,
+});
+
+/**FTP日志对象信息内表单属性和校验规则 */
+const modalStateFTPFrom = Form.useForm(
+ modalStateFTP.from,
+ reactive({
+ toIp: [
+ {
+ required: true,
+ pattern: regExpIPv4,
+ message: 'Please enter the service login IP',
+ },
+ ],
+ username: [
+ {
+ required: true,
+ trigger: 'blur',
+ message: 'Please enter the service login user name',
+ },
+ ],
+ dir: [
+ {
+ required: true,
+ trigger: 'blur',
+ message: 'Please enter the service address target file directory',
+ },
+ ],
+ })
+);
+
+/**
+ * 对话框弹出显示为 新增或者修改
+ * @param configId 参数编号id, 不传为新增
+ */
+function fnModalFTPVisibleByEdit() {
+ if (modalStateFTP.confirmLoading) return;
+ const hide = message.loading(t('common.loading'), 0);
+ modalStateFTP.confirmLoading = true;
+ getFTPInfo().then(res => {
+ modalStateFTP.confirmLoading = false;
+ hide();
+ if (res.code === RESULT_CODE_SUCCESS && res.data) {
+ modalStateFTP.from = Object.assign(modalStateFTP.from, res.data);
+ modalStateFTP.title = 'Setting Remote Backup';
+ modalStateFTP.openByEdit = true;
+ } else {
+ message.error(res.msg, 3);
+ modalStateFTP.title = 'Setting Remote Backup';
+ modalStateFTP.openByEdit = false;
+ }
+ });
+}
+
+/**FTP对象保存 */
+function fnModalFTPOk() {
+ modalStateFTPFrom.validate().then(() => {
+ modalStateFTP.confirmLoading = true;
+ const from = toRaw(modalStateFTP.from);
+ updateFTPInfo(from)
+ .then(res => {
+ if (res.code === RESULT_CODE_SUCCESS) {
+ message.success(`Configuration saved successfully`, 3);
+ fnModalFTPCancel();
+ } else {
+ message.warning(`Configuration save exception`, 3);
+ }
+ })
+ .finally(() => {
+ modalStateFTP.confirmLoading = false;
+ });
+ });
+}
+
+/**
+ * 对话框弹出关闭执行函数
+ * 进行表达规则校验
+ */
+function fnModalFTPCancel() {
+ modalStateFTP.openByEdit = false;
+ modalStateFTPFrom.resetFields();
+}
+
+/**
+ * 同步文件到FTP
+ * @param row
+ */
+function fnSyncFileToFTP(row: Record) {
+ modalStateFTP.confirmLoading = true;
+ putFTPInfo(row.path)
+ .then(res => {
+ if (res.code === RESULT_CODE_SUCCESS) {
+ message.success(t('common.operateOk'), 3);
+ } else {
+ message.warning(res.msg, 3);
+ }
+ })
+ .finally(() => {
+ modalStateFTP.confirmLoading = false;
+ });
+}
@@ -457,14 +571,11 @@ onMounted(() => {
-
- {{ t('common.searchBarText') }}
-
+
+ Setting Remote Backup
+
+
+
{{ t('common.reloadText') }}
@@ -520,6 +631,16 @@ onMounted(() => {
+
+ Send Current File To Remote Backup
+
+
+
+
{{ t('common.downloadText') }}
@@ -597,6 +718,106 @@ onMounted(() => {
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
From 59127104a6b79ba419fc04f2f4c5b8c87e0f0dca Mon Sep 17 00:00:00 2001
From: TsMask <340112800@qq.com>
Date: Fri, 11 Apr 2025 18:00:06 +0800
Subject: [PATCH 27/54] =?UTF-8?q?fix:=20=E7=9C=8B=E6=9D=BF=E7=94=A8?=
=?UTF-8?q?=E6=88=B7=E6=95=B0=E5=88=9D=E5=A7=8BneId=E4=BC=A0=E5=85=A5?=
=?UTF-8?q?=E5=A4=B1=E8=B4=A5=EF=BC=8C=E7=A6=81=E6=AD=A2=E9=80=89=E6=8B=A9?=
=?UTF-8?q?=E5=BD=93=E5=89=8D=E9=A1=B9?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/views/dashboard/overview/index.vue | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/views/dashboard/overview/index.vue b/src/views/dashboard/overview/index.vue
index bf22122c..14a03197 100644
--- a/src/views/dashboard/overview/index.vue
+++ b/src/views/dashboard/overview/index.vue
@@ -316,7 +316,7 @@ onMounted(() => {
});
udmOtions.value = arr1;
if (arr1.length > 0) {
- fnSelectUDM(arr1[0].value);
+ fnSelectUDM({ key: arr1[0].value });
}
// 过滤不可用的网元
@@ -399,7 +399,7 @@ onBeforeUnmount(() => {
-
+
{{ v.label }}
From 83808a4f88ee97abf69fbc2d04abf7fee3b94440 Mon Sep 17 00:00:00 2001
From: TsMask <340112800@qq.com>
Date: Fri, 18 Apr 2025 15:38:21 +0800
Subject: [PATCH 28/54] =?UTF-8?q?ref:=20=E9=87=8D=E6=9E=84=E7=BD=91?=
=?UTF-8?q?=E5=85=83=E8=B7=9F=E8=B8=AA=E4=BB=BB=E5=8A=A1=E5=8A=9F=E8=83=BD?=
=?UTF-8?q?=E9=A1=B5=E9=9D=A2?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/api/trace/analysis.ts | 27 -
src/api/trace/task.ts | 36 +-
src/i18n/locales/en-US.ts | 43 +-
src/i18n/locales/zh-CN.ts | 39 +-
src/views/traceManage/task/analyze.vue | 640 ++++++++++++++----
.../{analysis/index.vue => task/data.vue} | 499 ++++++++------
src/views/traceManage/task/index.vue | 283 ++++----
7 files changed, 999 insertions(+), 568 deletions(-)
delete mode 100644 src/api/trace/analysis.ts
rename src/views/traceManage/{analysis/index.vue => task/data.vue} (51%)
diff --git a/src/api/trace/analysis.ts b/src/api/trace/analysis.ts
deleted file mode 100644
index 1a4ccf11..00000000
--- a/src/api/trace/analysis.ts
+++ /dev/null
@@ -1,27 +0,0 @@
-import { request } from '@/plugins/http-fetch';
-
-/**
- * 跟踪任务数据列表
- * @param query 查询参数
- * @returns object
- */
-export async function listTraceData(query: Record) {
- return request({
- url: '/trace/task/list',
- method: 'GET',
- params: query,
- });
-}
-
-/**
- * 信令数据解析HTML
- * @param id 任务ID
- * @returns
- */
-export function getTraceRawInfo(id: Record) {
- return request({
- url: `/api/rest/traceManagement/v1/decMessage/${id}`,
- method: 'GET',
- responseType: 'text',
- });
-}
diff --git a/src/api/trace/task.ts b/src/api/trace/task.ts
index d30473e1..629b71ba 100644
--- a/src/api/trace/task.ts
+++ b/src/api/trace/task.ts
@@ -76,29 +76,31 @@ export function filePullTask(traceId: string) {
method: 'GET',
params: { traceId },
responseType: 'blob',
- timeout: 60_000,
+ timeout: 180_000,
});
}
/**
- * 获取网元跟踪接口列表
+ * 跟踪任务数据列表
+ * @param query 查询参数
* @returns object
*/
-export async function getNeTraceInterfaceAll() {
- // 发起请求
- const result = await request({
- url: `/api/rest/databaseManagement/v1/elementType/omc_db/objectType/ne_info`,
+export async function listTraceData(query: Record) {
+ return request({
+ url: '/trace/data/list',
+ method: 'GET',
+ params: query,
+ });
+}
+
+/**
+ * 查询跟踪任务数据信息
+ * @param id ID
+ * @returns object
+ */
+export async function getTraceData(id: string | number) {
+ return request({
+ url: `/trace/data/${id}`,
method: 'GET',
- params: {
- SQL: `SELECT ne_type,interface FROM trace_info GROUP BY ne_type,interface`,
- },
});
- // 解析数据
- if (result.code === RESULT_CODE_SUCCESS && Array.isArray(result.data.data)) {
- let data = result.data.data[0];
- return Object.assign(result, {
- data: parseObjLineToHump(data['trace_info']),
- });
- }
- return result;
}
diff --git a/src/i18n/locales/en-US.ts b/src/i18n/locales/en-US.ts
index 6d2257f6..73f9aecb 100644
--- a/src/i18n/locales/en-US.ts
+++ b/src/i18n/locales/en-US.ts
@@ -16,7 +16,6 @@ export default {
errorFields: 'Please fill in the required information in {num} correctly!',
tablePaginationTotal: 'Total {total} items',
noData: "No Data",
- zebra:'Tabular zebra pattern',
ok: 'Ok',
cancel: 'Cancel',
close: 'Close',
@@ -1010,25 +1009,6 @@ export default {
},
},
traceManage: {
- analysis: {
- imsi: 'IMSI',
- imsiPlease: 'Please enter IMSI',
- msisdn: 'MSISDN',
- msisdnPlease: 'Please enter MSISDN',
- trackTaskId: 'Task ID',
- srcIp: 'Source IP Address',
- dstIp: 'Destination IP Address',
- signalType: 'Signaling Type',
- msgDirect: 'Message Direction',
- msgType: 'Message Type',
- rowTime: 'Record Time',
- signalData: 'Signaling Data',
- signalDetail: 'Signaling Details',
- noData: 'No information content',
- taskTitle: 'Task {num}',
- taskDownText: 'Download HTML',
- taskDownTip: 'Confirm downloading the signaling details HTML file?',
- },
pcap: {
capArgPlease: 'Please enter tcpdump -i any support parameter',
cmd: 'Command',
@@ -1079,30 +1059,35 @@ export default {
imsiTip: 'Mobile communication IMSI number',
srcIp: 'Source IP Address',
srcIpPlease: 'Please enter the IP address',
- srcIpTip: 'Current sender IPv4 address',
+ srcIpTip: 'sending IPv4 address',
dstIp: 'Destination IP Address',
dstIpPlease: 'Please enter the IP address',
- dstIpTip: 'IPv4 address of the receiving end of the other party',
+ dstIpTip: 'receiving end IPv4 address',
interfaces: 'Signaling Interface',
interfacesPlease: 'Please enter the signaling interface',
- signalPort: 'Signal Port',
- signalPortPlease: 'Please enter the signaling port',
- signalPortTip: 'Port of the side corresponding to the destination IP address or source IP address',
- rangePicker: 'Start/End Time',
+ rangePicker: 'Task Time',
rangePickerPlease: 'Please select the start and end time of the task',
remark: 'Remark',
remarkPlease: 'Task description can be entered',
addTask: 'Add Task',
- editTask: 'Modify Task',
viewTask: 'View Task',
errorTaskInfo: 'Failed to obtain task information',
delTaskTip: 'Are you sure to delete the data item with record ID {id} ?',
stopTask: 'Successful cessation of tasks {id}',
stopTaskTip: 'Confirm stopping the task with record ID {id} ?',
- pcapView: "Tracking Data Analysis",
- traceFile: "Tracking File",
+ pcapView: "Track Data Analysis",
+ traceFile: "Track File",
errMsg: "Error Message",
imsiORmsisdn: "imsi or msisdn is null, cannot start task",
+ dataView: "Track Data",
+ protocolOrInterface: "Protocol/Interface",
+ msgNe: 'Network Element',
+ msgEvent: 'Event',
+ msgType: 'Type',
+ msgDirect: 'Direction',
+ msgLen: 'Length',
+ rowTime: 'Time',
+ taskInfo: 'Task information',
},
},
faultManage: {
diff --git a/src/i18n/locales/zh-CN.ts b/src/i18n/locales/zh-CN.ts
index 37d5808e..1ff6ecb5 100644
--- a/src/i18n/locales/zh-CN.ts
+++ b/src/i18n/locales/zh-CN.ts
@@ -16,7 +16,6 @@ export default {
errorFields: '请正确填写 {num} 处必填信息!',
tablePaginationTotal: '总共 {total} 条',
noData: "暂无数据",
- zebra:'表格斑马纹',
ok: '确定',
cancel: '取消',
close: '关闭',
@@ -1010,25 +1009,6 @@ export default {
},
},
traceManage: {
- analysis: {
- imsi: 'IMSI',
- imsiPlease: '请输入IMSI',
- msisdn: 'MSISDN',
- msisdnPlease: '请输入MSISDN',
- trackTaskId: '跟踪任务标记',
- srcIp: '源IP地址',
- dstIp: '目标IP地址',
- signalType: '信令类型',
- msgDirect: '消息元',
- msgType: '消息类型',
- rowTime: '记录时间',
- signalData: '信令数据',
- signalDetail: '信令详情',
- noData: '无信息内容',
- taskTitle: '任务 {num}',
- taskDownText: '下载HTML',
- taskDownTip: '确认下载信令详情HTML文件?',
- },
pcap: {
capArgPlease: '请输入tcpdump -i any支持参数',
cmd: '命令',
@@ -1079,21 +1059,17 @@ export default {
imsiTip: '移动通信IMSI编号',
srcIp: '源IP地址',
srcIpPlease: '请输入源IP地址',
- srcIpTip: '当前发送端IPv4地址',
+ srcIpTip: '发送端IPv4地址',
dstIp: '目标IP地址',
dstIpPlease: '请输入目标IP地址',
- dstIpTip: '对方接收端IPv4地址',
+ dstIpTip: '接收端IPv4地址',
interfaces: '信令接口',
interfacesPlease: '请输入信令接口',
- signalPort: '信令端口',
- signalPortPlease: '请输入信令端口',
- signalPortTip: '目标IP地址或源IP地址对应一方的端口',
- rangePicker: '开始结束时间',
+ rangePicker: '任务时间',
rangePickerPlease: '请选择任务时间开始结束时间',
remark: '说明',
remarkPlease: '可输入任务说明',
addTask: '添加任务',
- editTask: '修改任务',
viewTask: '查看任务',
errorTaskInfo: '获取任务信息失败',
delTaskTip: '确认删除记录编号为 {id} 的数据项?',
@@ -1103,6 +1079,15 @@ export default {
traceFile: "跟踪文件",
errMsg: "错误信息",
imsiORmsisdn: "imsi 或 msisdn 是空值,不能开始任务",
+ dataView: "跟踪数据",
+ protocolOrInterface: "协议/接口",
+ msgNe: '消息网元',
+ msgEvent: '消息事件',
+ msgType: '消息类型',
+ msgDirect: '消息方向',
+ msgLen: '消息长度',
+ rowTime: '消息时间',
+ taskInfo: '任务信息',
},
},
faultManage: {
diff --git a/src/views/traceManage/task/analyze.vue b/src/views/traceManage/task/analyze.vue
index 1cee75c4..16aae17c 100644
--- a/src/views/traceManage/task/analyze.vue
+++ b/src/views/traceManage/task/analyze.vue
@@ -1,35 +1,32 @@
@@ -154,8 +567,9 @@ onBeforeUnmount(() => {
:loading="!state.initialized"
:body-style="{ padding: '12px' }"
>
-
-
-
-
-
-
-
-
-
-
- Filter
-
-
-
+
+
+
+ {{ t('common.reloadText') }}
+
+
+
+
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
@@ -268,15 +658,15 @@ onBeforeUnmount(() => {
@@ -289,24 +679,20 @@ onBeforeUnmount(() => {
diff --git a/src/views/traceManage/task/index.vue b/src/views/traceManage/task/index.vue
index 1be6f3e6..43ae3eda 100644
--- a/src/views/traceManage/task/index.vue
+++ b/src/views/traceManage/task/index.vue
@@ -20,7 +20,7 @@ import {
updateTraceTask,
} from '@/api/trace/task';
import useDictStore from '@/store/modules/dict';
-import { regExpIPv4, regExpPort } from '@/utils/regular-utils';
+import { regExpIPv4 } from '@/utils/regular-utils';
import dayjs, { Dayjs } from 'dayjs';
import { parseObjHumpToLine } from '@/utils/parse-utils';
const neInfoStore = useNeInfoStore();
@@ -33,8 +33,11 @@ const route = useRoute();
let dict: {
/**跟踪类型 */
traceType: DictType[];
+ /**跟踪接口 */
+ traceInterfaces: DictType[];
} = reactive({
traceType: [],
+ traceInterfaces: [],
});
/**网元类型_多neId */
@@ -98,40 +101,28 @@ let tableState: TabeStateType = reactive({
/**表格字段列 */
let tableColumns: ColumnsType = [
- {
- title: t('views.ne.common.neType'),
- dataIndex: 'neType',
- align: 'left',
- sorter: {
- compare: (a, b) => 1,
- multiple: 1,
- },
- },
- {
- title: t('views.ne.common.neId'),
- dataIndex: 'neId',
- align: 'left',
- },
{
title: t('views.traceManage.task.traceId'),
dataIndex: 'traceId',
align: 'left',
+ width: 150,
},
{
title: t('views.traceManage.task.trackType'),
dataIndex: 'traceType',
key: 'traceType',
align: 'left',
+ width: 150,
},
{
title: t('views.traceManage.task.startTime'),
dataIndex: 'startTime',
align: 'left',
+ width: 200,
customRender(opt) {
if (!opt.value) return '';
return parseDateToStr(opt.value);
},
- sorter: true,
},
{
title: t('views.traceManage.task.endTime'),
@@ -141,6 +132,7 @@ let tableColumns: ColumnsType = [
if (!opt.value) return '';
return parseDateToStr(opt.value);
},
+ width: 200,
},
{
title: t('common.operate'),
@@ -274,18 +266,15 @@ type ModalStateType = {
/**标题 */
title: string;
/**网元类型设备对象 */
- neType: string[];
+ neType: any[] | undefined;
/**网元类型设备对象接口 */
- neTypeInterface: Record[];
- /**网元类型设备对象接口选择 */
- neTypeInterfaceSelect: string[];
+ neTypeInterface: string[];
/**任务开始结束时间 */
- timeRangePicker: [string, string];
+ timeRangePicker: [Dayjs, Dayjs] | undefined;
/**表单数据 */
from: {
id?: string;
- neType: string;
- neId: string;
+ neList: string; // 网元列表 neType_neId 例如 UDM_001,AMF_001
/**1-Interface,2-Device,3-User */
traceType: string;
startTime?: number;
@@ -312,13 +301,11 @@ let modalState: ModalStateType = reactive({
title: '',
neType: [],
neTypeInterface: [],
- neTypeInterfaceSelect: [],
- timeRangePicker: ['', ''],
+ timeRangePicker: undefined,
from: {
id: undefined,
- neType: '',
- neId: '',
- traceId: '',
+ neList: '',
+ traceId: undefined,
traceType: '3',
startTime: undefined,
endTime: undefined,
@@ -330,8 +317,8 @@ let modalState: ModalStateType = reactive({
dstIp: '',
signalPort: undefined,
/**3用户跟踪 */
- imsi: '',
- msisdn: '',
+ imsi: undefined,
+ // msisdn: undefined,
},
confirmLoading: false,
});
@@ -346,7 +333,7 @@ const modalStateFrom = Form.useForm(
message: t('views.traceManage.task.trackTypePlease'),
},
],
- neId: [
+ neList: [
{
required: true,
message: t('views.ne.common.neTypePlease'),
@@ -393,43 +380,48 @@ const modalStateFrom = Form.useForm(
message: t('views.traceManage.task.dstIpPlease'),
},
],
- signalPort: [
- {
- required: false,
- pattern: regExpPort,
- message: t('views.traceManage.task.signalPortPlease'),
- },
- ],
})
);
/**网元类型选择对应修改 */
-function fnNeChange(_: any, item: any) {
- modalState.from.neType = item[1].neType;
- modalState.from.neId = item[1].neId;
- // 网元信令接口可选列表
- modalState.from.interfaces = '';
- modalState.neTypeInterfaceSelect = [];
- fnSelectInterfaceInit(item[1].neType);
-}
-
-/**跟踪类型选择对应修改 */
-function fnTraceTypeChange(v: any, _: any) {
- // 网元信令接口可选列表
- if (v === '1' && modalState.from.neType) {
- modalState.from.interfaces = '';
- modalState.neTypeInterfaceSelect = [];
- fnSelectInterfaceInit(modalState.from.neType);
+function fnNeChange(p: any, c: any) {
+ let neList: string[] = [];
+ for (let i = 0; i < p.length; i++) {
+ const v = p[i];
+ if (v.length === 1) {
+ c[i][0].children.forEach((item: any) => {
+ neList.push(`${item.neType}_${item.neId}`);
+ });
+ } else if (v.length === 2) {
+ neList.push(`${v[0]}_${v[1]}`);
+ }
+ }
+ if (neList.length > 0) {
+ modalState.from.neList = neList.join(',');
+ } else {
+ modalState.from.neList = '';
}
}
/**开始结束时间选择对应修改 */
function fnRangePickerChange(item: any, _: any) {
- modalState.from.startTime = +item[0];
- modalState.from.endTime = +item[1];
+ if (!item || item.length !== 2) {
+ modalState.from.startTime = undefined;
+ modalState.from.endTime = undefined;
+ return;
+ }
+ // 获取当前时间
+ const now = dayjs();
+ // 如果开始时间小于当前时间,则设置为当前时间
+ const startTime = item[0].isBefore(now) ? now : item[0];
+ const endTime = item[1].isBefore(now) ? now : item[1];
+ modalState.timeRangePicker = [startTime, endTime];
+
+ modalState.from.startTime = startTime.valueOf();
+ modalState.from.endTime = endTime.valueOf();
}
function fnRangePickerDisabledDate(current: Dayjs) {
- return current && current < dayjs().subtract(1, 'day').endOf('day');
+ return current && current < dayjs().startOf('day');
}
/**信令接口选择对应修改 */
@@ -437,19 +429,6 @@ function fnSelectInterface(s: any, _: any) {
modalState.from.interfaces = s.join(',');
}
-/**信令接口选择初始 */
-function fnSelectInterfaceInit(neType: string) {
- const interfaces = neInfoStore.traceInterfaceList;
- modalState.neTypeInterface = interfaces
- .filter(i => i.neType === neType)
- .map(i => {
- return {
- value: i.interface,
- label: i.interface,
- };
- });
-}
-
/**
* 对话框弹出显示为 新增或者修改
* @param noticeId 网元id, 不传为新增
@@ -467,20 +446,45 @@ function fnModalOpenByEdit(id?: string) {
modalState.confirmLoading = false;
hide();
if (res.code === RESULT_CODE_SUCCESS && res.data) {
- modalState.neType = [res.data.neType, res.data.neId];
- modalState.timeRangePicker = [res.data.startTime, res.data.endTime];
- modalState.from = Object.assign(modalState.from, res.data);
- // 接口
- if (res.data.traceType === 'Interface') {
- if (
- res.data.interfaces.length > 4 &&
- res.data.interfaces.includes('[')
- ) {
- modalState.neTypeInterfaceSelect = JSON.parse(res.data.interfaces);
+ // 回显网元类型
+ const neType: any[] = [];
+ const neList = res.data.neList.split(',');
+ const neListMap: any = {};
+ for (const v of neList) {
+ const item: string[] = v.split('_');
+ if (!neListMap[item[0]]) {
+ neListMap[item[0]] = [];
}
- fnSelectInterfaceInit(res.data.neType);
+ neListMap[item[0]].push(item[1]);
}
- modalState.title = t('views.traceManage.task.editTask');
+ for (const op of neCascaderOptions.value) {
+ const arr = neListMap[op.value];
+ if (!arr) {
+ continue;
+ }
+ const all = op.children.every((c: any) => {
+ return arr.includes(c.neId);
+ });
+ if (all) {
+ neType.push([op.value]);
+ } else {
+ arr.forEach((v: string) => {
+ neType.push([op.value, v]);
+ });
+ }
+ }
+ modalState.neType = neType;
+ // 回显时间
+ modalState.timeRangePicker = [
+ dayjs(res.data.startTime),
+ dayjs(res.data.endTime),
+ ];
+ // 回显接口
+ if (res.data.traceType === '1') {
+ modalState.neTypeInterface = res.data.interfaces.split(',');
+ }
+ modalState.from = Object.assign(modalState.from, res.data);
+ modalState.title = t('views.traceManage.task.viewTask');
modalState.openByEdit = true;
} else {
message.error(t('views.traceManage.task.errorTaskInfo'), 3);
@@ -495,15 +499,15 @@ function fnModalOpenByEdit(id?: string) {
*/
function fnModalOk() {
const from = toRaw(modalState.from);
- let valids = ['traceType', 'neId', 'endTime'];
+ let valids = ['traceType', 'neList', 'endTime'];
if (from.traceType === '1') {
valids = valids.concat(['interfaces']);
}
if (from.traceType === '2') {
- valids = valids.concat(['srcIp', 'dstIp', 'signalPort']);
+ valids = valids.concat(['srcIp', 'dstIp']);
}
if (from.traceType === '3') {
- valids = valids.concat(['imsi', 'msisdn']);
+ valids = valids.concat(['imsi']);
}
modalStateFrom
@@ -546,29 +550,31 @@ function fnModalCancel() {
modalState.openByEdit = false;
modalState.confirmLoading = false;
modalStateFrom.resetFields();
- modalState.timeRangePicker = ['', ''];
- modalState.neTypeInterfaceSelect = [];
modalState.neType = [];
modalState.neTypeInterface = [];
+ modalState.timeRangePicker = undefined;
}
-/**跳转PCAP文件详情页面 */
-function fnRecordPCAPView(row: Record) {
+/**跳转内嵌详情页面 */
+function fnRecordView(traceId: any, type: 'analyze' | 'data') {
router.push({
- path: `${route.path}${MENU_PATH_INLINE}/analyze`,
- query: {
- traceId: row.traceId,
- },
+ path: `${route.path}${MENU_PATH_INLINE}/${type}`,
+ query: { traceId },
});
}
onMounted(() => {
// 初始字典数据
- Promise.allSettled([getDict('trace_type')]).then(resArr => {
- if (resArr[0].status === 'fulfilled') {
- dict.traceType = resArr[0].value;
+ Promise.allSettled([getDict('trace_type'), getDict('trace_interfaces')]).then(
+ resArr => {
+ if (resArr[0].status === 'fulfilled') {
+ dict.traceType = resArr[0].value;
+ }
+ if (resArr[1].status === 'fulfilled') {
+ dict.traceInterfaces = resArr[1].value;
+ }
}
- });
+ );
// 获取网元网元列表
useNeInfoStore()
@@ -579,13 +585,13 @@ onMounted(() => {
// 过滤不可用的网元
neCascaderOptions.value = neInfoStore.getNeSelectOtions.filter(
(item: any) => {
- return ['UDM'].includes(item.value);
+ return ['AMF', 'AUSF', 'SMF', 'UDM', 'PCF'].includes(item.value);
}
);
if (neCascaderOptions.value.length === 0) {
message.warning({
content: t('common.noData'),
- duration: 2,
+ duration: 3,
});
return;
}
@@ -593,13 +599,11 @@ onMounted(() => {
} else {
message.warning({
content: t('common.noData'),
- duration: 2,
+ duration: 3,
});
}
})
.finally(() => {
- // 获取跟踪接口列表
- neInfoStore.fnNeTraceInterface();
// 获取列表数据
fnGetList();
});
@@ -765,21 +769,40 @@ onMounted(() => {
+
+
+
+ {{ t('views.traceManage.task.dataView') }}
+
+
+
+
+
+
+
+
+
+ {{ t('views.traceManage.task.pcapView') }}
+
+
+
+
+
+
+
- {{ t('common.editText') }}
+ {{ t('common.viewText') }}
-
-
-
-
- {{
- t('views.traceManage.task.pcapView')
- }}
-
-
+
@@ -810,12 +833,14 @@ onMounted(() => {
:confirm-loading="modalState.confirmLoading"
@ok="fnModalOk"
@cancel="fnModalCancel"
+ :footer="modalState.from.id ? null : undefined"
>
@@ -823,12 +848,13 @@ onMounted(() => {
:label="t('views.ne.common.neType')"
:label-col="{ span: 8 }"
name="neType"
- v-bind="modalStateFrom.validateInfos.neId"
+ v-bind="modalStateFrom.validateInfos.neList"
>
@@ -844,7 +870,6 @@ onMounted(() => {
@@ -861,11 +886,9 @@ onMounted(() => {
@@ -904,26 +927,6 @@ onMounted(() => {
-
-
-
-
-
- {{ t('views.traceManage.task.signalPortTip') }}
-
-
-
-
-
-
{
- {
-
+ -->
From b92c871b3b5a840e2fb7a5fe2f20e2646c80892d Mon Sep 17 00:00:00 2001
From: TsMask <340112800@qq.com>
Date: Fri, 18 Apr 2025 15:38:57 +0800
Subject: [PATCH 29/54] =?UTF-8?q?perf:=20=E9=87=8D=E6=9E=84=E4=BF=A1?=
=?UTF-8?q?=E4=BB=A4=E8=B7=9F=E8=B8=AA=E5=8A=9F=E8=83=BD?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/api/trace/packet.ts | 15 +
src/views/traceManage/wireshark/index.vue | 725 +++++++++++++++-------
2 files changed, 512 insertions(+), 228 deletions(-)
diff --git a/src/api/trace/packet.ts b/src/api/trace/packet.ts
index 2266e510..57f777dd 100644
--- a/src/api/trace/packet.ts
+++ b/src/api/trace/packet.ts
@@ -62,3 +62,18 @@ export function packetKeep(taskNo: string, duration: number = 120) {
data: { taskNo, duration },
});
}
+
+/**
+ * 信令跟踪文件
+ * @param taskNo 对象
+ * @returns object
+ */
+export function packetPCAPFile(taskNo: string) {
+ return request({
+ url: '/trace/packet/filePull',
+ method: 'GET',
+ params: { taskNo },
+ responseType: 'blob',
+ timeout: 180_000,
+ });
+}
diff --git a/src/views/traceManage/wireshark/index.vue b/src/views/traceManage/wireshark/index.vue
index ff765751..d372d17b 100644
--- a/src/views/traceManage/wireshark/index.vue
+++ b/src/views/traceManage/wireshark/index.vue
@@ -1,16 +1,16 @@
-
+
-
-
+
-
-
-
-
+
+
+
+
+
+
Filter
-
-
-
+
+
+
+
+
+
+
+
+
@@ -474,28 +765,6 @@ onBeforeUnmount(() => {
diff --git a/src/views/neData/udm-volte/index.vue b/src/views/neData/udm-volte/index.vue
new file mode 100644
index 00000000..2bd168eb
--- /dev/null
+++ b/src/views/neData/udm-volte/index.vue
@@ -0,0 +1,1070 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('common.search') }}
+
+
+
+
+
+ {{ t('common.reset') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('common.addText') }}
+
+
+
+
+ {{ t('views.neData.common.checkDel') }}
+
+
+
+
+ {{ t('views.neData.common.batchOper') }}
+
+
+
+ fnModalVisibleByBatch(key)">
+
+
+ {{ t('views.neData.common.batchAddText') }}
+
+
+
+ {{ t('views.neData.common.batchDelText') }}
+
+
+
+
+
+
+
+
+ {{ t('views.neData.common.loadData') }}
+
+
+
+
+
+ {{ t('common.import') }}
+
+
+
+
+ {{ t('common.export') }}
+
+
+
+
+
+
+
+
+
+
+ {{
+ tableState.seached
+ ? t('common.switch.show')
+ : t('common.switch.hide')
+ }}
+
+
+
+
+
+ {{ t('common.reloadText') }}
+
+
+
+
+
+ {{ t('common.sizeText') }}
+
+
+
+
+
+
+
+ {{ t('common.size.default') }}
+
+
+ {{ t('common.size.middle') }}
+
+
+ {{ t('common.size.small') }}
+
+
+
+
+
+
+
+
+
+ (col.width = w)"
+ :row-selection="{
+ type: 'checkbox',
+ selectedRowKeys: tableState.selectedRowKeys,
+ onChange: fnTableSelectedRowKeys,
+ }"
+ >
+
+
+
+
+
+
+
+ {{ t('common.deleteText') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('views.neData.common.imsiTip') }}
+ {{ t('views.neData.common.imsiTip1') }}
+ {{ t('views.neData.common.imsiTip2') }}
+ {{ t('views.neData.common.imsiTip3') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('views.neData.common.imsiTip') }}
+ {{ t('views.neData.common.imsiTip1') }}
+ {{ t('views.neData.common.imsiTip2') }}
+ {{ t('views.neData.common.imsiTip3') }}
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('views.neData.common.msisdn') }}
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('views.neData.udmVolteIMS.vniTip') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('views.neData.common.importTemplate') }}
+
+
+
+
+
+
+
+
+
+
From 71b4943816ebfdd447ae35552faa8ff96ee2c9ab Mon Sep 17 00:00:00 2001
From: TsMask <340112800@qq.com>
Date: Fri, 25 Apr 2025 16:14:23 +0800
Subject: [PATCH 39/54] =?UTF-8?q?style:=20neFile=E7=9B=AE=E5=BD=95?=
=?UTF-8?q?=E7=A7=BB=E5=8A=A8=E5=88=B0ne?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../{logManage => ne}/neFile/components/ViewDrawer.vue | 0
src/views/{logManage => ne}/neFile/index.vue | 8 ++++++--
2 files changed, 6 insertions(+), 2 deletions(-)
rename src/views/{logManage => ne}/neFile/components/ViewDrawer.vue (100%)
rename src/views/{logManage => ne}/neFile/index.vue (98%)
diff --git a/src/views/logManage/neFile/components/ViewDrawer.vue b/src/views/ne/neFile/components/ViewDrawer.vue
similarity index 100%
rename from src/views/logManage/neFile/components/ViewDrawer.vue
rename to src/views/ne/neFile/components/ViewDrawer.vue
diff --git a/src/views/logManage/neFile/index.vue b/src/views/ne/neFile/index.vue
similarity index 98%
rename from src/views/logManage/neFile/index.vue
rename to src/views/ne/neFile/index.vue
index 3f62684b..f76a9a68 100644
--- a/src/views/logManage/neFile/index.vue
+++ b/src/views/ne/neFile/index.vue
@@ -12,6 +12,7 @@ import useI18n from '@/hooks/useI18n';
import ViewDrawer from './components/ViewDrawer.vue';
import saveAs from 'file-saver';
import { useRoute } from 'vue-router';
+import { parseSizeFromFile } from '@/utils/parse-utils';
const neInfoStore = useNeInfoStore();
const { t } = useI18n();
const route = useRoute();
@@ -79,16 +80,19 @@ let tableColumns: ColumnsType = [
dataIndex: 'size',
align: 'left',
width: 100,
+ customRender(opt) {
+ return parseSizeFromFile(opt.value);
+ },
},
{
title: t('views.logManage.neFile.modifiedTime'),
dataIndex: 'modifiedTime',
align: 'left',
+ width: 200,
customRender(opt) {
if (!opt.value) return '';
return parseDateToStr(opt.value * 1000);
},
- width: 150,
},
{
title: t('views.logManage.neFile.fileName'),
@@ -238,7 +242,7 @@ function fnGetList(pageNum?: number) {
}
queryParams.path = nePathArr.value.join('/');
listNeFiles(toRaw(queryParams)).then(res => {
- if (res.code === RESULT_CODE_SUCCESS) {
+ if (res.code === RESULT_CODE_SUCCESS) {
const { total, rows } = res.data;
tablePagination.total = total;
tableState.data = rows;
From 204d19881959a35fa37547284402a36e2b554c33 Mon Sep 17 00:00:00 2001
From: TsMask <340112800@qq.com>
Date: Fri, 25 Apr 2025 16:16:09 +0800
Subject: [PATCH 40/54] =?UTF-8?q?ref:=20=E7=BB=9F=E4=B8=80ftp=E6=93=8D?=
=?UTF-8?q?=E4=BD=9C=E5=8A=9F=E8=83=BD=EF=BC=8C=E5=A4=87=E4=BB=BD=E6=96=87?=
=?UTF-8?q?=E4=BB=B6=E6=9F=A5=E7=9C=8B=E4=B8=8B=E8=BD=BD=E5=88=A0=E9=99=A4?=
=?UTF-8?q?=E5=8A=9F=E8=83=BD?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/api/logManage/exportFile.ts | 40 --
src/api/ne/neConfigBackup.ts | 40 --
src/api/neData/backup.ts | 38 ++
src/api/tool/file.ts | 44 ++
src/utils/parse-utils.ts | 9 +-
src/views/logManage/exportFile/index.vue | 433 +++++-------------
.../neConfigBackup/components/BackupModal.vue | 230 ++++++++++
src/views/ne/neConfigBackup/index.vue | 248 ++--------
8 files changed, 473 insertions(+), 609 deletions(-)
create mode 100644 src/api/neData/backup.ts
create mode 100644 src/views/ne/neConfigBackup/components/BackupModal.vue
diff --git a/src/api/logManage/exportFile.ts b/src/api/logManage/exportFile.ts
index 19f7b068..2ce72877 100644
--- a/src/api/logManage/exportFile.ts
+++ b/src/api/logManage/exportFile.ts
@@ -53,43 +53,3 @@ export function delFile(query: Record) {
params: query,
});
}
-
-/**
- * 更新FTP信息
- * @param data 数据
- * @returns object
- */
-export function updateFTPInfo(data: Record) {
- return request({
- url: `/lm/table/ftp`,
- method: 'POST',
- data: data,
- crypto: sessionGet(CACHE_SESSION_CRYPTO_API) !== 'false',
- });
-}
-
-/**
- * 获取FTP信息
- * @param data 数据
- * @returns object
- */
-export function getFTPInfo() {
- return request({
- url: `/lm/table/ftp`,
- method: 'GET',
- crypto: sessionGet(CACHE_SESSION_CRYPTO_API) !== 'false',
- });
-}
-
-/**
- * 发送FTP文件
- * @param data 数据
- * @returns object
- */
-export function putFTPInfo(filePath: string, fileName: string) {
- return request({
- url: `/lm/table/ftp`,
- method: 'PUT',
- data: { filePath, fileName },
- });
-}
diff --git a/src/api/ne/neConfigBackup.ts b/src/api/ne/neConfigBackup.ts
index e6b8c817..af63fdea 100644
--- a/src/api/ne/neConfigBackup.ts
+++ b/src/api/ne/neConfigBackup.ts
@@ -83,43 +83,3 @@ export function importNeConfigBackup(data: Record) {
data: data,
});
}
-
-/**
- * 更新FTP信息
- * @param data 数据
- * @returns object
- */
-export function updateFTPInfo(data: Record) {
- return request({
- url: `/ne/config/backup/ftp`,
- method: 'POST',
- data: data,
- crypto: sessionGet(CACHE_SESSION_CRYPTO_API) !== 'false',
- });
-}
-
-/**
- * 获取FTP信息
- * @param data 数据
- * @returns object
- */
-export function getFTPInfo() {
- return request({
- url: `/ne/config/backup/ftp`,
- method: 'GET',
- crypto: sessionGet(CACHE_SESSION_CRYPTO_API) !== 'false',
- });
-}
-
-/**
- * 发送FTP文件
- * @param data 数据
- * @returns object
- */
-export function putFTPInfo(path: string) {
- return request({
- url: `/ne/config/backup/ftp`,
- method: 'PUT',
- data: { path },
- });
-}
diff --git a/src/api/neData/backup.ts b/src/api/neData/backup.ts
new file mode 100644
index 00000000..eeb3781c
--- /dev/null
+++ b/src/api/neData/backup.ts
@@ -0,0 +1,38 @@
+import { request } from '@/plugins/http-fetch';
+
+/**
+ * 备份文件-获取FTP配置
+ * @returns object
+ */
+export function getBackupFTP() {
+ return request({
+ url: '/neData/backup/ftp',
+ method: 'GET',
+ });
+}
+
+/**
+ * 备份文件-文件FTP发送
+ * @param data 对象
+ * @returns object
+ */
+export function pushBackupFTP(data: Record) {
+ return request({
+ url: '/neData/backup/ftp',
+ method: 'POST',
+ data,
+ });
+}
+
+/**
+ * 备份文件-更新FTP配置
+ * @param data 对象
+ * @returns object
+ */
+export function updateBackupFTP(data: Record) {
+ return request({
+ url: '/neData/backup/ftp',
+ method: 'PUT',
+ data,
+ });
+}
diff --git a/src/api/tool/file.ts b/src/api/tool/file.ts
index 5a29df83..ff31c5ae 100644
--- a/src/api/tool/file.ts
+++ b/src/api/tool/file.ts
@@ -210,6 +210,50 @@ export function chunkUpload(data: FormData) {
});
}
+/**
+ * 本地文件列表
+ * @param path 文件路径
+ * @param search search prefix
+ * @returns object
+ */
+export async function listFile(query: Record) {
+ return request({
+ url: `/file/list`,
+ method: 'GET',
+ params: query,
+ });
+}
+
+/**
+ * 本地文件获取下载
+ * @param path 文件路径
+ * @param fileName 文件名
+ * @returns object
+ */
+export async function getFile(path: string, fileName: string) {
+ return request({
+ url: `/file`,
+ method: 'GET',
+ params: { path, fileName },
+ responseType: 'blob',
+ timeout: 60_000,
+ });
+}
+
+/**
+ * 本地文件删除
+ * @param path 文件路径
+ * @param fileName 文件名
+ * @returns object
+ */
+export async function delFile(path: string, fileName: string) {
+ return request({
+ url: `/file`,
+ method: 'DELETE',
+ params: { path, fileName },
+ });
+}
+
/**
* 转存上传文件到静态资源
* @returns object
diff --git a/src/utils/parse-utils.ts b/src/utils/parse-utils.ts
index 8e13fd43..ada8afec 100644
--- a/src/utils/parse-utils.ts
+++ b/src/utils/parse-utils.ts
@@ -101,7 +101,14 @@ export function parseObjLineToHump(obj: any): any {
* @param decimalPlaces 保留小数位,默认2位
* @returns 单位 xB
*/
-export function parseSizeFromFile(bytes: number, decimalPlaces: number = 2) {
+export function parseSizeFromFile(
+ bytes: number,
+ decimalPlaces: number = 2
+): string {
+ if (typeof bytes !== 'number' || isNaN(bytes) || bytes < 0) {
+ return `${bytes}`;
+ }
+ if (bytes === 0) return '0 B';
const units = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
let i = 0;
while (bytes >= 1024 && i < units.length - 1) {
diff --git a/src/views/logManage/exportFile/index.vue b/src/views/logManage/exportFile/index.vue
index b39391db..d7a2ba2a 100644
--- a/src/views/logManage/exportFile/index.vue
+++ b/src/views/logManage/exportFile/index.vue
@@ -1,38 +1,57 @@
@@ -410,12 +313,14 @@ function fnSyncFileToFTP(row: Record) {
- {{ t('views.logManage.exportFile.fileName') }}:
+ {{ t('views.logManage.exportFile.fileSource') }}:
@@ -436,9 +341,11 @@ function fnSyncFileToFTP(row: Record) {
-
- Setting Remote Backup
-
+
+
+ {{ t('views.ne.neConfigBackup.backupModal.title') }}
+
+
@@ -465,135 +372,45 @@ function fnSyncFileToFTP(row: Record) {
-
-
-
-
-
-
-
-
-
+
+
+ {{ t('views.ne.neConfigBackup.backupModal.pushFileOper') }}
+
+
+
+
+
+
+ {{ t('common.downloadText') }}
+
+
+
+
+
+ {{ t('common.deleteText') }}
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
diff --git a/src/views/ne/neConfigBackup/components/BackupModal.vue b/src/views/ne/neConfigBackup/components/BackupModal.vue
new file mode 100644
index 00000000..74cb751d
--- /dev/null
+++ b/src/views/ne/neConfigBackup/components/BackupModal.vue
@@ -0,0 +1,230 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/ne/neConfigBackup/index.vue b/src/views/ne/neConfigBackup/index.vue
index 3cd1e855..2f24ed70 100644
--- a/src/views/ne/neConfigBackup/index.vue
+++ b/src/views/ne/neConfigBackup/index.vue
@@ -5,22 +5,20 @@ import { ProModal } from 'antdv-pro-modal';
import { Form, Modal, TableColumnsType, message } from 'ant-design-vue/es';
import { SizeType } from 'ant-design-vue/es/config-provider';
import { MenuInfo } from 'ant-design-vue/es/menu/src/interface';
+import BackupModal from './components/BackupModal.vue';
import useNeInfoStore from '@/store/modules/neinfo';
import useI18n from '@/hooks/useI18n';
import useDictStore from '@/store/modules/dict';
import { NE_TYPE_LIST } from '@/constants/ne-constants';
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
import { parseDateToStr } from '@/utils/date-utils';
-import { regExpIPv4 } from '@/utils/regular-utils';
import {
delNeConfigBackup,
downNeConfigBackup,
listNeConfigBackup,
updateNeConfigBackup,
- getFTPInfo,
- putFTPInfo,
- updateFTPInfo,
} from '@/api/ne/neConfigBackup';
+import { pushBackupFTP } from '@/api/neData/backup';
import saveAs from 'file-saver';
const { t } = useI18n();
const { getDict } = useDictStore();
@@ -389,119 +387,26 @@ onMounted(() => {
});
});
-/**FTP日志对象信息状态 */
-let modalStateFTP: ModalStateType = reactive({
- openByEdit: false,
- title: '设置远程备份配置',
- from: {
- username: '',
- password: '',
- toIp: '',
- toPort: 22,
- enable: false,
- dir: '',
- },
- confirmLoading: false,
-});
+/**打开FTP配置窗口 */
+const openFTPModal = ref(false);
+function fnFTPModalOpen() {
+ openFTPModal.value = !openFTPModal.value;
+}
-/**FTP日志对象信息内表单属性和校验规则 */
-const modalStateFTPFrom = Form.useForm(
- modalStateFTP.from,
- reactive({
- toIp: [
- {
- required: true,
- pattern: regExpIPv4,
- message: 'Please enter the service login IP',
- },
- ],
- username: [
- {
- required: true,
- trigger: 'blur',
- message: 'Please enter the service login user name',
- },
- ],
- dir: [
- {
- required: true,
- trigger: 'blur',
- message: 'Please enter the service address target file directory',
- },
- ],
- })
-);
-
-/**
- * 对话框弹出显示为 新增或者修改
- * @param configId 参数编号id, 不传为新增
- */
-function fnModalFTPVisibleByEdit() {
- if (modalStateFTP.confirmLoading) return;
- const hide = message.loading(t('common.loading'), 0);
- modalStateFTP.confirmLoading = true;
- getFTPInfo().then(res => {
- modalStateFTP.confirmLoading = false;
- hide();
- if (res.code === RESULT_CODE_SUCCESS && res.data) {
- modalStateFTP.from = Object.assign(modalStateFTP.from, res.data);
- modalStateFTP.title = 'Setting Remote Backup';
- modalStateFTP.openByEdit = true;
+/**同步文件到FTP */
+function fnSyncFileToFTP(row: Record) {
+ pushBackupFTP({
+ path: row.path.substring(0, row.path.lastIndexOf('/')),
+ fileName: row.name,
+ tag: 'ne_config',
+ }).then(res => {
+ if (res.code === RESULT_CODE_SUCCESS) {
+ message.success(t('common.operateOk'), 3);
} else {
- message.error(res.msg, 3);
- modalStateFTP.title = 'Setting Remote Backup';
- modalStateFTP.openByEdit = false;
+ message.warning(res.msg, 3);
}
});
}
-
-/**FTP对象保存 */
-function fnModalFTPOk() {
- modalStateFTPFrom.validate().then(() => {
- modalStateFTP.confirmLoading = true;
- const from = toRaw(modalStateFTP.from);
- updateFTPInfo(from)
- .then(res => {
- if (res.code === RESULT_CODE_SUCCESS) {
- message.success(`Configuration saved successfully`, 3);
- fnModalFTPCancel();
- } else {
- message.warning(`Configuration save exception`, 3);
- }
- })
- .finally(() => {
- modalStateFTP.confirmLoading = false;
- });
- });
-}
-
-/**
- * 对话框弹出关闭执行函数
- * 进行表达规则校验
- */
-function fnModalFTPCancel() {
- modalStateFTP.openByEdit = false;
- modalStateFTPFrom.resetFields();
-}
-
-/**
- * 同步文件到FTP
- * @param row
- */
-function fnSyncFileToFTP(row: Record) {
- modalStateFTP.confirmLoading = true;
- putFTPInfo(row.path)
- .then(res => {
- if (res.code === RESULT_CODE_SUCCESS) {
- message.success(t('common.operateOk'), 3);
- } else {
- message.warning(res.msg, 3);
- }
- })
- .finally(() => {
- modalStateFTP.confirmLoading = false;
- });
-}
@@ -572,8 +477,10 @@ function fnSyncFileToFTP(row: Record) {
- Setting Remote Backup
-
+
+ {{ t('views.ne.neConfigBackup.backupModal.title') }}
+
+
@@ -632,12 +539,10 @@ function fnSyncFileToFTP(row: Record) {
- Send Current File To Remote Backup
-
+
+ {{ t('views.ne.neConfigBackup.backupModal.pushFileOper') }}
+
+
@@ -676,7 +581,7 @@ function fnSyncFileToFTP(row: Record) {
) {
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
From 032d0578bb82ca595b0316adeb34d0f71cfd887d Mon Sep 17 00:00:00 2001
From: TsMask <340112800@qq.com>
Date: Fri, 25 Apr 2025 16:18:40 +0800
Subject: [PATCH 41/54] =?UTF-8?q?fix:=20=E8=B0=83=E5=BA=A6=E4=BB=BB?=
=?UTF-8?q?=E5=8A=A1=E5=8F=82=E6=95=B0=E6=9C=80=E5=A4=A7=E8=BE=93=E5=85=A5?=
=?UTF-8?q?2000=E5=AD=97=E7=AC=A6=E3=80=82=E6=97=A5=E5=BF=97=E6=9F=A5?=
=?UTF-8?q?=E7=9C=8Bid=E9=94=99=E8=AF=AF=E4=BF=AE=E5=A4=8D?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/views/monitor/job/index.vue | 2 +-
src/views/monitor/job/log.vue | 26 +++++++++++++-------------
2 files changed, 14 insertions(+), 14 deletions(-)
diff --git a/src/views/monitor/job/index.vue b/src/views/monitor/job/index.vue
index 534da650..540615d2 100644
--- a/src/views/monitor/job/index.vue
+++ b/src/views/monitor/job/index.vue
@@ -1100,7 +1100,7 @@ onMounted(() => {
diff --git a/src/views/monitor/job/log.vue b/src/views/monitor/job/log.vue
index 1ef1a221..b7cb4c43 100644
--- a/src/views/monitor/job/log.vue
+++ b/src/views/monitor/job/log.vue
@@ -118,8 +118,8 @@ let tableState: TabeStateType = reactive({
let tableColumns: ColumnsType = [
{
title: t('common.rowId'),
- dataIndex: 'jobLogId',
- align: 'center',
+ dataIndex: 'logId',
+ align: 'left',
width: 100,
},
{
@@ -132,7 +132,7 @@ let tableColumns: ColumnsType = [
title: t('views.monitor.jobLog.jobGroup'),
dataIndex: 'jobGroup',
key: 'jobGroup',
- align: 'center',
+ align: 'left',
width: 100,
},
{
@@ -142,17 +142,17 @@ let tableColumns: ColumnsType = [
width: 100,
},
{
- title: t('views.monitor.jobLog.statusFlag'),
+ title: t('views.monitor.jobLog.status'),
dataIndex: 'statusFlag',
key: 'statusFlag',
- align: 'center',
+ align: 'left',
width: 100,
},
{
title: t('views.monitor.jobLog.createTime'),
dataIndex: 'createTime',
- align: 'center',
- width: 150,
+ align: 'left',
+ width: 200,
customRender(opt) {
if (+opt.value <= 0) return '';
return parseDateToStr(+opt.value);
@@ -170,7 +170,7 @@ let tableColumns: ColumnsType = [
},
{
title: t('common.operate'),
- key: 'jobLogId',
+ key: 'logId',
align: 'left',
},
];
@@ -229,7 +229,7 @@ let modalState: ModalStateType = reactive({
open: false,
title: '任务日志',
from: {
- jobLogId: undefined,
+ logId: undefined,
jobName: '',
jobGroup: 'DEFAULT',
invokeTarget: '',
@@ -588,7 +588,7 @@ onMounted(() => {
{
}}
-
+
{{ t('common.viewText') }}
@@ -644,8 +644,8 @@ onMounted(() => {
-
- {{ modalState.from.jobLogId }}
+
+ {{ modalState.from.logId }}
From df73440d8609d28633aa79983e2dd2e8d37eb4ec Mon Sep 17 00:00:00 2001
From: TsMask <340112800@qq.com>
Date: Fri, 25 Apr 2025 16:22:38 +0800
Subject: [PATCH 42/54] =?UTF-8?q?style:=20=E8=A1=A5=E5=85=85=E5=A4=9A?=
=?UTF-8?q?=E8=AF=AD=E8=A8=80=E7=BF=BB=E8=AF=91?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/i18n/locales/en-US.ts | 63 +++++++++++++++++++++++++++++++++++++--
src/i18n/locales/zh-CN.ts | 28 +++++++++++++++--
2 files changed, 87 insertions(+), 4 deletions(-)
diff --git a/src/i18n/locales/en-US.ts b/src/i18n/locales/en-US.ts
index 0af81942..902d0405 100644
--- a/src/i18n/locales/en-US.ts
+++ b/src/i18n/locales/en-US.ts
@@ -664,6 +664,19 @@ export default {
name: "Name",
downTip: 'Confirmed to download the backup file [{txt}]?',
title: "Modify Backup {txt}",
+ backupModal: {
+ pushFileOper: "Send Current File To Remote Backup",
+ title: "Setting Remote Backup Service",
+ enable: "Enable",
+ toIp: "Service IP",
+ toIpPleace: "Please input the remote backup server IP address",
+ toPort: "Service Port",
+ username: "UserName",
+ usernamePleace: 'Please enter the service login username',
+ password: "Password",
+ dir: "Save Dir",
+ dirPleace: 'Please enter the service address target file directory',
+ }
},
neQuickSetup: {
reloadPara5G: 'Reload',
@@ -716,8 +729,43 @@ export default {
},
neData: {
common: {
+ startIMSI: 'Starting IMSI',
+ imsi: 'IMSI',
+ imsiTip: 'IMSI=MCC+MNC+MSIN',
+ imsiTip1: 'MCC=Mobile Country Code, consisting of three digits.',
+ imsiTip2: 'MNC = Mobile Network Number, consisting of two digits',
+ imsiTip3: 'MSIN = Mobile Subscriber Identification Number, consisting of 10 equal digits.',
+ imsiPlease: "Please enter IMSI correctly",
+ msisdn: 'Mobile Customer Identification Number',
+ msisdnPlease: "Please enter the Mobile Customer Identification Number correctly",
+ loadDataConfirm: 'Confirmed to reload data?',
+ loadData: 'Load Data',
+ loadDataTip: 'Successfully fetched loaded data: {num} items, the system is internally updating the data, it will take about {timer} seconds, please wait!!!!!.',
+ batchOper: 'Batch Operation',
+ batchAddText: 'Batch Addition',
+ batchDelText: 'Batch Deletion',
+ batchUpdateText: 'Batch Update',
+ batchNum: 'Number of releases',
+ checkDel:'Check Delete',
importTemplate: 'Download Template',
},
+ udmVOIP: {
+ startUsername: 'Starting username',
+ username: 'username',
+ usernamePlease: "Please enter your username correctly",
+ password: "password",
+ passwordPlease: "Please enter your password correctly",
+ addTitle: 'Add VOIP subscriber',
+ delTip: 'Confirm that you want to delete the information of VOIP user as [{num}]?',
+ exportTip: "Confirm exporting xlsx table files based on search criteria?",
+ },
+ udmVolteIMS: {
+ addTitle: 'Addition of new IMS subscribers',
+ vniTip: 'Example: ims.mnc000.mcc000.3gppnetwork.org',
+ vniPlease: 'Please enter VNI correctly',
+ delTip: 'Are you sure you want to delete the information of IMS signing as [{num}]?',
+ exportTip: "Confirm exporting xlsx table files based on search criteria?",
+ },
baseStation: {
list: "List",
topology: "Topology",
@@ -740,6 +788,12 @@ export default {
exportTip: "Confirm exporting xlsx table files based on search criteria?",
importDataEmpty: "Imported data is empty",
},
+ backupData: {
+ auth: "UDM Authentication",
+ sub: "UDM Subscribers",
+ voip: "VoIP Authentication",
+ volte: "IMS Subscribers",
+ }
},
neUser: {
auth: {
@@ -1205,12 +1259,17 @@ export default {
tailLines: 'End Lines',
},
exportFile:{
- fileName:'File Source',
+ fileSource:'File Source',
+ fileSourcePlease:'Please select the source of the document',
downTip: "Confirm the download file name is [{fileName}] File?",
downTipErr: "Failed to get file",
deleteTip: "Confirm the delete file name is [{fileName}] File?",
deleteTipErr: "Failed to delete file",
- selectTip:"Please select File Name",
+ operateLog:'Operation Log',
+ cdrIMS:'Voice CDR',
+ cdrSMF:'Data CDR',
+ cdrSMSC:'SMS CDR',
+ cdrSGWC:'Roaming Data CDR',
}
},
monitor: {
diff --git a/src/i18n/locales/zh-CN.ts b/src/i18n/locales/zh-CN.ts
index 58bd9392..bdd61282 100644
--- a/src/i18n/locales/zh-CN.ts
+++ b/src/i18n/locales/zh-CN.ts
@@ -664,6 +664,19 @@ export default {
name: "名称",
downTip: '确认要下载备份文件【{txt}】吗?',
title: "修改备份信息 {txt}",
+ backupModal: {
+ pushFileOper: "将当前文件发送到远程备份",
+ title: "设置远程备份服务",
+ enable: "启用",
+ toIp: "服务IP",
+ toIpPleace: "请输入远程备份服务器 IP 地址",
+ toPort: "服务端口",
+ username: "登录用户名",
+ usernamePleace: '请输入服务登录用户名',
+ password: "登录密码",
+ dir: "保存目录",
+ dirPleace: '请输入服务地址目标文件目录',
+ }
},
neQuickSetup: {
reloadPara5G: '刷新',
@@ -775,6 +788,12 @@ export default {
exportTip: "确认根据搜索条件导出xlsx表格文件吗?",
importDataEmpty: "导入数据为空",
},
+ backupData: {
+ auth: "UDM鉴权用户",
+ sub: "UDM签约用户",
+ voip: "VOIP鉴权用户",
+ volte: "IMS签约用户",
+ }
},
neUser: {
auth: {
@@ -1240,12 +1259,17 @@ export default {
tailLines: '末尾行数',
},
exportFile:{
- fileName:'文件来源',
+ fileSource:'文件来源',
+ fileSourcePlease:'请选择文件来源',
downTip: "确认下载文件名为 【{fileName}】 文件?",
downTipErr: "文件获取失败",
deleteTip: "确认删除文件名为 【{fileName}】 文件?",
deleteTipErr: "文件删除失败",
- selectTip:"请选择文件名",
+ operateLog:'操作日志',
+ cdrIMS:'语音话单',
+ cdrSMF:'数据话单',
+ cdrSMSC:'短信话单',
+ cdrSGWC:'漫游数据话单',
}
},
monitor: {
From 19eea9fe9b15005731069f330bde7bd3b16e679d Mon Sep 17 00:00:00 2001
From: TsMask <340112800@qq.com>
Date: Fri, 25 Apr 2025 17:23:38 +0800
Subject: [PATCH 43/54] =?UTF-8?q?feat:=20UDMVolte=E7=94=A8=E6=88=B7?=
=?UTF-8?q?=E7=89=B9=E6=AE=8AVoIP=E6=95=B0=E6=8D=AE?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
public/neDataImput/udm_volte_template.txt | 3 +-
src/i18n/locales/en-US.ts | 2 +
src/i18n/locales/zh-CN.ts | 2 +
src/views/neData/backup-data/index.vue | 412 ++++++++++++++++++++++
src/views/neData/udm-auth/index.vue | 3 +-
src/views/neData/udm-sub/index.vue | 3 +-
src/views/neData/udm-voip/index.vue | 1 +
src/views/neData/udm-volte/index.vue | 83 ++++-
8 files changed, 492 insertions(+), 17 deletions(-)
create mode 100644 src/views/neData/backup-data/index.vue
diff --git a/public/neDataImput/udm_volte_template.txt b/public/neDataImput/udm_volte_template.txt
index 2abb96c7..c23508f7 100644
--- a/public/neDataImput/udm_volte_template.txt
+++ b/public/neDataImput/udm_volte_template.txt
@@ -1,3 +1,4 @@
+#vlote=0 MSISDN and IMSI need to be filled in the same way.
#imsi,msisdn,vlote,vni
460996650000580,62357000580,1,ims.mnc000.mcc460.3gppnetwork.org
-460996650000581,62357000581,1,ims.mnc000.mcc460.3gppnetwork.org
\ No newline at end of file
+62357000581,62357000581,0,ims.mnc000.mcc460.3gppnetwork.org
diff --git a/src/i18n/locales/en-US.ts b/src/i18n/locales/en-US.ts
index 902d0405..cb87a8b1 100644
--- a/src/i18n/locales/en-US.ts
+++ b/src/i18n/locales/en-US.ts
@@ -760,6 +760,8 @@ export default {
exportTip: "Confirm exporting xlsx table files based on search criteria?",
},
udmVolteIMS: {
+ startMSISDN: 'Starting MSISDN',
+ voipTip: 'When VoIP is selected MSISDN will be equal to IMSI',
addTitle: 'Addition of new IMS subscribers',
vniTip: 'Example: ims.mnc000.mcc000.3gppnetwork.org',
vniPlease: 'Please enter VNI correctly',
diff --git a/src/i18n/locales/zh-CN.ts b/src/i18n/locales/zh-CN.ts
index bdd61282..9bc99748 100644
--- a/src/i18n/locales/zh-CN.ts
+++ b/src/i18n/locales/zh-CN.ts
@@ -760,6 +760,8 @@ export default {
exportTip: "确认根据搜索条件导出xlsx表格文件吗?",
},
udmVolteIMS: {
+ startMSISDN: '起始MSISDN',
+ voipTip: '当选择VoIP时MSISDN会等于IMSI',
addTitle: '新增IMS签约用户',
vniTip: '示例:ims.mnc000.mcc000.3gppnetwork.org',
vniPlease: '请正确输入VNI',
diff --git a/src/views/neData/backup-data/index.vue b/src/views/neData/backup-data/index.vue
new file mode 100644
index 00000000..2b34a0d7
--- /dev/null
+++ b/src/views/neData/backup-data/index.vue
@@ -0,0 +1,412 @@
+
+
+
+
+
+
+
+
+
+
+ {{ t('views.logManage.exportFile.fileSource') }}:
+
+
+
+ {{ t('views.logManage.neFile.nePath') }}:
+
+
+
+ {{ queryParams.path }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('views.ne.neConfigBackup.backupModal.title') }}
+
+
+
+
+
+
+ {{ t('common.reloadText') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('views.ne.neConfigBackup.backupModal.pushFileOper') }}
+
+
+
+
+
+
+ {{ t('common.downloadText') }}
+
+
+
+
+
+ {{ t('common.deleteText') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/neData/udm-auth/index.vue b/src/views/neData/udm-auth/index.vue
index 2e14e3a1..4b759502 100644
--- a/src/views/neData/udm-auth/index.vue
+++ b/src/views/neData/udm-auth/index.vue
@@ -780,11 +780,12 @@ onMounted(() => {
-
+
diff --git a/src/views/neData/udm-sub/index.vue b/src/views/neData/udm-sub/index.vue
index 595c4d40..8ef6cd0c 100644
--- a/src/views/neData/udm-sub/index.vue
+++ b/src/views/neData/udm-sub/index.vue
@@ -1171,11 +1171,12 @@ onMounted(() => {
-
+
diff --git a/src/views/neData/udm-voip/index.vue b/src/views/neData/udm-voip/index.vue
index a1a138ec..6d2288b6 100644
--- a/src/views/neData/udm-voip/index.vue
+++ b/src/views/neData/udm-voip/index.vue
@@ -584,6 +584,7 @@ onMounted(() => {
v-model:value="queryParams.neId"
:options="neOtions"
:placeholder="t('common.selectPlease')"
+ :disabled="modalState.loadDataLoading"
@change="fnGetList(1)"
/>
diff --git a/src/views/neData/udm-volte/index.vue b/src/views/neData/udm-volte/index.vue
index 2bd168eb..c96b44ae 100644
--- a/src/views/neData/udm-volte/index.vue
+++ b/src/views/neData/udm-volte/index.vue
@@ -291,6 +291,12 @@ function fnModalOk() {
const from = JSON.parse(JSON.stringify(modalState.from));
from.neId = queryParams.neId || '-';
+ // 如果是VoIP, 则MSISDN和IMSI相同
+ if (from.tag === '0') {
+ modalState.from.imsi = from.msisdn;
+ from.imsi = from.msisdn;
+ }
+
// 校验规则
let validateArr = ['imsi', 'msisdn', 'vni', 'tag'];
if (modalState.isBatch) {
@@ -550,7 +556,7 @@ function fnModalUploadImportUpload(file: File) {
if (res.code === RESULT_CODE_SUCCESS) {
return importUDMVOIP({
neId: neID,
- uploadPath: res.data,
+ uploadPath: res.data,
});
}
return res;
@@ -639,6 +645,7 @@ onMounted(() => {
v-model:value="queryParams.neId"
:options="neOtions"
:placeholder="t('common.selectPlease')"
+ :disabled="modalState.loadDataLoading"
@change="fnGetList(1)"
/>
@@ -905,6 +912,19 @@ onMounted(() => {
>
+
+
+
+ {
+
+
+
+
+
+ {{ t('views.neData.common.msisdn') }}
+
+
+
+
+
+
@@ -949,6 +994,19 @@ onMounted(() => {
+
+
+
+ {
@@ -1013,18 +1080,6 @@ onMounted(() => {
-
-
-
-
From f76311cf1bb71cbf560071441c35de479907451a Mon Sep 17 00:00:00 2001
From: TsMask <340112800@qq.com>
Date: Fri, 25 Apr 2025 17:31:25 +0800
Subject: [PATCH 44/54] =?UTF-8?q?chore:=20=E7=BC=96=E8=AF=91=E6=96=87?=
=?UTF-8?q?=E4=BB=B6=E5=BC=95=E7=94=A8=E7=BC=BA=E5=A4=B1?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/views/traceManage/pcap/file.vue | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/views/traceManage/pcap/file.vue b/src/views/traceManage/pcap/file.vue
index cba89530..c250c630 100644
--- a/src/views/traceManage/pcap/file.vue
+++ b/src/views/traceManage/pcap/file.vue
@@ -7,7 +7,7 @@ import { Modal, message } from 'ant-design-vue/es';
import { parseDateToStr } from '@/utils/date-utils';
import { getNeDirZip, getNeFile, listNeFiles } from '@/api/tool/neFile';
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
-import ViewDrawer from '@/views/logManage/neFile/components/ViewDrawer.vue';
+import ViewDrawer from '@/views/ne/neFile/components/ViewDrawer.vue';
import useNeInfoStore from '@/store/modules/neinfo';
import useTabsStore from '@/store/modules/tabs';
import useI18n from '@/hooks/useI18n';
From 2de97883731b4ddafeff5d639feb00d33171b2aa Mon Sep 17 00:00:00 2001
From: TsMask <340112800@qq.com>
Date: Sun, 27 Apr 2025 17:23:33 +0800
Subject: [PATCH 45/54] =?UTF-8?q?ref=20:=20=E9=87=8D=E6=9E=84=E4=BB=A4?=
=?UTF-8?q?=E7=89=8C=E7=AE=A1=E7=90=86=E9=80=BB=E8=BE=91,=EF=BC=8C?=
=?UTF-8?q?=E7=BB=9F=E4=B8=80=E7=8A=B6=E6=80=81=E7=A0=81=E8=AF=86=E5=88=AB?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/api/{login.ts => auth.ts} | 51 +++++--
src/api/index.ts | 60 --------
src/api/profile.ts | 13 --
src/api/router.ts | 12 --
src/api/system/user.ts | 13 ++
src/components/ForcePasswdChange/index.vue | 2 +-
src/constants/result-constants.ts | 29 ++--
src/constants/token-constants.ts | 9 +-
src/i18n/locales/zh-CN.ts | 2 +-
src/plugins/auth-token.ts | 54 ++++---
src/plugins/http-fetch.ts | 139 +++++++++---------
src/plugins/ws-websocket.ts | 4 +-
src/router/index.ts | 4 +-
src/store/modules/app.ts | 5 +-
src/store/modules/neinfo.ts | 4 +-
src/store/modules/router.ts | 4 +-
src/store/modules/user.ts | 22 +--
src/views/logManage/mml/index.vue | 2 +-
src/views/login.vue | 37 +++--
src/views/neData/base-station/list.vue | 1 +
src/views/register.vue | 2 +-
.../system/quick-start/components/Done.vue | 5 +-
.../system/quick-start/components/Start.vue | 8 +-
23 files changed, 229 insertions(+), 253 deletions(-)
rename src/api/{login.ts => auth.ts} (61%)
delete mode 100644 src/api/router.ts
diff --git a/src/api/login.ts b/src/api/auth.ts
similarity index 61%
rename from src/api/login.ts
rename to src/api/auth.ts
index e66963c6..eab43a76 100644
--- a/src/api/login.ts
+++ b/src/api/auth.ts
@@ -1,15 +1,28 @@
-import { CACHE_SESSION_CRYPTO_API } from '@/constants/cache-keys-constants';
-import { sessionGet } from '@/utils/cache-session-utils';
import { request } from '@/plugins/http-fetch';
-// 登录方法
+/**
+ * 登录方法
+ * @param data 数据
+ * @returns 结果
+ */
export function login(data: Record) {
return request({
- url: '/login',
+ url: '/auth/login',
method: 'POST',
data: data,
whithToken: false,
- crypto: sessionGet(CACHE_SESSION_CRYPTO_API) !== 'false',
+ });
+}
+
+/**
+ * 退出方法
+ * @returns object
+ */
+export function logout() {
+ return request({
+ url: '/auth/logout',
+ method: 'POST',
+ repeatSubmit: false,
});
}
@@ -20,11 +33,24 @@ export function login(data: Record) {
*/
export function register(data: Record) {
return request({
- url: '/register',
+ url: '/auth/register',
method: 'POST',
data: data,
whithToken: false,
- crypto: sessionGet(CACHE_SESSION_CRYPTO_API) !== 'false',
+ });
+}
+
+/**
+ * 刷新登录令牌
+ * @param data 数据
+ * @returns 结果
+ */
+export function refreshToken(refreshToken: string) {
+ return request({
+ url: '/auth/refresh-token',
+ method: 'POST',
+ data: { refreshToken },
+ whithToken: false,
});
}
@@ -40,16 +66,15 @@ export function getInfo() {
}
/**
- * 退出方法
+ * 获取路由
* @returns object
*/
-export function logout() {
+export const getRouter = () => {
return request({
- url: '/logout',
- method: 'POST',
- repeatSubmit: false,
+ url: '/router',
+ method: 'GET',
});
-}
+};
/**
* 获取验证码
diff --git a/src/api/index.ts b/src/api/index.ts
index 4806e43c..f7d04d31 100644
--- a/src/api/index.ts
+++ b/src/api/index.ts
@@ -1,65 +1,5 @@
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
import { request } from '@/plugins/http-fetch';
-import { parseDateToStr } from '@/utils/date-utils';
-import { NE_TYPE_LIST } from '@/constants/ne-constants';
-
-/**
- * 查询公告列表
- * @param query 查询参数
- * @returns object
- */
-export async function listMain() {
- const result = await request({
- url: '/api/rest/systemManagement/v1/elementType/all/objectType/systemState',
- method: 'GET',
- timeout: 60_000,
- });
- // console.log(result);
- let realData = result.data.data;
- const mergedData = realData.map((obj: any) => {
- // console.log(obj);
- const [key, value] = Object.entries(obj)[0];
- const ipAddress = (value as any).ipAddress;
- const systemState = (value as any).systemState;
- const serialNum = (value as any).serialNum;
- const version = (value as any).version;
-
- const errCode = systemState && systemState['errorCode'];
- var time = new Date();
- // console.log(key, value);
- let mergedObj;
- if (errCode === undefined && systemState) {
- mergedObj = {
- ...systemState,
- refresh: parseDateToStr(time),
- ipAddress: ipAddress,
- name: key.split('/').join('_'),
- status: 'Normal',
- };
- } else {
- mergedObj = {
- version,
- refresh: parseDateToStr(time),
- ipAddress,
- serialNum,
- name: key.split('/').join('_'),
- expiryDate: '-',
- status: 'Abnormal',
- };
- }
- return mergedObj;
- });
- //通过sort进行冒泡排序
- mergedData.sort((a: any, b: any) => {
- const typeA = NE_TYPE_LIST.indexOf(a.name.split('_')[0]);
- const typeB = NE_TYPE_LIST.indexOf(b.name.split('_')[0]);
- if (typeA === -1) return 1; // 如果不在特定顺序中,排到后面
- if (typeB === -1) return -1; // 如果不在特定顺序中,排到后面
- return typeA - typeB;
- });
-
- return mergedData;
-}
/**
* 获取服务器时间
diff --git a/src/api/profile.ts b/src/api/profile.ts
index 3e52e664..63295ed3 100644
--- a/src/api/profile.ts
+++ b/src/api/profile.ts
@@ -37,16 +37,3 @@ export function updateUserPassword(oldPassword: string, newPassword: string) {
data: { oldPassword, newPassword },
});
}
-
-/**
- * 用户强制重置密码
- * @param password 密码
- * @returns object
- */
-export function updateUserPasswordForce(password: string) {
- return request({
- url: '/system/user/profile/password-force',
- method: 'PUT',
- data: { password },
- });
-}
diff --git a/src/api/router.ts b/src/api/router.ts
deleted file mode 100644
index 4846be2b..00000000
--- a/src/api/router.ts
+++ /dev/null
@@ -1,12 +0,0 @@
-import { request } from '@/plugins/http-fetch';
-
-/**
- * 获取路由
- * @returns object
- */
-export const getRouters = () => {
- return request({
- url: '/router',
- method: 'GET',
- });
-};
diff --git a/src/api/system/user.ts b/src/api/system/user.ts
index 4563069f..f59758f8 100644
--- a/src/api/system/user.ts
+++ b/src/api/system/user.ts
@@ -136,3 +136,16 @@ export function changeUserStatus(
data: { userId, statusFlag },
});
}
+
+/**
+ * 用户强制重置密码
+ * @param password 密码
+ * @returns object
+ */
+export function updateUserPasswordForce(password: string) {
+ return request({
+ url: '/system/user/profile/password-force',
+ method: 'PUT',
+ data: { password },
+ });
+}
diff --git a/src/components/ForcePasswdChange/index.vue b/src/components/ForcePasswdChange/index.vue
index c433ad35..0229ffd8 100644
--- a/src/components/ForcePasswdChange/index.vue
+++ b/src/components/ForcePasswdChange/index.vue
@@ -4,7 +4,7 @@ import { regExpPasswd, regExpUserName } from '@/utils/regular-utils';
import { Form, message, Modal } from 'ant-design-vue';
import useI18n from '@/hooks/useI18n';
import useUserStore from '@/store/modules/user';
-import { updateUserPasswordForce } from '@/api/profile';
+import { updateUserPasswordForce } from '@/api/system/user';
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
import { getConfigKey } from '@/api/system/config';
const userStore = useUserStore();
diff --git a/src/constants/result-constants.ts b/src/constants/result-constants.ts
index ae7dfeeb..76332a40 100644
--- a/src/constants/result-constants.ts
+++ b/src/constants/result-constants.ts
@@ -1,14 +1,14 @@
/**响应-code加密数据 */
-export const RESULT_CODE_ENCRYPT = 2;
+export const RESULT_CODE_ENCRYPT = 200999;
/**响应-msg加密数据 */
export const RESULT_MSG_ENCRYPT: Record = {
zh_CN: '加密!',
- en_US: 'encrypt!',
+ en_US: 'Encrypt!',
};
/**响应-code正常成功 */
-export const RESULT_CODE_SUCCESS = 1;
+export const RESULT_CODE_SUCCESS = 200001;
/**响应-msg正常成功 */
export const RESULT_MSG_SUCCESS: Record = {
@@ -17,7 +17,16 @@ export const RESULT_MSG_SUCCESS: Record = {
};
/**响应-code错误失败 */
-export const RESULT_CODE_ERROR = 0;
+export const RESULT_CODE_ERROR = 400001;
+
+/**响应-code错误异常 */
+export const RESULT_CODE_EXCEPTION = 500001;
+
+/**响应-服务器连接出错 */
+export const RESULT_MSG_SERVER_ERROR: Record = {
+ zh_CN: '服务器连接出错!',
+ en_US: 'Server Connection Error!',
+};
/**响应-msg错误失败 */
export const RESULT_MSG_ERROR: Record = {
@@ -37,18 +46,6 @@ export const RESULT_MSG_NOT_TYPE: Record = {
en_US: 'Unknown Response Data Type!',
};
-/**响应-服务器连接出错 */
-export const RESULT_MSG_SERVER_ERROR: Record = {
- zh_CN: '服务器连接出错!',
- en_US: 'Server Connection Error!',
-};
-
-/**响应-请求地址未找到 */
-export const RESULT_MSG_URL_NOTFOUND: Record = {
- zh_CN: '请求地址未找到!',
- en_US: 'Request Address Not Found!',
-};
-
/**响应-数据正在处理,请勿重复提交 */
export const RESULT_MSG_URL_RESUBMIT: Record = {
zh_CN: '数据正在处理,请勿重复提交!',
diff --git a/src/constants/token-constants.ts b/src/constants/token-constants.ts
index 03d2cc87..44316013 100644
--- a/src/constants/token-constants.ts
+++ b/src/constants/token-constants.ts
@@ -2,10 +2,13 @@
export const TOKEN_RESPONSE_FIELD = 'accessToken';
/**令牌-请求头标识前缀 */
-export const TOKEN_KEY_PREFIX = 'Bearer ';
+export const TOKEN_KEY_PREFIX = 'Bearer';
/**令牌-请求头标识 */
export const TOKEN_KEY = 'Authorization';
-/**令牌-存放Cookie标识 */
-export const TOKEN_COOKIE = 'AuthOMC';
+/**令牌-访问令牌存放Cookie标识 */
+export const TOKEN_ACCESS_COOKIE = 'omc_access';
+
+/**令牌-刷新令牌存放Cookie标识 */
+export const TOKEN_REFRESH_COOKIE = 'omc_refresh';
diff --git a/src/i18n/locales/zh-CN.ts b/src/i18n/locales/zh-CN.ts
index 9bc99748..4a544f38 100644
--- a/src/i18n/locales/zh-CN.ts
+++ b/src/i18n/locales/zh-CN.ts
@@ -1224,7 +1224,7 @@ export default {
type:'网元类型',
neId:'网元唯一标识',
MML:'MML',
- logTime:'log Time'
+ logTime:'记录时间'
},
forwarding:{
alarmId:'告警唯一标识',
diff --git a/src/plugins/auth-token.ts b/src/plugins/auth-token.ts
index 536d54b1..09b420b4 100644
--- a/src/plugins/auth-token.ts
+++ b/src/plugins/auth-token.ts
@@ -1,25 +1,45 @@
import Cookies from 'js-cookie';
-import { TOKEN_COOKIE } from '@/constants/token-constants';
-import { localRemove, localSet } from '@/utils/cache-local-utils';
import {
- CACHE_LOCAL_LOCK_PASSWD,
- CACHE_LOCAL_MASK,
-} from '@/constants/cache-keys-constants';
+ TOKEN_ACCESS_COOKIE,
+ TOKEN_REFRESH_COOKIE,
+} from '@/constants/token-constants';
-/**获取cookis中Token字符串 */
-export function getToken(): string {
- return Cookies.get(TOKEN_COOKIE) || '';
+/**获取访问令牌 */
+export function getAccessToken(): string {
+ return Cookies.get(TOKEN_ACCESS_COOKIE) || '';
}
-/**设置cookis中Token字符串 */
-export function setToken(token: string): void {
- Cookies.set(TOKEN_COOKIE, token || '');
- localSet(CACHE_LOCAL_MASK, 'none');
+/**
+ * 设置访问令牌
+ * @param token token字符串
+ * @param exp 过期时间(秒)
+ */
+export function setAccessToken(token: string, exp: number): void {
+ const expires = new Date(new Date().getTime() + exp * 1000);
+ Cookies.set(TOKEN_ACCESS_COOKIE, token, { expires });
}
-/**移除cookis中Token字符串,localStorage中锁屏字符串 */
-export function removeToken(): void {
- Cookies.remove(TOKEN_COOKIE);
- localRemove(CACHE_LOCAL_MASK);
- localRemove(CACHE_LOCAL_LOCK_PASSWD);
+/**移除访问令牌 */
+export function delAccessToken(): void {
+ Cookies.remove(TOKEN_ACCESS_COOKIE);
+}
+
+/**获取刷新令牌 */
+export function getRefreshToken(): string {
+ return Cookies.get(TOKEN_REFRESH_COOKIE) || '';
+}
+
+/**
+ * 设置刷新令牌
+ * @param token token字符串
+ * @param exp 过期时间(秒)
+ */
+export function setRefreshToken(token: string, exp: number): void {
+ const expires = new Date(new Date().getTime() + exp * 1000);
+ Cookies.set(TOKEN_REFRESH_COOKIE, token, { expires });
+}
+
+/**移除刷新令牌 */
+export function delRefreshToken(): void {
+ Cookies.remove(TOKEN_REFRESH_COOKIE);
}
diff --git a/src/plugins/http-fetch.ts b/src/plugins/http-fetch.ts
index b5f38c97..f3673262 100644
--- a/src/plugins/http-fetch.ts
+++ b/src/plugins/http-fetch.ts
@@ -1,10 +1,16 @@
-import { getToken, removeToken } from '@/plugins/auth-token';
+import {
+ getAccessToken,
+ setAccessToken,
+ delAccessToken,
+ getRefreshToken,
+ setRefreshToken,
+ delRefreshToken,
+} from '@/plugins/auth-token';
import {
sessionGet,
sessionGetJSON,
sessionSetJSON,
} from '@/utils/cache-session-utils';
-import { localGet } from '@/utils/cache-local-utils';
import { TOKEN_KEY, TOKEN_KEY_PREFIX } from '@/constants/token-constants';
import {
CACHE_LOCAL_I18N,
@@ -18,6 +24,7 @@ import {
import {
RESULT_CODE_ENCRYPT,
RESULT_CODE_ERROR,
+ RESULT_CODE_EXCEPTION,
RESULT_CODE_SUCCESS,
RESULT_MSG_ENCRYPT,
RESULT_MSG_ERROR,
@@ -25,10 +32,11 @@ import {
RESULT_MSG_SERVER_ERROR,
RESULT_MSG_SUCCESS,
RESULT_MSG_TIMEOUT,
- RESULT_MSG_URL_NOTFOUND,
RESULT_MSG_URL_RESUBMIT,
} from '@/constants/result-constants';
import { decryptAES, encryptAES } from '@/utils/encrypt-utils';
+import { localGet } from '@/utils/cache-local-utils';
+import { refreshToken } from '@/api/auth';
/**响应结果类型 */
export type ResultType = {
@@ -61,7 +69,7 @@ type OptionsType = {
/**请求地址 */
url: string;
/**请求方法 */
- method: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';
+ method: 'GET' | 'POST' | 'PUT' | 'DELETE';
/**请求头 */
headers?: HeadersInit;
/**地址栏参数 */
@@ -133,16 +141,21 @@ function beforeRequest(options: OptionsType): OptionsType | Promise {
Reflect.set(options.headers, 'Accept-Language', `${language};q=0.9`);
// 是否需要设置 token
- const token = getToken();
- if (options.whithToken && token) {
- Reflect.set(options.headers, TOKEN_KEY, TOKEN_KEY_PREFIX + token);
+ const accessToken = getAccessToken();
+ if (options.whithToken && accessToken) {
+ Reflect.set(
+ options.headers,
+ TOKEN_KEY,
+ TOKEN_KEY_PREFIX + ' ' + accessToken
+ );
}
// 是否需要防止数据重复提交
if (
options.repeatSubmit &&
options.dataType === 'json' &&
- ['post', 'put'].includes(options.method)
+ !(options.data instanceof FormData) &&
+ ['POST', 'PUT'].includes(options.method)
) {
const requestObj: RepeatSubmitType = {
url: options.url,
@@ -212,13 +225,31 @@ function beforeRequest(options: OptionsType): OptionsType | Promise {
return options;
}
-/**请求后的拦截 */
-function interceptorResponse(res: ResultType): ResultType | Promise {
+/**响应前的拦截 */
+async function beforeResponse(
+ options: OptionsType,
+ res: ResultType
+): Promise {
// console.log('请求后的拦截', res);
// 登录失效时,移除授权令牌并重新刷新页面
- if (res.code === 401) {
- removeToken();
+ // 登录失效时,移除访问令牌并重新请求
+ if (res.code === 401001) {
+ const result = await refreshToken(getRefreshToken());
+ // 更新访问令牌和刷新令牌
+ if (result.code === RESULT_CODE_SUCCESS) {
+ setAccessToken(result.data.accessToken, result.data.refreshExpiresIn);
+ setRefreshToken(result.data.refreshToken, result.data.refreshExpiresIn);
+ return await request(options);
+ } else {
+ delAccessToken();
+ delRefreshToken();
+ window.location.reload();
+ }
+ }
+ if ([401002, 401003].includes(res.code)) {
+ delAccessToken();
+ delRefreshToken();
window.location.reload();
}
@@ -271,43 +302,45 @@ function interceptorResponse(res: ResultType): ResultType | Promise {
* @returns 返回 Promise
*/
export async function request(options: OptionsType): Promise {
- options = Object.assign({}, FATCH_OPTIONS, options);
- let timeoutId: any = 0;
+ let reqOptions = Object.assign({}, FATCH_OPTIONS, options);
+
// 请求超时控制请求终止
- if (!options.signal) {
+ let timeoutId: any = null;
+ if (!reqOptions.signal) {
const controller = new AbortController();
- const { signal } = controller;
- options.signal = signal;
+ reqOptions.signal = controller.signal;
timeoutId = setTimeout(() => {
controller.abort(); // 终止请求
- }, options.timeout);
+ }, reqOptions.timeout);
}
// 检查请求拦截
- const beforeReq = beforeRequest(options);
+ const beforeReq = beforeRequest(reqOptions);
if (beforeReq instanceof Promise) {
return await beforeReq;
}
- options = beforeReq;
+ reqOptions = beforeReq;
// 判断用户传递的URL是否http或/开头
- if (!options.url.startsWith('http')) {
- const uri = options.url.startsWith('/') ? options.url : `/${options.url}`;
- options.url = options.baseUrl + uri;
+ if (!reqOptions.url.startsWith('http')) {
+ const uri = reqOptions.url.startsWith('/')
+ ? reqOptions.url
+ : `/${reqOptions.url}`;
+ reqOptions.url = reqOptions.baseUrl + uri;
}
try {
- const res = await fetch(options.url, options);
+ const res = await fetch(reqOptions.url, reqOptions);
// console.log('请求结果:', res);
-
- // 状态码拦截处理
- const reqNot = stateCode(res);
- if (reqNot != false) {
- return reqNot;
+ if (res.status === 500) {
+ return {
+ code: RESULT_CODE_EXCEPTION,
+ msg: RESULT_MSG_SERVER_ERROR[language],
+ };
}
// 根据响应数据类型返回
- switch (options.responseType) {
+ switch (reqOptions.responseType) {
case 'text': // 文本数据
const str = await res.text();
return {
@@ -317,11 +350,7 @@ export async function request(options: OptionsType): Promise {
case 'json': // json格式数据
const result = await res.json();
// 请求后的拦截
- const beforeRes = interceptorResponse(result);
- if (beforeRes instanceof Promise) {
- return await beforeRes;
- }
- return result;
+ return await beforeResponse(options, result);
case 'blob': // 二进制数据则直接返回
case 'arrayBuffer':
const contentType = res.headers.get('content-type') || '';
@@ -330,7 +359,7 @@ export async function request(options: OptionsType): Promise {
return result as ResultType;
}
const data =
- options.responseType === 'blob'
+ reqOptions.responseType === 'blob'
? await res.blob()
: await res.arrayBuffer();
return {
@@ -356,41 +385,7 @@ export async function request(options: OptionsType): Promise {
}
throw error;
} finally {
- clearTimeout(timeoutId); // 请求成功,清除超时计时器
+ clearTimeout(timeoutId); // 清除超时计时器
+ timeoutId = null;
}
}
-
-/**
- * 判断状态码处理结果信息(不可处理)
- * @param res 请求结果
- * @returns
- */
-function stateCode(res: Response) {
- // 网络异常
- if (res.status === 500) {
- return {
- code: RESULT_CODE_ERROR,
- msg: RESULT_MSG_SERVER_ERROR[language],
- };
- }
- // 上传文件成功无内容返回
- if (res.status === 204 || res.statusText === 'No Content') {
- return {
- code: RESULT_CODE_SUCCESS,
- msg: RESULT_MSG_SUCCESS[language],
- };
- }
- // 地址找不到
- if (res.status === 404 || res.status === 405) {
- return {
- code: RESULT_CODE_ERROR,
- msg: RESULT_MSG_URL_NOTFOUND[language],
- };
- }
- // 身份授权
- if (res.status === 401) {
- removeToken();
- window.location.reload();
- }
- return false;
-}
diff --git a/src/plugins/ws-websocket.ts b/src/plugins/ws-websocket.ts
index 623cd7cf..ca2c00a0 100644
--- a/src/plugins/ws-websocket.ts
+++ b/src/plugins/ws-websocket.ts
@@ -1,5 +1,5 @@
import { sessionGet } from '@/utils/cache-session-utils';
-import { getToken } from './auth-token';
+import { getAccessToken } from './auth-token';
import { localGet } from '@/utils/cache-local-utils';
import { CACHE_LOCAL_I18N } from '@/constants/cache-keys-constants';
import { TOKEN_RESPONSE_FIELD } from '@/constants/token-constants';
@@ -92,7 +92,7 @@ export class WS {
// 地址栏参数
let params = Object.assign({}, options.params, {
// 设置 token
- [TOKEN_RESPONSE_FIELD]: getToken(),
+ [TOKEN_RESPONSE_FIELD]: getAccessToken(),
// 多语言
['language']: localGet(CACHE_LOCAL_I18N) || 'en_US',
});
diff --git a/src/router/index.ts b/src/router/index.ts
index b16ea27c..6a2755d3 100644
--- a/src/router/index.ts
+++ b/src/router/index.ts
@@ -8,7 +8,7 @@ import NProgress from 'nprogress';
import 'nprogress/nprogress.css';
import BasicLayout from '../layouts/BasicLayout.vue';
import BlankLayout from '../layouts/BlankLayout.vue';
-import { getToken } from '@/plugins/auth-token';
+import { getAccessToken } from '@/plugins/auth-token';
import { validHttp } from '@/utils/regular-utils';
import useUserStore from '@/store/modules/user';
import useAppStore from '@/store/modules/app';
@@ -182,7 +182,7 @@ router.beforeEach(async (to, from, next) => {
next({ name: 'Index' });
}
- let token = getToken();
+ let token = getAccessToken();
// 免用户登录认证
if (!appStore.loginAuth) {
diff --git a/src/store/modules/app.ts b/src/store/modules/app.ts
index 1634e3cd..b2664c3a 100644
--- a/src/store/modules/app.ts
+++ b/src/store/modules/app.ts
@@ -4,7 +4,7 @@ import {
CACHE_SESSION_CRYPTO_API,
} from '@/constants/cache-keys-constants';
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
-import { removeToken } from '@/plugins/auth-token';
+import { delAccessToken, delRefreshToken } from '@/plugins/auth-token';
import { parseUrlPath } from '@/plugins/file-static-url';
import { localGet, localSet } from '@/utils/cache-local-utils';
import { sessionSet } from '@/utils/cache-session-utils';
@@ -94,7 +94,8 @@ const useAppStore = defineStore('app', {
this.bootloader = res.data.bootloader === 'true';
// 引导时
if (this.bootloader) {
- removeToken();
+ delAccessToken();
+ delRefreshToken();
}
this.loginAuth = res.data.loginAuth !== 'false';
this.cryptoApi = res.data.cryptoApi !== 'false';
diff --git a/src/store/modules/neinfo.ts b/src/store/modules/neinfo.ts
index 13bab5ee..ebf4cd9f 100644
--- a/src/store/modules/neinfo.ts
+++ b/src/store/modules/neinfo.ts
@@ -52,7 +52,7 @@ const useNeInfoStore = defineStore('neinfo', {
async fnNelist() {
// 有数据不请求
if (this.neList.length > 0) {
- return { code: 1, data: this.neList, msg: 'success' };
+ return { code: RESULT_CODE_SUCCESS, data: this.neList, msg: 'success' };
}
const res = await listAllNeInfo({
bandStatus: false,
@@ -79,7 +79,7 @@ const useNeInfoStore = defineStore('neinfo', {
async fnNeTaskPerformance() {
// 有数据不请求
if (this.perMeasurementList.length > 0) {
- return { code: 1, data: this.perMeasurementList, msg: 'success' };
+ return { code: RESULT_CODE_SUCCESS, data: this.perMeasurementList, msg: 'success' };
}
const res = await getNePerformanceList();
if (res.code === RESULT_CODE_SUCCESS) {
diff --git a/src/store/modules/router.ts b/src/store/modules/router.ts
index a4131a7d..ade7ef3b 100644
--- a/src/store/modules/router.ts
+++ b/src/store/modules/router.ts
@@ -5,7 +5,7 @@ import type {
RouteMeta,
RouteRecordRaw,
} from 'vue-router';
-import { getRouters } from '@/api/router';
+import { getRouter } from '@/api/auth';
import BasicLayout from '@/layouts/BasicLayout.vue';
import BlankLayout from '@/layouts/BlankLayout.vue';
import LinkLayout from '@/layouts/LinkLayout.vue';
@@ -46,7 +46,7 @@ const useRouterStore = defineStore('router', {
* @returns 生成的路由菜单
*/
async generateRoutes() {
- const res = await getRouters();
+ const res = await getRouter();
if (res.code === RESULT_CODE_SUCCESS) {
const buildRoutes = buildRouters(res.data.concat());
this.buildRouterData = buildRoutes;
diff --git a/src/store/modules/user.ts b/src/store/modules/user.ts
index 003ac7e9..7af89458 100644
--- a/src/store/modules/user.ts
+++ b/src/store/modules/user.ts
@@ -1,9 +1,13 @@
import defaultAvatar from '@/assets/images/default_avatar.png';
import useLayoutStore from './layout';
-import { login, logout, getInfo } from '@/api/login';
-import { setToken, removeToken } from '@/plugins/auth-token';
+import { login, logout, getInfo } from '@/api/auth';
+import {
+ delAccessToken,
+ delRefreshToken,
+ setAccessToken,
+ setRefreshToken,
+} from '@/plugins/auth-token';
import { defineStore } from 'pinia';
-import { TOKEN_RESPONSE_FIELD } from '@/constants/token-constants';
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
import { parseUrlPath } from '@/plugins/file-static-url';
@@ -105,8 +109,8 @@ const useUserStore = defineStore('user', {
async fnLogin(loginBody: Record) {
const res = await login(loginBody);
if (res.code === RESULT_CODE_SUCCESS && res.data) {
- const token = res.data[TOKEN_RESPONSE_FIELD];
- setToken(token);
+ setAccessToken(res.data.accessToken, res.data.refreshExpiresIn);
+ setRefreshToken(res.data.refreshToken, res.data.refreshExpiresIn);
if (res.data?.forcePasswdChange) {
this.forcePasswdChange = true;
}
@@ -150,11 +154,6 @@ const useUserStore = defineStore('user', {
this.forcePasswdChange = true;
}
}
- // 网络错误时退出登录状态
- if (res.code === 0) {
- removeToken();
- window.location.reload();
- }
return res;
},
// 退出系统
@@ -166,7 +165,8 @@ const useUserStore = defineStore('user', {
} finally {
this.roles = [];
this.permissions = [];
- removeToken();
+ delAccessToken();
+ delRefreshToken();
}
},
},
diff --git a/src/views/logManage/mml/index.vue b/src/views/logManage/mml/index.vue
index 5931820d..ae69cf66 100644
--- a/src/views/logManage/mml/index.vue
+++ b/src/views/logManage/mml/index.vue
@@ -97,7 +97,7 @@ let tableColumns: ColumnsType = reactive([
title: t('views.logManage.mml.logTime'),
dataIndex: 'logTime',
align: 'left',
- width: 150,
+ width: 200,
customRender(opt) {
if (!opt.value) return '';
return parseDateToStr(opt.value);
diff --git a/src/views/login.vue b/src/views/login.vue
index 18adece3..d01be8c7 100644
--- a/src/views/login.vue
+++ b/src/views/login.vue
@@ -5,7 +5,7 @@ import { message } from 'ant-design-vue/es';
import { reactive, onMounted, computed, toRaw } from 'vue';
import useUserStore from '@/store/modules/user';
import useAppStore from '@/store/modules/app';
-import { getCaptchaImage } from '@/api/login';
+import { getCaptchaImage } from '@/api/auth';
import { useRouter, useRoute } from 'vue-router';
import useI18n from '@/hooks/useI18n';
import useLayoutStore from '@/store/modules/layout';
@@ -75,21 +75,28 @@ function fnFinish() {
function fnGetCaptcha() {
if (state.captchaClick) return;
state.captchaClick = true;
- getCaptchaImage().then(res => {
- state.captchaClick = false;
- if (res.code != RESULT_CODE_SUCCESS) {
- message.warning(`${res.msg}`, 3);
- return;
- }
- state.captcha.enabled = Boolean(res.captchaEnabled);
- if (state.captcha.enabled) {
- state.captcha.codeImg = res.img;
- state.from.uuid = res.uuid;
- if (res.text) {
- state.from.code = res.text;
+ getCaptchaImage()
+ .then(res => {
+ if (res.code !== RESULT_CODE_SUCCESS) {
+ message.warning({
+ content: `${res.msg}`,
+ duration: 3,
+ });
+ return;
}
- }
- });
+ const { enabled, img, uuid } = res.data;
+ state.captcha.enabled = Boolean(enabled);
+ if (state.captcha.enabled) {
+ state.captcha.codeImg = img;
+ state.from.uuid = uuid;
+ }
+ if (res.data?.text) {
+ state.from.code = res.data.text;
+ }
+ })
+ .finally(() => {
+ state.captchaClick = false;
+ });
}
// 判断是否有背景地址
diff --git a/src/views/neData/base-station/list.vue b/src/views/neData/base-station/list.vue
index 9b3c7407..4a233e76 100644
--- a/src/views/neData/base-station/list.vue
+++ b/src/views/neData/base-station/list.vue
@@ -910,6 +910,7 @@ onMounted(() => {
{
if (res.code === RESULT_CODE_SUCCESS) {
- removeToken();
+ delAccessToken();
+ delRefreshToken();
useAppStore().bootloader = false;
}
})
diff --git a/src/views/system/quick-start/components/Start.vue b/src/views/system/quick-start/components/Start.vue
index f337a9e0..1d9c5a7c 100644
--- a/src/views/system/quick-start/components/Start.vue
+++ b/src/views/system/quick-start/components/Start.vue
@@ -2,8 +2,7 @@
import { onMounted } from 'vue';
import { useRouter } from 'vue-router';
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
-import { TOKEN_RESPONSE_FIELD } from '@/constants/token-constants';
-import { getToken, setToken } from '@/plugins/auth-token';
+import { getAccessToken, setAccessToken } from '@/plugins/auth-token';
import { bootloaderStart } from '@/api/system/quick-start/bootloader';
import { fnToStepName } from '../hooks/useStep';
import useI18n from '@/hooks/useI18n';
@@ -19,11 +18,10 @@ function fnChangeLocale(e: any) {
/**引导开始 */
function fnGuideStart() {
- if (getToken()) return;
+ if (getAccessToken()) return;
bootloaderStart().then(res => {
if (res.code === RESULT_CODE_SUCCESS && res.data) {
- const token = res.data[TOKEN_RESPONSE_FIELD];
- setToken(token);
+ setAccessToken(res.data.accessToken, res.data.refreshExpiresIn);
} else {
router.push({ name: 'Login' });
}
From f41557de949fcb87e5a306666611bd99dcbd4ad7 Mon Sep 17 00:00:00 2001
From: TsMask <340112800@qq.com>
Date: Sun, 27 Apr 2025 17:47:58 +0800
Subject: [PATCH 46/54] =?UTF-8?q?fix:=20=E5=8E=BB=E9=99=A4=E8=AF=B7?=
=?UTF-8?q?=E6=B1=82=E6=96=B9=E6=B3=95PATCH?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/api/perfManage/taskManage.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/api/perfManage/taskManage.ts b/src/api/perfManage/taskManage.ts
index bcd32b47..bd9e99ec 100644
--- a/src/api/perfManage/taskManage.ts
+++ b/src/api/perfManage/taskManage.ts
@@ -220,6 +220,6 @@ export function taskRun(data: Record) {
export function taskStop(data: Record) {
return request({
url: `/api/rest/performanceManagement/v1/elementType/${data.neType.toLowerCase()}/objectType/measureTask?id=${data.id}`,
- method: 'PATCH',
+ method: 'PUT',
});
}
\ No newline at end of file
From 96621f4261f9d6cbc3ac63e5415dcbd753d30e6d Mon Sep 17 00:00:00 2001
From: TsMask <340112800@qq.com>
Date: Sun, 27 Apr 2025 17:48:49 +0800
Subject: [PATCH 47/54] =?UTF-8?q?chore:=20=E6=9B=B4=E6=96=B0=E4=BE=9D?=
=?UTF-8?q?=E8=B5=96=E9=A1=B9=E7=89=88=E6=9C=AC?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
package.json | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/package.json b/package.json
index bb4a8c07..3c04f55a 100644
--- a/package.json
+++ b/package.json
@@ -13,7 +13,7 @@
},
"dependencies": {
"@ant-design/icons-vue": "7.0.1",
- "@antv/g6": "4.8.24",
+ "@antv/g6": "4.8.25",
"@codemirror/lang-javascript": "6.2.3",
"@codemirror/lang-yaml": "6.1.2",
"@codemirror/merge": "6.10.0",
@@ -24,7 +24,7 @@
"@xterm/xterm": "5.5.0",
"ant-design-vue": "4.2.6",
"antdv-pro-layout": "4.2.0",
- "antdv-pro-modal": "4.0.6",
+ "antdv-pro-modal": "4.0.8",
"codemirror": "6.0.1",
"crypto-js": "4.2.0",
"dayjs": "1.11.13",
@@ -54,7 +54,7 @@
"less": "4.2.2",
"typescript": "5.8.2",
"unplugin-vue-components": "0.28.0",
- "vite": "6.2.2",
+ "vite": "6.3.3",
"vite-plugin-compression": "0.5.1",
"vue-tsc": "2.2.8"
}
From efceb68ff3df174f9c5a4f450a52448bc74f7b95 Mon Sep 17 00:00:00 2001
From: TsMask <340112800@qq.com>
Date: Sun, 27 Apr 2025 17:49:08 +0800
Subject: [PATCH 48/54] =?UTF-8?q?chore:=20=E6=9B=B4=E6=96=B0=E7=89=88?=
=?UTF-8?q?=E6=9C=AC=E5=8F=B7=202.250427?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.env.development | 2 +-
.env.production | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/.env.development b/.env.development
index 727b5002..32b5a70d 100644
--- a/.env.development
+++ b/.env.development
@@ -11,7 +11,7 @@ VITE_APP_NAME = "Core Network OMC"
VITE_APP_CODE = "OMC"
# 应用版本
-VITE_APP_VERSION = "2.250418"
+VITE_APP_VERSION = "2.250427"
# 接口基础URL地址-不带/后缀
VITE_API_BASE_URL = "/omc-api"
diff --git a/.env.production b/.env.production
index 727b5002..32b5a70d 100644
--- a/.env.production
+++ b/.env.production
@@ -11,7 +11,7 @@ VITE_APP_NAME = "Core Network OMC"
VITE_APP_CODE = "OMC"
# 应用版本
-VITE_APP_VERSION = "2.250418"
+VITE_APP_VERSION = "2.250427"
# 接口基础URL地址-不带/后缀
VITE_API_BASE_URL = "/omc-api"
From 78b5ec90eee719bc0eb6cc50c3220ef56960f85a Mon Sep 17 00:00:00 2001
From: TsMask <340112800@qq.com>
Date: Sun, 27 Apr 2025 18:45:56 +0800
Subject: [PATCH 49/54] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E5=BC=95?=
=?UTF-8?q?=E5=AF=BC=E8=8E=B7=E5=8F=96token=E5=AD=98=E5=82=A8=E9=97=AE?=
=?UTF-8?q?=E9=A2=98?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/plugins/auth-token.ts | 8 ++++++++
src/views/system/quick-start/components/Done.vue | 3 +--
src/views/system/quick-start/components/Start.vue | 2 +-
3 files changed, 10 insertions(+), 3 deletions(-)
diff --git a/src/plugins/auth-token.ts b/src/plugins/auth-token.ts
index 09b420b4..88361459 100644
--- a/src/plugins/auth-token.ts
+++ b/src/plugins/auth-token.ts
@@ -1,4 +1,9 @@
import Cookies from 'js-cookie';
+import { localRemove, localSet } from '@/utils/cache-local-utils';
+import {
+ CACHE_LOCAL_LOCK_PASSWD,
+ CACHE_LOCAL_MASK,
+} from '@/constants/cache-keys-constants';
import {
TOKEN_ACCESS_COOKIE,
TOKEN_REFRESH_COOKIE,
@@ -17,11 +22,14 @@ export function getAccessToken(): string {
export function setAccessToken(token: string, exp: number): void {
const expires = new Date(new Date().getTime() + exp * 1000);
Cookies.set(TOKEN_ACCESS_COOKIE, token, { expires });
+ localSet(CACHE_LOCAL_MASK, 'none');
}
/**移除访问令牌 */
export function delAccessToken(): void {
Cookies.remove(TOKEN_ACCESS_COOKIE);
+ localRemove(CACHE_LOCAL_MASK);
+ localRemove(CACHE_LOCAL_LOCK_PASSWD);
}
/**获取刷新令牌 */
diff --git a/src/views/system/quick-start/components/Done.vue b/src/views/system/quick-start/components/Done.vue
index e0b71880..627f2cf4 100644
--- a/src/views/system/quick-start/components/Done.vue
+++ b/src/views/system/quick-start/components/Done.vue
@@ -56,9 +56,8 @@ function fnGuideDone() {
bootloaderDone()
.then(res => {
if (res.code === RESULT_CODE_SUCCESS) {
- delAccessToken();
- delRefreshToken();
useAppStore().bootloader = false;
+ delAccessToken();
}
})
.finally(() => {
diff --git a/src/views/system/quick-start/components/Start.vue b/src/views/system/quick-start/components/Start.vue
index 1d9c5a7c..63924eb6 100644
--- a/src/views/system/quick-start/components/Start.vue
+++ b/src/views/system/quick-start/components/Start.vue
@@ -21,7 +21,7 @@ function fnGuideStart() {
if (getAccessToken()) return;
bootloaderStart().then(res => {
if (res.code === RESULT_CODE_SUCCESS && res.data) {
- setAccessToken(res.data.accessToken, res.data.refreshExpiresIn);
+ setAccessToken(res.data.accessToken, res.data.expiresIn);
} else {
router.push({ name: 'Login' });
}
From a65f8ed95fafe50ed7be7e86d5b5bae522f1332d Mon Sep 17 00:00:00 2001
From: TsMask <340112800@qq.com>
Date: Mon, 28 Apr 2025 18:30:14 +0800
Subject: [PATCH 50/54] =?UTF-8?q?fix:=20=E7=9C=8B=E6=9D=BF=E7=94=A8?=
=?UTF-8?q?=E6=88=B7=E6=B4=BB=E5=8A=A8=E4=B9=B1=E5=BA=8F=E9=97=AE=E9=A2=98?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/views/dashboard/overview/hooks/useUserActivity.ts | 5 +----
src/views/dashboard/overview/hooks/useWS.ts | 4 ++++
2 files changed, 5 insertions(+), 4 deletions(-)
diff --git a/src/views/dashboard/overview/hooks/useUserActivity.ts b/src/views/dashboard/overview/hooks/useUserActivity.ts
index 5e307552..8c4a80b1 100644
--- a/src/views/dashboard/overview/hooks/useUserActivity.ts
+++ b/src/views/dashboard/overview/hooks/useUserActivity.ts
@@ -97,10 +97,7 @@ export function eventListParse(
}
}
- // 有数据进行排序
- if (eventData.value.length > 5) {
- eventData.value.sort((a, b) => b.eTime - a.eTime);
- }
+ // 激活选中
if (eventData.value.length > 0) {
eventId.value = eventData.value[0].eId;
}
diff --git a/src/views/dashboard/overview/hooks/useWS.ts b/src/views/dashboard/overview/hooks/useWS.ts
index 285cdcee..eefa91f2 100644
--- a/src/views/dashboard/overview/hooks/useWS.ts
+++ b/src/views/dashboard/overview/hooks/useWS.ts
@@ -2,6 +2,7 @@ import { RESULT_CODE_ERROR } from '@/constants/result-constants';
import { OptionsType, WS } from '@/plugins/ws-websocket';
import { onBeforeUnmount, ref } from 'vue';
import {
+ eventData,
eventListParse,
eventItemParseAndPush,
userActivityReset,
@@ -52,18 +53,21 @@ export default function useWS() {
case 'amf_1010_001':
if (Array.isArray(data.rows)) {
eventListParse('amf_ue', data);
+ eventData.value.sort((a, b) => b.eTime - a.eTime);
}
break;
// MME_UE会话事件
case 'mme_1011_001':
if (Array.isArray(data.rows)) {
eventListParse('mme_ue', data);
+ eventData.value.sort((a, b) => b.eTime - a.eTime);
}
break;
// IMS_CDR会话事件
case 'ims_1005_001':
if (Array.isArray(data.rows)) {
eventListParse('ims_cdr', data);
+ eventData.value.sort((a, b) => b.eTime - a.eTime);
}
break;
//UPF-总流量数
From 42f8c0b64f9bee867fbbb40b811e0512e87387f0 Mon Sep 17 00:00:00 2001
From: TsMask <340112800@qq.com>
Date: Mon, 28 Apr 2025 18:32:14 +0800
Subject: [PATCH 51/54] =?UTF-8?q?fix:=20=E7=9C=8B=E6=9D=BF=E6=B5=81?=
=?UTF-8?q?=E9=87=8F=E5=9B=BE=E7=A1=AE=E4=BF=9D=E6=97=B6=E9=97=B4=E4=BB=A5?=
=?UTF-8?q?HH:mm:ss=E6=A0=BC=E5=BC=8F=E6=98=BE=E7=A4=BA?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../overview/components/UPFFlow/index.vue | 24 +------------------
.../overview/hooks/useUPFTotalFlow.ts | 4 +++-
2 files changed, 4 insertions(+), 24 deletions(-)
diff --git a/src/views/dashboard/overview/components/UPFFlow/index.vue b/src/views/dashboard/overview/components/UPFFlow/index.vue
index df77d5c6..c635fa8c 100644
--- a/src/views/dashboard/overview/components/UPFFlow/index.vue
+++ b/src/views/dashboard/overview/components/UPFFlow/index.vue
@@ -159,7 +159,7 @@ function handleRanderChart() {
data: lineXTime,
axisLabel: {
formatter: function (params: any) {
- return params.split(' ')[1];
+ return params;
},
fontSize: 14,
},
@@ -251,28 +251,6 @@ watch(
onMounted(() => {
fnGetInitData();
-
- // setInterval(() => {
- // upfFlowData.value.lineXTime.push(parseDateToStr(new Date()));
- // const upN3 = parseSizeFromKbs(+145452, 5);
- // upfFlowData.value.lineYUp.push(upN3[0]);
- // const downN6 = parseSizeFromKbs(+232343, 5);
- // upfFlowData.value.lineYDown.push(downN6[0]);
-
- // upfFlowChart.value.setOption({
- // xAxis: {
- // data: upfFlowData.value.lineXTime,
- // },
- // series: [
- // {
- // data: upfFlowData.value.lineYUp,
- // },
- // {
- // data: upfFlowData.value.lineYDown,
- // },
- // ],
- // });
- // }, 5000);
});
diff --git a/src/views/dashboard/overview/hooks/useUPFTotalFlow.ts b/src/views/dashboard/overview/hooks/useUPFTotalFlow.ts
index 95b73ddd..edc1335b 100644
--- a/src/views/dashboard/overview/hooks/useUPFTotalFlow.ts
+++ b/src/views/dashboard/overview/hooks/useUPFTotalFlow.ts
@@ -23,7 +23,9 @@ export const upfFlowData = ref({
/**UPF-流量数据 数据解析 */
export function upfFlowParse(data: Record) {
- upfFlowData.value.lineXTime.push(parseDateToStr(+data['timeGroup']));
+ upfFlowData.value.lineXTime.push(
+ parseDateToStr(+data['timeGroup'], 'HH:mm:ss')
+ );
const upN3 = parseSizeFromKbs(+data['UPF.03'], 5);
upfFlowData.value.lineYUp.push(upN3[0]);
const downN6 = parseSizeFromKbs(+data['UPF.06'], 5);
From 76caaf694c4688a69d7dd653f573875aee28d30e Mon Sep 17 00:00:00 2001
From: TsMask <340112800@qq.com>
Date: Mon, 28 Apr 2025 19:34:56 +0800
Subject: [PATCH 52/54] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0IMS=20SIP?=
=?UTF-8?q?=E5=93=8D=E5=BA=94=E7=A0=81=E5=8E=9F=E5=9B=A0=E6=98=BE=E7=A4=BA?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/i18n/locales/en-US.ts | 2 +
src/i18n/locales/zh-CN.ts | 2 +
src/views/dashboard/imsCDR/index.vue | 65 ++++++++++-----
.../components/UserActivity/index.vue | 80 ++++++++++++-------
4 files changed, 100 insertions(+), 49 deletions(-)
diff --git a/src/i18n/locales/en-US.ts b/src/i18n/locales/en-US.ts
index cb87a8b1..550b54ef 100644
--- a/src/i18n/locales/en-US.ts
+++ b/src/i18n/locales/en-US.ts
@@ -424,6 +424,8 @@ export default {
caller: "Caller",
called: "Called",
result: "Result",
+ resultCode: "Result Code",
+ resultCause: "Result Cause",
resultOk: "Success",
resultFail: "Fail",
delTip: "Confirm deletion of the data item numbered [{msg}]?",
diff --git a/src/i18n/locales/zh-CN.ts b/src/i18n/locales/zh-CN.ts
index 4a544f38..7328c77a 100644
--- a/src/i18n/locales/zh-CN.ts
+++ b/src/i18n/locales/zh-CN.ts
@@ -424,6 +424,8 @@ export default {
caller: "主叫",
called: "被叫",
result: "结果",
+ resultCode: "结果码",
+ resultCause: "结果原因",
resultOk: "成功",
resultFail: "失败",
delTip: "确认删除编号为【{msg}】的数据项?",
diff --git a/src/views/dashboard/imsCDR/index.vue b/src/views/dashboard/imsCDR/index.vue
index cc8fdb51..b47aea60 100644
--- a/src/views/dashboard/imsCDR/index.vue
+++ b/src/views/dashboard/imsCDR/index.vue
@@ -35,9 +35,12 @@ let dict: {
cdrSipCode: DictType[];
/**CDR 呼叫类型 */
cdrCallType: DictType[];
+ /**IMS-Voice-SIP响应代码类别类型原因 */
+ cdrSipCodeCause: DictType[];
} = reactive({
cdrSipCode: [],
cdrCallType: [],
+ cdrSipCodeCause: [],
});
/**网元可选 */
@@ -182,13 +185,6 @@ let tableColumns: ColumnsType = [
return cdrJSON.calledParty;
},
},
- {
- title: t('views.dashboard.cdr.result'),
- dataIndex: 'cdrJSON',
- key: 'cause',
- align: 'left',
- width: 150,
- },
{
title: t('views.dashboard.cdr.duration'),
dataIndex: 'cdrJSON',
@@ -202,6 +198,22 @@ let tableColumns: ColumnsType = [
: parseDuration(cdrJSON.callDuration);
},
},
+ {
+ title: t('views.dashboard.cdr.resultCode'),
+ dataIndex: 'cdrJSON',
+ key: 'code',
+ align: 'left',
+ width: 200,
+ ellipsis: true,
+ },
+ {
+ title: t('views.dashboard.cdr.resultCause'),
+ dataIndex: 'cdrJSON',
+ key: 'cause',
+ align: 'left',
+ width: 200,
+ ellipsis: true,
+ },
{
title: t('views.dashboard.cdr.seizureTime'),
dataIndex: 'cdrJSON',
@@ -212,7 +224,7 @@ let tableColumns: ColumnsType = [
if (typeof cdrJSON.seizureTime === 'number') {
return parseDateToStr(+cdrJSON.seizureTime * 1000);
}
- return cdrJSON.seizureTime;
+ return parseDateToStr(cdrJSON.seizureTime);
},
},
{
@@ -225,7 +237,7 @@ let tableColumns: ColumnsType = [
if (typeof cdrJSON.releaseTime === 'number') {
return parseDateToStr(+cdrJSON.releaseTime * 1000);
}
- return cdrJSON.releaseTime;
+ return parseDateToStr(cdrJSON.releaseTime);
},
},
{
@@ -498,16 +510,21 @@ function wsMessage(res: Record) {
onMounted(() => {
// 初始字典数据
- Promise.allSettled([getDict('cdr_sip_code'), getDict('cdr_call_type')]).then(
- resArr => {
- if (resArr[0].status === 'fulfilled') {
- dict.cdrSipCode = resArr[0].value;
- }
- if (resArr[1].status === 'fulfilled') {
- dict.cdrCallType = resArr[1].value;
- }
+ Promise.allSettled([
+ getDict('cdr_sip_code'),
+ getDict('cdr_call_type'),
+ getDict('cdr_sip_code_cause'),
+ ]).then(resArr => {
+ if (resArr[0].status === 'fulfilled') {
+ dict.cdrSipCode = resArr[0].value;
}
- );
+ if (resArr[1].status === 'fulfilled') {
+ dict.cdrCallType = resArr[1].value;
+ }
+ if (resArr[2].status === 'fulfilled') {
+ dict.cdrSipCodeCause = resArr[2].value;
+ }
+ });
// 获取网元网元列表
useNeInfoStore()
.fnNelist()
@@ -751,7 +768,7 @@ onBeforeUnmount(() => {
:value="record.cdrJSON.callType"
/>
-
+
{
{{ t('views.dashboard.cdr.resultOk') }}
+
+
+
+
+ Call failure for other reason
+
diff --git a/src/views/dashboard/overview/components/UserActivity/index.vue b/src/views/dashboard/overview/components/UserActivity/index.vue
index a5aaa9c9..23ec0c35 100644
--- a/src/views/dashboard/overview/components/UserActivity/index.vue
+++ b/src/views/dashboard/overview/components/UserActivity/index.vue
@@ -19,12 +19,15 @@ let dict: {
ueEventType: DictType[];
/**UE 事件CM状态 */
ueEventCmState: DictType[];
+ /**CDR SIP响应代码类别类型 */
+ cdrSipCodeCause: DictType[];
} = reactive({
cdrSipCode: [],
cdrCallType: [],
ueAauthCode: [],
ueEventType: [],
ueEventCmState: [],
+ cdrSipCodeCause: [],
});
onMounted(() => {
@@ -35,6 +38,7 @@ onMounted(() => {
getDict('ue_auth_code'),
getDict('ue_event_type'),
getDict('ue_event_cm_state'),
+ getDict('cdr_sip_code_cause'),
]).then(resArr => {
if (resArr[0].status === 'fulfilled') {
dict.cdrSipCode = resArr[0].value;
@@ -51,6 +55,9 @@ onMounted(() => {
if (resArr[4].status === 'fulfilled') {
dict.ueEventCmState = resArr[4].value;
}
+ if (resArr[5].status === 'fulfilled') {
+ dict.cdrSipCodeCause = resArr[5].value;
+ }
});
});
@@ -75,16 +82,7 @@ onMounted(() => {
- {{ t('views.dashboard.overview.userActivity.time') }}:
-
- {{
- typeof item.data.releaseTime === 'number'
- ? parseDateToStr(+item.data.releaseTime * 1000)
- : item.data.releaseTime
- }}
-
-
+