diff --git a/.env.development b/.env.development index 98a7b1ff..820724bd 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.2506.4" +VITE_APP_VERSION = "local-dev" # 接口基础URL地址-不带/后缀 VITE_API_BASE_URL = "/omc-api" diff --git a/.env.production b/.env.production index 98a7b1ff..0819485a 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.2506.4" +VITE_APP_VERSION = "local-prod" # 接口基础URL地址-不带/后缀 VITE_API_BASE_URL = "/omc-api" diff --git a/CHANGELOG.md b/CHANGELOG.md index 98972264..e6069eb2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,59 @@ # 版本发布日志 +## 2.2508.2-20250815 + +- 优化 给config.js加随机数避免缓存 +- 新增 第三方登录认证功能和管理页,第三方用户不可删除和修改密码 +- 优化 系统操作日志详情json格式化显示 +- 优化 网元信息更新禁止修改neType neId +- 修复 用户数累加问题修复,液体图中浮标显示错误修复 +- 修复 基站数修复以及资源模块下拉框修复 +- 修复 告警事件时间显示不是时间格式字符串 +- 修复 透明柱状图自适应,数值标签定位 +- 修复 告警数据参数调整 + +## 2.2508.1-20250808 + +- 修复 UDM鉴权更新ki长度提示错误无法发送请求 +- 优化 MML命令为空判断不发送,MML日志列表显示 +- 优化 关闭网元reload操作,只有amf smf upf udm四个网元支持,改用mml发送 +- 优化 网元概览隐藏容量字段显示,CBC创建时间格式显示错误 +- 优化 系统用户账号简单4位长度 +- 修复 看板2用户数量显示不出,修改广播帮助的数量提示 +- 优化 性能栏目相关页面主动呼叫改正在通话,网元切换清除缓存数据 + +## 2.2507.4-20250801 + +- 新增 cbc界面 +- 修复 数据处理修复,显示优化 +- 修复 告警模块优化,底部边距,数据采集说明 + +## 2.2507.3-20250725 + +- 优化 将UDM鉴权导出按钮隐藏 +- 修复 自定义指标数值格式处理,导出表格修复 +- 修复 仪表盘2用户事件显示不正常 +- 修复 自定义指标数值格式化保留3位小数 +- 优化 参数配置AMF导入Index字段存在更新,不存在默认新增 + +## 2.2507.2-20250718 + +- 优化 变更nssf/n3iwf接口调用 +- 优化 调整告警类型参数值,参数配置列表项不记录勾选状态 +- 优化 调整UE数据返回参数 +- 修复 基站状态拓扑图显示失败 +- 修复 基站状态记录和smscCDR导出改为get行为 +- 新增 mt版本移动过来的的告警/仪表/性能大屏页面 +- 移除 删除无用文件 +- 修复 指标页面数据获取异常接口调整 + +## 2.2507.1-20250705 + +- 修复 缓存管理列表key查询URL路径错误 +- 优化 SMF-Date显示图表日期显示不完整,改日期格式 +- 修复 跟踪任务编号的传入获取信息不一致 +- 修复 参数配置可见visible属性判断 + ## 2.2506.4-20250627 - 修复 UDM-IMS数据批量新增/批量删除命令调整 diff --git a/index.html b/index.html index e2eb9bb0..c7d299c6 100644 --- a/index.html +++ b/index.html @@ -2,14 +2,18 @@ - + loading... - + - - +
diff --git a/package.json b/package.json index 3c04f55a..07a2b8ac 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,7 @@ "crypto-js": "4.2.0", "dayjs": "1.11.13", "echarts": "5.6.0", + "echarts-liquidfill": "^3.1.0", "file-saver": "2.0.5", "grid-layout-plus": "1.0.6", "intl-tel-input": "25.2.0", diff --git a/public/neDataImput/import_amf_imeiWhitelist_template.xlsx b/public/neDataImput/import_amf_imeiWhitelist_template.xlsx index 8716464a..b4e3749e 100644 Binary files a/public/neDataImput/import_amf_imeiWhitelist_template.xlsx and b/public/neDataImput/import_amf_imeiWhitelist_template.xlsx differ diff --git a/public/neDataImput/import_amf_whitelist_template.xlsx b/public/neDataImput/import_amf_whitelist_template.xlsx index 26b66e5a..f59e18ff 100644 Binary files a/public/neDataImput/import_amf_whitelist_template.xlsx and b/public/neDataImput/import_amf_whitelist_template.xlsx differ diff --git a/public/neDataImput/import_mme_imeiWhitelist_template.xlsx b/public/neDataImput/import_mme_imeiWhitelist_template.xlsx index 44957994..7c91df6e 100644 Binary files a/public/neDataImput/import_mme_imeiWhitelist_template.xlsx and b/public/neDataImput/import_mme_imeiWhitelist_template.xlsx differ diff --git a/src/api/auth.ts b/src/api/auth.ts index eab43a76..c11bde79 100644 --- a/src/api/auth.ts +++ b/src/api/auth.ts @@ -1,4 +1,5 @@ import { request } from '@/plugins/http-fetch'; +import { sessionGet } from '@/utils/cache-session-utils'; /** * 登录方法 @@ -87,3 +88,69 @@ export function getCaptchaImage() { whithToken: false, }); } + +/** + * 登录认证源 + * @returns object + */ +export function getLoginSource() { + return request({ + url: '/auth/login/source', + method: 'GET', + whithToken: false, + }); +} + +/** + * LDAP登录 + * @returns object + */ +export function loginLDAP(data: Record) { + return request({ + url: '/auth/login/ldap', + method: 'POST', + data: data, + whithToken: false, + }); +} + +/** + * SMTP登录 + * @returns object + */ +export function loginSMTP(data: Record) { + return request({ + url: '/auth/login/smtp', + method: 'POST', + data: data, + whithToken: false, + }); +} + +/** + * 登录认证源OAuth2跳转登录URL + * @returns object + */ +export function loginOAuth2URL(state: string): string { + // 兼容旧前端可改配置文件 + const baseUrl = import.meta.env.PROD + ? sessionGet('baseUrl') || import.meta.env.VITE_API_BASE_URL + : import.meta.env.VITE_API_BASE_URL; + return `${baseUrl}/auth/login/oauth2/authorize?state=${state}`; +} + +/** + * 登录认证源OAuth2认证登录 + * @returns object + */ +export function loginOAuth2Token(code: string, state: string) { + return request({ + url: '/auth/login/oauth2/token', + method: 'POST', + data: { + code, + state, + }, + whithToken: false, + }); +} diff --git a/src/api/cbc/cbe.ts b/src/api/cbc/cbe.ts new file mode 100644 index 00000000..07df3200 --- /dev/null +++ b/src/api/cbc/cbe.ts @@ -0,0 +1,75 @@ +import { request } from '@/plugins/http-fetch'; + + + +/** + * CBC列表 + * @param query 查询参数 + * @returns object + */ +export function listCBC(query: Record) { + return request({ + url: `/neData/cbc/message/list`, + method: 'GET', + params: query, + timeout: 30_000, + }); +} + + + +/** + * CBC签约用户新增 + * @param data 签约对象 + * @returns object + */ +export function addCBC(data: Record) { + return request({ + url: `/neData/cbc/message?neId=${data.neId}`, + method: 'POST', + data: data, + timeout: 180_000, + }); +} + + + + +export function updateCBCStatus(data:any) { + return request({ + url: `/neData/cbc/message/${data.id}/${data.status}?neId=${data.neId}`, + method: 'PUT', + timeout: 180_000, + }); +} + + +export function updateCBC(data:any) { + return request({ + url: `/neData/cbc/message/${data.id}?neId=${data.neId}`, + method: 'PUT', + data, + timeout: 180_000, + }); +} + + + +/** + * CBC删除 + * @param data 签约对象 + * @returns object + */ +export function delCBC(neId: string, id: string) { + return request({ + url: `/neData/cbc/message/${id}?neId=${neId}`, + method: 'DELETE', + timeout: 180_000, + }); +} + + + + + + diff --git a/src/api/configManage/configParam.ts b/src/api/configManage/configParam.ts deleted file mode 100644 index 494176cb..00000000 --- a/src/api/configManage/configParam.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { - RESULT_CODE_ERROR, - RESULT_CODE_SUCCESS, - RESULT_MSG_ERROR, -} from '@/constants/result-constants'; -import { language, request } from '@/plugins/http-fetch'; - -/** - * 更新网元配置重新载入 - * @param neType 网元类型 - * @param neId 网元ID - * @returns - */ -export async function updateNeConfigReload(neType: string, neId: string) { - // 发起请求 - const result = await request({ - url: `/api/rest/operationManagement/v1/elementType/${neType}/objectType/mml?ne_id=${neId}`, - method: 'POST', - data: { mml: ['reload'] }, - timeout: 180_000, - }); - // 解析数据 - if (result.code === RESULT_CODE_SUCCESS && Array.isArray(result.data.data)) { - const v = result.data.data[0]; - const str = v.toLowerCase(); - if (str.indexOf('ok') !== -1) { - delete result.data; - } else if (str.indexOf('success') !== -1) { - delete result.data; - } else { - return { code: RESULT_CODE_ERROR, msg: RESULT_MSG_ERROR[language] }; - } - } - return result; -} diff --git a/src/api/faultManage/actAlarm.ts b/src/api/faultManage/actAlarm.ts index 210d9023..9bb59835 100644 --- a/src/api/faultManage/actAlarm.ts +++ b/src/api/faultManage/actAlarm.ts @@ -12,7 +12,7 @@ export async function getActiveAlarmTotal() { url: `/neData/alarm/list`, method: 'GET', params: { - alarmStatus: '1', + alarmStatus: 'Active', sortField: 'event_time', sortOrder: 'desc', pageNum: 1, @@ -194,33 +194,13 @@ export async function exportAll(query: Record) { * @returns bolb */ export async function origGet() { - let totalSQL = `select count(*) as value,orig_severity as name from alarm WHERE alarm_status='1' and orig_severity!='Event' group by orig_severity`; - - // 发起请求 - const result = await request({ - url: `/api/rest/databaseManagement/v1/select/omc_db/alarm`, + return await request({ + url: `/neData/alarm/count/severity`, method: 'GET', params: { - SQL: totalSQL, + alarmStatus: 'Active', }, - timeout: 30_000, }); - //// - - // 解析数据 - if (result.code === RESULT_CODE_SUCCESS) { - const itemData = result.data.data; - if (Array.isArray(itemData)) { - const v = itemData[0]['alarm']; - if (Array.isArray(v)) { - result.data = v; - } - if (v === null) { - result.data = []; - } - } - } - return result; } /** @@ -228,34 +208,13 @@ export async function origGet() { * @param filterFlag 查询参数 * @returns object */ -export async function top3Sel(filterFlag?: string) { - let filter = ` WHERE alarm_status='1'and orig_severity='${filterFlag}'`; - if (!filterFlag) filter = "WHERE alarm_status='1'"; - - let top3SQL = `select count(*) as value,ne_type as name from alarm ${filter} and orig_severity!='Event' group by ne_type ORDER BY value desc limit 0,3 `; - - // 发起请求 - const result = await request({ - url: `/api/rest/databaseManagement/v1/select/omc_db/alarm`, +export async function top3Sel() { + return await request({ + url: `/neData/alarm/count/ne`, method: 'GET', params: { - SQL: top3SQL, + alarmStatus: 'Active', + top: 3, }, - timeout: 30_000, }); - - // 解析数据 - if (result.code === RESULT_CODE_SUCCESS) { - const itemData = result.data.data; - if (Array.isArray(itemData)) { - const v = itemData[0]['alarm']; - if (Array.isArray(v)) { - result.data = v; - } - if (v === null) { - result.data = []; - } - } - } - return result; } diff --git a/src/api/logManage/exportFile.ts b/src/api/logManage/exportFile.ts deleted file mode 100644 index 2ce72877..00000000 --- a/src/api/logManage/exportFile.ts +++ /dev/null @@ -1,55 +0,0 @@ -import { CACHE_SESSION_CRYPTO_API } from '@/constants/cache-keys-constants'; -import { sessionGet } from '@/utils/cache-session-utils'; -import { request } from '@/plugins/http-fetch'; - -/** - * 获取下拉框数据 - * @returns object - */ -export function getBakFile() { - return request({ - url: '/lm/table/list', - method: 'GET', - }); -} - -/** - * 获取对应类型的文件列表 - * @param query 查询参数 - * @returns object - */ -export function getBakFileList(query: Record) { - return request({ - url: '/lm/file/list', - method: 'GET', - params: query, - }); -} - -/** - * 下载远端文件 - * @param query 查询参数 - * @returns object - */ -export function downFile(query: Record) { - return request({ - url: `/lm/file/${query.fileName}`, - method: 'GET', - params: query, - responseType: 'blob', - timeout: 180_000, - }); -} - -/** - * 删除远端获取文件 - * @param query 查询参数 - * @returns object - */ -export function delFile(query: Record) { - return request({ - url: `/lm/file/${query.fileName}`, - method: 'DELETE', - params: query, - }); -} diff --git a/src/api/logManage/mml.ts b/src/api/logManage/mml.ts deleted file mode 100644 index c32452ed..00000000 --- a/src/api/logManage/mml.ts +++ /dev/null @@ -1,68 +0,0 @@ -import { RESULT_CODE_SUCCESS } from '@/constants/result-constants'; -import { request } from '@/plugins/http-fetch'; -import { parseObjLineToHump } from '@/utils/parse-utils'; - -/** - * 查询日志列表 - * @param query 查询参数 - * @returns object - */ -export async function listMML(query: Record) { - let totalSQL = 'select count(*) as total from mml_log where 1=1 '; - let rowsSQL = 'select * from mml_log where 1=1 '; - - // 查询 - let querySQL = ''; - if (query.accountName) { - querySQL += ` and user like '%${query.accountName}%' `; - } - if (query.beginTime) { - querySQL += ` and log_time >= '${query.beginTime}' `; - } - if (query.endTime) { - querySQL += ` and log_time <= '${query.endTime}' `; - } - - // 排序 - let sortSql = ' order by log_time '; - if (query.sortOrder === 'asc') { - sortSql += ' asc '; - } else { - sortSql += ' desc '; - } - - // 分页 - const pageNum = (query.pageNum - 1) * query.pageSize; - const limtSql = ` limit ${pageNum},${query.pageSize} `; - - // 发起请求 - const result = await request({ - url: `/api/rest/databaseManagement/v1/select/omc_db/mml_log`, - method: 'GET', - params: { - totalSQL: totalSQL + querySQL, - rowsSQL: rowsSQL + querySQL + sortSql + limtSql, - }, - }); - - // 解析数据 - if (result.code === RESULT_CODE_SUCCESS) { - const data = { - data: { total: 0, rows: [] as any }, - code: result.code, - msg: result.msg, - }; - result.data.data.forEach((item: any) => { - const itemData = item['mml_log']; - if (Array.isArray(itemData)) { - if (itemData.length === 1 && itemData[0]['total'] >= 0) { - data.data.total = itemData[0]['total']; - } else { - data.data.rows = itemData.map(v => parseObjLineToHump(v)); - } - } - }); - return data; - } - return result; -} diff --git a/src/api/logManage/security.ts b/src/api/logManage/security.ts deleted file mode 100644 index 4a1448b2..00000000 --- a/src/api/logManage/security.ts +++ /dev/null @@ -1,71 +0,0 @@ -import { RESULT_CODE_SUCCESS } from '@/constants/result-constants'; -import { request } from '@/plugins/http-fetch'; -import { parseObjLineToHump } from '@/utils/parse-utils'; - -/** - * 查询日志列表 - * @param query 查询参数 - * @returns object - */ -export async function listSecurityLog(query: Record) { - let totalSQL = 'select count(*) as total from security_log where 1=1 '; - let rowsSQL = 'select * from security_log where 1=1 '; - - // 查询 - let querySQL = ''; - if (query.accountName) { - querySQL += ` and account_name like '%${query.accountName}%' `; - } - if (query.opType) { - querySQL += ` and op_type = '${query.opType}' `; - } - if (query.beginTime) { - querySQL += ` and op_time >= '${query.beginTime}' `; - } - if (query.endTime) { - querySQL += ` and op_time <= '${query.endTime}' `; - } - - // 排序 - let sortSql = ' order by op_time '; - if (query.sortOrder === 'asc') { - sortSql += ' asc '; - } else { - sortSql += ' desc '; - } - - // 分页 - const pageNum = (query.pageNum - 1) * query.pageSize; - const limtSql = ` limit ${pageNum},${query.pageSize} `; - - // 发起请求 - const result = await request({ - url: `/api/rest/databaseManagement/v1/select/omc_db/security_log`, - method: 'GET', - params: { - totalSQL: totalSQL + querySQL, - rowsSQL: rowsSQL + querySQL + sortSql + limtSql, - }, - }); - - // 解析数据 - if (result.code === RESULT_CODE_SUCCESS) { - const data = { - data: { total: 0, rows: [] as any }, - code: result.code, - msg: result.msg, - }; - result.data.data.forEach((item: any) => { - const itemData = item['security_log']; - if (Array.isArray(itemData)) { - if (itemData.length === 1 && itemData[0]['total'] >= 0) { - data.data.total = itemData[0]['total']; - } else { - data.data.rows = itemData.map(v => parseObjLineToHump(v)); - } - } - }); - return data; - } - return result; -} diff --git a/src/api/mmlManage/neOperate.ts b/src/api/mmlManage/neOperate.ts index 34cb3f2c..a4744380 100644 --- a/src/api/mmlManage/neOperate.ts +++ b/src/api/mmlManage/neOperate.ts @@ -1,6 +1,4 @@ -import { RESULT_CODE_SUCCESS } from '@/constants/result-constants'; import { request } from '@/plugins/http-fetch'; -import { parseObjLineToHump } from '@/utils/parse-utils'; /** * 查询网元可用cmd命令 @@ -8,22 +6,17 @@ import { parseObjLineToHump } from '@/utils/parse-utils'; * @returns object */ export async function getMMLByNE(neType: string) { - // 发起请求 - const result = await request({ - url: `/api/rest/databaseManagement/v1/elementType/omc_db/objectType/mml_system`, + return request({ + url: '/tool/mml/system/list', method: 'GET', params: { - SQL: `select * from mml_system where ne_type = '${neType}' and status = 'Active'`, + neType: neType, + status: 'Active', + pageNum: 1, + pageSize: 1000, }, + timeout: 60_000, }); - // 解析数据 - if (result.code === RESULT_CODE_SUCCESS && Array.isArray(result.data.data)) { - let data = result.data.data[0]; - return Object.assign(result, { - data: parseObjLineToHump(data['mml_system']), - }); - } - return result; } /** @@ -40,16 +33,15 @@ export async function sendMMlByNE( objectType: string, cmdArr: string[] ) { - // 发起请求 - const result = await request({ - url: `/api/rest/operationManagement/v1/elementType/${neType}/objectType/${objectType}?ne_id=${neId}`, + return request({ + url: '/tool/mml/command', method: 'POST', - data: { mml: cmdArr }, + data: { + neType: neType, + neId: neId, + type: objectType, + command: cmdArr, + }, timeout: 180_000, }); - // 解析数据 - if (result.code === RESULT_CODE_SUCCESS && Array.isArray(result.data.data)) { - result.data = result.data.data; - } - return result; } diff --git a/src/api/mmlManage/udmOperate.ts b/src/api/mmlManage/udmOperate.ts index 31042eae..5fa50452 100644 --- a/src/api/mmlManage/udmOperate.ts +++ b/src/api/mmlManage/udmOperate.ts @@ -1,28 +1,21 @@ -import { RESULT_CODE_SUCCESS } from '@/constants/result-constants'; import { request } from '@/plugins/http-fetch'; -import { parseObjLineToHump } from '@/utils/parse-utils'; /** * 查询UDM可用cmd命令 * @returns object */ export async function getMMLByUDM() { - // 发起请求 - const result = await request({ - url: `/api/rest/databaseManagement/v1/elementType/omc_db/objectType/mml_subscriber`, + return request({ + url: '/tool/mml/subscriber/list', method: 'GET', params: { - SQL: `select * from mml_subscriber where ne_type = 'UDM' and status = 'Active'`, + neType: 'UDM', + status: 'Active', + pageNum: 1, + pageSize: 1000, }, + timeout: 60_000, }); - // 解析数据 - if (result.code === RESULT_CODE_SUCCESS && Array.isArray(result.data.data)) { - let data = result.data.data[0]; - return Object.assign(result, { - data: parseObjLineToHump(data['mml_subscriber']), - }); - } - return result; } /** @@ -32,16 +25,15 @@ export async function getMMLByUDM() { * @returns */ export async function sendMMlByUDM(neId: string, cmdArr: string[]) { - // 发起请求 - const result = await request({ - url: `/api/rest/operationManagement/v1/elementType/UDM/objectType/mml?ne_id=${neId}`, + return request({ + url: '/tool/mml/command', method: 'POST', - data: { mml: cmdArr }, + data: { + neType: 'UDM', + neId: neId, + type: 'General', + command: cmdArr, + }, timeout: 180_000, }); - // 解析数据 - if (result.code === RESULT_CODE_SUCCESS && Array.isArray(result.data.data)) { - result.data = result.data.data; - } - return result; } diff --git a/src/api/monitor/cache.ts b/src/api/monitor/cache.ts index 37ef06ed..7019498a 100644 --- a/src/api/monitor/cache.ts +++ b/src/api/monitor/cache.ts @@ -29,7 +29,7 @@ export function listCacheName() { */ export function listCacheKey(cacheName: string) { return request({ - url: `/monitor/cache//keys`, + url: `/monitor/cache/keys`, method: 'GET', params: { cacheName }, }); diff --git a/src/api/neData/amf.ts b/src/api/neData/amf.ts index 77895799..824c2bb4 100644 --- a/src/api/neData/amf.ts +++ b/src/api/neData/amf.ts @@ -29,14 +29,14 @@ export function delAMFDataUE(ueIds: string | number) { /** * AMF-UE会话列表导出 - * @param data 查询列表条件 + * @param query 查询列表条件 * @returns object */ -export function exportAMFDataUE(data: Record) { +export function exportAMFDataUE(query: Record) { return request({ url: '/neData/amf/ue/export', - method: 'POST', - data, + method: 'GET', + params: query, responseType: 'blob', timeout: 60_000, }); diff --git a/src/api/neData/ims.ts b/src/api/neData/ims.ts index b56486a5..cbefa062 100644 --- a/src/api/neData/ims.ts +++ b/src/api/neData/ims.ts @@ -29,14 +29,14 @@ export function delIMSDataCDR(cdrIds: string | number) { /** * IMS-CDR会话列表导出 - * @param data 查询列表条件 + * @param query 查询列表条件 * @returns object */ -export function exportIMSDataCDR(data: Record) { +export function exportIMSDataCDR(query: Record) { return request({ url: '/neData/ims/cdr/export', - method: 'POST', - data, + method: 'GET', + params: query, responseType: 'blob', timeout: 60_000, }); diff --git a/src/api/neData/mme.ts b/src/api/neData/mme.ts index 6b1bbe3b..de5f63f9 100644 --- a/src/api/neData/mme.ts +++ b/src/api/neData/mme.ts @@ -29,14 +29,14 @@ export function delMMEDataUE(ueIds: string | number) { /** * MME-UE会话列表导出 - * @param data 查询列表条件 + * @param query 查询列表条件 * @returns object */ -export function exportMMEDataUE(data: Record) { +export function exportMMEDataUE(query: Record) { return request({ url: '/neData/mme/ue/export', - method: 'POST', - data, + method: 'GET', + params: query, responseType: 'blob', timeout: 60_000, }); diff --git a/src/api/neData/nb-state.ts b/src/api/neData/nb-state.ts index bb62e9ad..8e1732a5 100644 --- a/src/api/neData/nb-state.ts +++ b/src/api/neData/nb-state.ts @@ -16,14 +16,14 @@ export function listNBState(query: Record) { /** * 历史记录列表导出 - * @param data 查询列表条件 + * @param query 查询列表条件 * @returns object */ -export function exportNBState(data: Record) { +export function exportNBState(query: Record) { return request({ url: '/neData/nb-state/export', - method: 'POST', - data, + method: 'GET', + params: query, responseType: 'blob', timeout: 60_000, }); diff --git a/src/api/neData/sgwc.ts b/src/api/neData/sgwc.ts index 1cb3853f..b7ea17c7 100644 --- a/src/api/neData/sgwc.ts +++ b/src/api/neData/sgwc.ts @@ -29,14 +29,14 @@ export function delSGWCDataCDR(cdrIds: string | number) { /** * SGWC-CDR会话列表导出 - * @param data 查询列表条件 + * @param query 查询列表条件 * @returns object */ -export function exportSGWCDataCDR(data: Record) { +export function exportSGWCDataCDR(query: Record) { return request({ url: '/neData/sgwc/cdr/export', - method: 'POST', - data, + method: 'GET', + params: query, responseType: 'blob', timeout: 60_000, }); diff --git a/src/api/neData/smf.ts b/src/api/neData/smf.ts index 9b87a10f..61f79cea 100644 --- a/src/api/neData/smf.ts +++ b/src/api/neData/smf.ts @@ -29,14 +29,14 @@ export function delSMFDataCDR(cdrIds: string | number) { /** * SMF-CDR会话列表导出 - * @param data 查询列表条件 + * @param query 查询列表条件 * @returns object */ -export function exportSMFDataCDR(data: Record) { +export function exportSMFDataCDR(query: Record) { return request({ url: '/neData/smf/cdr/export', - method: 'POST', - data, + method: 'GET', + params: query, responseType: 'blob', timeout: 60_000, }); diff --git a/src/api/neData/smsc.ts b/src/api/neData/smsc.ts index bcbe6545..88235405 100644 --- a/src/api/neData/smsc.ts +++ b/src/api/neData/smsc.ts @@ -29,14 +29,14 @@ export function delSMSCDataCDR(cdrIds: string | number) { /** * SMSC-CDR会话列表导出 - * @param data 查询列表条件 + * @param query 查询列表条件 * @returns object */ -export function exportSMSCDataCDR(data: Record) { +export function exportSMSCDataCDR(query: Record) { return request({ url: '/neData/smsc/cdr/export', - method: 'POST', - data, + method: 'GET', + params: query, responseType: 'blob', timeout: 60_000, }); diff --git a/src/api/neUser/n3iwf.ts b/src/api/neUser/n3iwf.ts index 3e2c4ece..4a028dbd 100644 --- a/src/api/neUser/n3iwf.ts +++ b/src/api/neUser/n3iwf.ts @@ -3,36 +3,14 @@ import { request } from '@/plugins/http-fetch'; import { parseObjLineToHump } from '@/utils/parse-utils'; /** - * 查询列表 - * @param query 查询参数 + * N3IWF-在线订阅用户列表信息 + * @param query 查询参数 {imsi} * @returns object */ -export async function listN3iwf(query: Record) { - const result = await request({ - url: '/api/rest/ueManagement/v1/elementType/n3iwf/objectType/ueInfo', +export function listN3IWFSubList(query: Record) { + return request({ + url: '/neData/n3iwf/sub/list', method: 'GET', params: query, }); - const data = { - data: { total: 0, rows: [] as any }, - code: result.code, - msg: result.msg, - }; - // 解析数据 - if (result.code === RESULT_CODE_SUCCESS && Array.isArray(result.data.data)) { - const rows = parseObjLineToHump(result.data.data); - data.data.total = rows.length; - data.data.rows = rows; - } - // 模拟数据 - // data.rows = [ - // { - // "activeTime": "2023-11-29 06:35:43", - // "imsi": "460302072701181", - // "nai": "0460302072701181@nai.epc.mnc030.mcc460.3gppnetwork.org", - // "regState": 1 - // } - // ] - - return data; } diff --git a/src/api/neUser/nssf.ts b/src/api/neUser/nssf.ts index 817c7361..9050bb47 100644 --- a/src/api/neUser/nssf.ts +++ b/src/api/neUser/nssf.ts @@ -3,24 +3,24 @@ import { request } from '@/plugins/http-fetch'; import { parseObjLineToHump } from '@/utils/parse-utils'; /** - * 查询列表 + * NSSF-在线订阅用户列表信息 + * @param query 查询参数 {imsi} * @returns object */ -export async function listNSSF() { - const result = await request({ - url: '/api/rest/ueManagement/v1/elementType/nssf/objectType/subscriptions', +export function listNSSFSubList() { + return request({ + url: '/neData/nssf/sub/list', + method: 'GET', + }); +} + +/** + * NSSF-可用AMF列表信息 + * @returns object + */ +export function listNSSFAmfList() { + return request({ + url: '/neData/nssf/amf/list', method: 'GET', }); - let data = { - data: { total: 0, rows: [] as any }, - code: result.code, - msg: result.msg, - }; - // 解析数据 - if (result.code === RESULT_CODE_SUCCESS && Array.isArray(result.data.data)) { - const rows = parseObjLineToHump(result.data.data); - data.data.total = rows.length; - data.data.rows = rows; - } - return data; } diff --git a/src/api/neUser/nssfAmf.ts b/src/api/neUser/nssfAmf.ts deleted file mode 100644 index edf06582..00000000 --- a/src/api/neUser/nssfAmf.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { RESULT_CODE_SUCCESS } from '@/constants/result-constants'; -import { request } from '@/plugins/http-fetch'; -import { parseObjLineToHump } from '@/utils/parse-utils'; - -/** - * 查询列表 - * @returns object - */ -export async function listNSSFAMF() { - const result = await request({ - url: '/api/rest/ueManagement/v1/elementType/nssf/objectType/availableAMFs', - method: 'GET', - }); - const data = { - data: { total: 0, rows: [] as any }, - code: result.code, - msg: result.msg, - }; - // 解析数据 - if (result.code === RESULT_CODE_SUCCESS && Array.isArray(result.data.data)) { - const rows = parseObjLineToHump(result.data.data); - data.data.total = rows.length; - data.data.rows = rows; - } - - // let testData = { - // total:0, - // rows: [ - // { - // nfId: '001', - // amfSetId: '001', - // }, - // { - // nfId: '002', - // amfSetId: '[001,002]', - // }, - // ], - // code: 1, - // msg:'', - // }; - //return testData; - return data; -} diff --git a/src/api/perfManage/customData.ts b/src/api/perfManage/customData.ts index d398044b..f35fb27f 100644 --- a/src/api/perfManage/customData.ts +++ b/src/api/perfManage/customData.ts @@ -8,7 +8,7 @@ import { request } from '@/plugins/http-fetch'; export async function listCustomData(query: Record) { // 发起请求 const result = await request({ - url: `/pm/kpiC/report`, + url: `/neData/kpic/data`, method: 'GET', params: query, timeout: 60_000, diff --git a/src/api/perfManage/customTarget.ts b/src/api/perfManage/customTarget.ts index be5c6d05..5e6b5824 100644 --- a/src/api/perfManage/customTarget.ts +++ b/src/api/perfManage/customTarget.ts @@ -1,30 +1,16 @@ import { request } from '@/plugins/http-fetch'; /** - * 新 查询自定义指标 + * 查询自定义指标 * @param query 查询参数 * @returns object */ export async function listCustom(query?: Record) { - // 发起请求 - const result = await request({ - url: `/pm/kpiC/title/totalList`, + return await request({ + url: `/neData/kpic/title/list`, method: 'GET', params: query, }); - return result; -} - -/** - * 查询自定义指标详细 - * @param id 网元ID - * @returns object - */ -export async function getCustom(id: string | number) { - return request({ - url: `/pm/kpiC/title/${id}`, - method: 'GET', - }); } /** @@ -34,7 +20,7 @@ export async function getCustom(id: string | number) { */ export function addCustom(data: Record) { return request({ - url: `/pm/kpiC/title`, + url: `/neData/kpic/title`, method: 'POST', data: data, }); @@ -47,7 +33,7 @@ export function addCustom(data: Record) { */ export function updateCustom(data: Record) { return request({ - url: `/pm/kpiC/title/${data.id}`, + url: `/neData/kpic/title`, method: 'PUT', data: data, }); @@ -59,7 +45,7 @@ export function updateCustom(data: Record) { */ export async function delCustom(data: Record) { return request({ - url: `/pm/kpiC/title/${data.id}`, + url: `/neData/kpic/title?id=${data.id}`, method: 'DELETE', }); } diff --git a/src/api/system/login-source.ts b/src/api/system/login-source.ts new file mode 100644 index 00000000..e1d923e8 --- /dev/null +++ b/src/api/system/login-source.ts @@ -0,0 +1,64 @@ +import { request } from '@/plugins/http-fetch'; + +/** + * 查询登录源列表 + * @param query 查询参数 + * @returns object + */ +export function listLoginSource(query: Record) { + return request({ + url: '/system/login-source/list', + method: 'GET', + params: query, + }); +} + +/** + * 查询登录源详细 + * @param id 登录源ID + * @returns object + */ +export function getLoginSource(id: string | number) { + return request({ + url: `/system/login-source/${id}`, + method: 'GET', + }); +} + +/** + * 新增登录源 + * @param data 登录源对象 + * @returns object + */ +export function addLoginSource(data: Record) { + return request({ + url: '/system/login-source', + method: 'POST', + data: data, + }); +} + +/** + * 修改登录源 + * @param data 登录源对象 + * @returns object + */ +export function updateLoginSource(data: Record) { + return request({ + url: '/system/login-source', + method: 'PUT', + data: data, + }); +} + +/** + * 认证源删除 + * @param id 登录源ID + * @returns object + */ +export function delLoginSource(id: string | number) { + return request({ + url: `/system/login-source/${id}`, + method: 'DELETE', + }); +} diff --git a/src/api/tool/mml.ts b/src/api/tool/mml.ts new file mode 100644 index 00000000..ad1a08d3 --- /dev/null +++ b/src/api/tool/mml.ts @@ -0,0 +1,25 @@ +import { request } from '@/plugins/http-fetch'; + +// 更新网元配置重新载入 +export function updateNeConfigReload(neType: string, neId: string) { + return request({ + url: '/tool/mml/command', + method: 'POST', + data: { + neType: neType, + neId: neId, + type: 'General', + command: ['reload'], + }, + timeout: 180_000, + }); +} + +// MMML日志列表 +export function mmlLogList(query: Record) { + return request({ + url: '/tool/mml/log/list', + method: 'GET', + params: query, + }); +} diff --git a/src/i18n/locales/en-US.ts b/src/i18n/locales/en-US.ts index 485d9614..a8e14239 100644 --- a/src/i18n/locales/en-US.ts +++ b/src/i18n/locales/en-US.ts @@ -261,12 +261,16 @@ export default { login: { tabPane1: 'Account password login', tabPane2: 'Login with phone number', - registerBtn: 'Register an account', + registerBtn: 'Register Account', loginBtn: 'Sign In', loginSuccess: 'Login Successful', - loginMethod: 'Other login methods:', - loginMethodWX: 'WeChat Scan Login', - loginMethodQQ: 'QQ Scan Code Login', + otherMethod: 'Other Methods', + backBtn: 'Back', + backBtnLogin: 'Return Login', + authorizedNotfound: 'Authorized Not Found', + authorizedFailed: 'Authorized Failed', + authorizedSuccess: 'Authorized Successful', + redirectHome: 'Redirect to home page in {i} seconds', }, register: { registerBtn: 'Register', @@ -357,6 +361,54 @@ export default { description: "No data yet, try refreshing", }, }, + cbc:{ + cbe:{ + neType:'CBC Object', + title: ' CBC Event', + delTip: 'Confirm deletion of the event data item numbered [{num}]?', + eventName: 'Event Name', + startTime: 'Start Time', + endTime: 'End Time', + repetitionPeriod: 'Repetition Period', + numOfBcast: 'Number of Broadcasts', + msgPWSType: 'Message Type', + messageId: 'Message ID', + displayMode: 'Display Mode', + geoScope:' Geographic Scope', + emergencyUserAlert: 'Emergency User Alert', + activatePopup: 'Activate Popup', + warningType: 'Warning Type', + language:' Language', + warningMessageText:' Broadcast Content', + status: 'Status', + warningAreaType: 'Warning Area Type', + taiListTip:'TAI List cannot be empty', + taiSonTip:'TAI List each item MCC, MNC, TAC cannot be empty', + eutraListTip:'EUTRA CellId List cannot be empty', + eutraSonTip:'EUTRA CellId List each item MCC, MNC, CellId cannot be empty', + nrTip:'NR CellId List cannot be empty', + nrSonTip:'NR CellId List each item MCC, MNC, CellId cannot be empty', + areaTip:'Area ID List cannot be empty', + areaSonTip:'Area ID List each item AreaID cannot be empty', + messageIdProfile:'Message ID Profile', + serialNumProfile:'Serial Num Profile', + warningTypeProfile:'Warning Type Profile', + warningMessageProfile:'Warning Message Profile', + etws:'Earthquake and Tsunami Warning System', + cmas:'Commercial Mobile Alert System', + createdAt:'Create Time', + eventNameHelp:'If it is CMAS, the recommended prefix is cmas_xxx. If it is ETWS, the recommended prefix is etws_xxx', + repetitionPeriodHelp:'Unit is seconds', + numOfBcastHelp:'Number of Broadcasts', + cellListTip:'CellId List cannot be empty', + cellListSonTip:'MCC、MNC、 Cannot be empty, and at least one EUTRA CellId/NR CellId must be filled in', + letupSure:'Do you confirm the status of the broadcast event with the modification number 【{id}】?', + tacHelp:'The TAC value is a decimal string, separated by ";" for multiple TAC values.', + cellIdHelp:'The CellId value is a hexadecimal string, separated by ";" for multiple CellId values.', + areaId:'The areaId value is a hexadecimal string.', + detail:'Detail', + } + }, dashboard: { overview:{ title: "Core Network Dashboard", @@ -368,10 +420,13 @@ export default { imsUeNum: "VoNR/VoLTE", smfUeNum: "Data Sessions", gnbBase: "Online gNodeB", + gnbSumBase: "Total gNodeB", enbBase: "Online eNodeB", + enbSumBase: "Total eNodeB", gnbUeNum:'5G Active Users', enbUeNum:'4G Active Users', baseTitle:'Online Information', + nodeBInfo: 'NodeB Information', }, upfFlow:{ title: "UPF Throughput", @@ -401,6 +456,7 @@ export default { }, userActivity: { title: "User Activity", + imsTitle: "IMS Activity", type: "Type", duration: "Duration", caller: "Caller", @@ -443,6 +499,14 @@ export default { sgwcVolumeGPRSUplink: 'GPRS Uplink', sgwcVolumeGPRSDownlink: 'GPRS Downlink', }, + chart:{ + charttitle:'Data Usage Report', + uplink:'Uplink(Byte)', + downlink:'Downlink(Byte)', + datausage:'Data Usage', + totaluplink:'Total Uplink', + totaldownlink:'Total Downlink', + }, ue: { eventType: "Event Type", realTimeDataStart: "Turn on real-time data", @@ -675,7 +739,7 @@ export default { toIpPleace: "Please input the remote backup server IP address", toPort: "Service Port", username: "UserName", - usernamePleace: 'Please enter the service login username', + usernamePleace: 'Please enter the service login username', password: "Password", dir: "Save Dir", dirPleace: 'Please enter the service address target file directory', @@ -1053,6 +1117,21 @@ export default { "chooseShowMetrics":"Select the metric you want to display", "chooseMetrics":"Select an indicator", }, + voiceOverView:{ + "voiceTitle":"Voice Calls Dashboard", + "tips":"Data and voice statistics per minute", + "ne":"NE", + "now":"now", + "last":"last", + "calls":"Calls", + "activeCall":"active calls", + "callMOMT":"calls MO/MT", + "failedcall":"failed calls", + "registration":"Registrations", + "activeregistration":"active registrations", + "registrationsuccess":"registration success", + "failedregistration":"failed registrations total", + }, }, traceManage: { pcap: { @@ -1637,11 +1716,12 @@ export default { userName: 'Nick Name', permission: 'Role', className: 'Department', + userType: 'User Type', loginIp: 'Login Address', 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:'Please enter the correct password format', + userNameTip:'Please enter the correct username format no less than 4 digits', + passwdTip:'Please enter the correct password format no less than 6 digits', nickNameTip:'Nicknames no less than 2 digits', emailTip:'Please enter the correct email address', phoneTip:'Please enter the correct phone number', @@ -1699,6 +1779,55 @@ export default { refreshCacheTip: "Are you sure you want to refresh the parameter configuration cache?", refreshCacheOk: "Refresh Cache Successful", }, + loginSource: { + uid: "UID", + name: "Name", + namePlease: 'Please enter the authentication source name correctly', + icon: "Icon", + iconPlease: 'You can enter the image link or upload the image path address', + type: "Type", + activeFlag: "Status", + remark: "Remark", + createTime: "Create Time", + updateTime: "Update Time", + ldapUrl: "Server Address", + ldapUrlPlease: 'Please enter the LDAP server address correctly', + ldapBaseDN: "Base DN", + baseDnPlease: 'Please enter the LDAP base DN correctly', + ldapUserFilter: "User Filter", + userFilterPlease: 'Please enter the LDAP user filter correctly', + ldapBindDN: "Bind DN", + ldapBindPassword: "Bind Password", + smtpHost: 'Server Address', + smtpHostPlease: 'Please enter the SMTP server address correctly', + smtpPort: 'Port Number', + smtpPortPlease: 'Please enter the SMTP port number correctly', + oauth2ClientID: 'Client ID', + oauth2ClientIDPlease: 'Please enter the OAuth2 client ID correctly', + oauth2ClientSecret: 'Client Secret', + oauth2ClientSecretPlease: 'Please enter the OAuth2 client secret correctly', + oauth2AuthURL: 'Authorization URL', + oauth2AuthURLPlease: 'Please enter the OAuth2 authorization URL correctly', + oauth2TokenURL: 'Token URL', + oauth2TokenURLPlease: 'Please enter the OAuth2 token URL correctly', + oauth2UserURL: 'User Info URL', + oauth2UserURLPlease: 'Please enter the OAuth2 user info URL correctly', + oauth2AccountField: 'Account Field', + oauth2AccountFieldPlease: 'Please enter the OAuth2 account field correctly', + oauth2Scopes: 'Scopes', + oauth2ScopesPlease: 'Please enter the OAuth2 scopes correctly', + oauth2RedirectURL: 'Redirect URL', + oauth2RedirectURLPlease: 'Please enter the OAuth2 redirect URL correctly', + oauth2RedirectURLTip: 'Please jump to the specified path (omchost/#/login/oauth2), redirect with code and state address parameters', + uploadFileTip: 'Confirm to upload the authentication source icon?', + uploadFileOk: 'Authentication source icon upload successful', + uploadFileErr: 'Authentication source icon upload failed', + viewInfoErr: "Failed to get authentication source information", + addInfo: "Add Authentication Source", + editInfo: "Modify Authentication Source", + delTip: "Confirm deleting the authentication source number [{num}] data item?", + delOk: "Deleted Successfully", + }, setting: { charMaxLen: 'characters length', saveSubmit: 'Submit&Save', diff --git a/src/i18n/locales/zh-CN.ts b/src/i18n/locales/zh-CN.ts index 6afa5faa..367db62a 100644 --- a/src/i18n/locales/zh-CN.ts +++ b/src/i18n/locales/zh-CN.ts @@ -264,9 +264,13 @@ export default { registerBtn: '注册账号', loginBtn: '登录', loginSuccess: '登录成功', - loginMethod: '其他登录方式:', - loginMethodWX: '微信扫一扫登录', - loginMethodQQ: 'QQ扫码登录', + otherMethod: '其他方式', + backBtn: '返回', + backBtnLogin: '返回登录', + authorizedNotfound: '授权无效', + authorizedFailed: '授权失败', + authorizedSuccess: '授权成功', + redirectHome: '{i} 秒后跳转主页', }, register: { registerBtn: '注册', @@ -357,6 +361,54 @@ export default { description: "暂无数据,尝试刷新看看", }, }, + cbc:{ + cbe:{ + neType:'CBC网元对象', + title: '广播事件', + delTip: '确认删除编号为【{num}】的CBC事件吗?', + eventName: '事件名称', + startTime: '开始时间', + endTime: '结束时间', + repetitionPeriod: '广播周期', + numOfBcast: '广播次数', + msgPWSType: '消息类型', + messageId: '消息编号', + displayMode: '显示模式', + geoScope:'广播覆盖范围', + emergencyUserAlert: '紧急用户提示', + activatePopup: '弹窗提示', + warningType: '预警类型标识', + language:'语言', + warningMessageText:'广播内容', + status: '状态', + warningAreaType: '预警区域类型', + taiListTip:'TAI List 不能为空', + taiSonTip:'TAI List 每项的 MCC、MNC、TAC 都不能为空', + eutraListTip:'EUTRA CellId List 不能为空', + eutraSonTip:'EUTRA CellId List 每项的 MCC、MNC、CellId 都不能为空', + nrTip:'NR CellId List 不能为空', + nrSonTip:'NR CellId List 每项的 MCC、MNC、CellId 都不能为空', + areaTip:'Area ID List 不能为空', + areaSonTip:'Area ID List 每项的 AreaID 都不能为空', + messageIdProfile:'消息标识配置', + serialNumProfile:'序列号配置', + warningTypeProfile:'预警类型配置', + warningMessageProfile:'预警消息配置', + etws:'地震海啸预警', + cmas:'公共预警广播', + createdAt:'创建时间', + eventNameHelp:'如果为CMAS,推荐前缀为cmas_xxx,如果为ETWS,推荐前缀为etws_xxx', + repetitionPeriodHelp:'单位是秒', + numOfBcastHelp:'广播帮助的数量', + cellListTip:'CellId List不能为空', + cellListSonTip:'MCC、MNC、不能为空以及EUTRA CellId/NR CellId至少填写一个', + letupSure:'确认修改编号为 【{id}】 的广播事件的状态嘛?', + tacHelp:'TAC值是十进制字符串,通过";"分隔多个TAC值', + cellIdHelp:'CellId值是十六进制字符串,通过";"分隔多个CellId值', + areaId:'areaId值是十六进制字符串', + detail:'详情', + } + }, dashboard: { overview:{ title: "核心网系统看板", @@ -367,11 +419,14 @@ export default { userTitle:'用户信息', imsUeNum: "IMS 会话数", smfUeNum: "Data 会话数", - gnbBase: "5G 基站数", + gnbBase: "5G 基站在线数", + gnbSumBase: "5G 基站总数", gnbUeNum:'5G 用户数', - enbBase: "4G 基站数", + enbBase: "4G 基站在线数", + enbSumBase: "4G 基站总数", enbUeNum:'4G 用户数', baseTitle:'在线信息', + nodeBInfo: '基站信息', }, upfFlow:{ title: "用户面吞吐量", @@ -401,6 +456,7 @@ export default { }, userActivity: { title: "用户活动", + imsTitle: "IMS 活动", type: "类型", duration: "时长", caller: "主叫", @@ -443,6 +499,14 @@ export default { sgwcVolumeGPRSUplink: 'GPRS 上行链路', sgwcVolumeGPRSDownlink: 'GPRS 下行链路', }, + chart:{ + charttitle:'数据使用报告', + uplink:'上行流量(B)', + downlink:'下行流量(B)', + datausage:'流量使用', + totaluplink:'总上行流量', + totaldownlink:'总下行流量', + }, ue: { eventType: "事件类型", realTimeDataStart: "开启实时数据", @@ -675,7 +739,7 @@ export default { toIpPleace: "请输入远程备份服务器 IP 地址", toPort: "服务端口", username: "登录用户名", - usernamePleace: '请输入服务登录用户名', + usernamePleace: '请输入服务登录用户名', password: "登录密码", dir: "保存目录", dirPleace: '请输入服务地址目标文件目录', @@ -1053,6 +1117,21 @@ export default { "chooseShowMetrics":"选择需要显示的指标", "chooseMetrics":"选择指标", }, + voiceOverView:{ + "voiceTitle":"语音通话仪表盘", + "tips":"每分钟数据语音统计", + "ne":"网元", + "now":"现在", + "last":"过去", + "calls":"呼叫", + "activeCall":"正在通话", + "callMOMT":"呼叫 主叫接通率/被叫接通率", + "failedcall":"失败呼叫", + "registration":"注册", + "activeregistration":"主动注册", + "registrationsuccess":"注册成功率", + "failedregistration":"失败注册", + }, }, traceManage: { pcap: { @@ -1635,13 +1714,14 @@ export default { userNum: '用户编号', account: '登录账号', userName: '用户昵称', - permission: '用户权限', + permission: '用户角色', className: '部门名称', + userType: '用户类型', loginIp: '登录地址', loginTime: '登录时间', status: '用户状态', - userNameTip:'账号只能包含大写字母、小写字母和数字的字符串,长度至少为6位', - passwdTip:'请输入正确的密码格式', + userNameTip:'请输入正确的用户名格式不少于4位', + passwdTip:'请输入正确的密码格式不少于6位', nickNameTip:'昵称不少于2位', emailTip:'请输入正确的邮箱地址', phoneTip:'请输入正确的手机号码', @@ -1699,6 +1779,55 @@ export default { refreshCacheTip: "确定要刷新参数配置缓存吗?", refreshCacheOk: "刷新缓存成功", }, + loginSource: { + uid: "唯一标识", + name: "名称", + namePlease: '请正确输入认证源名称', + icon: "图标", + iconPlease: '可填入图片链接或上传图片路径地址', + type: "类型", + activeFlag: "状态", + remark: "备注说明", + createTime: "创建时间", + updateTime: "更新时间", + ldapUrl: "服务器地址", + ldapUrlPlease: '请正确输入LDAP 服务器地址', + ldapBaseDN: "基础DN", + baseDnPlease: '请正确输入LDAP 基础DN', + ldapUserFilter: "用户过滤", + userFilterPlease: '请正确输入LDAP 用户过滤', + ldapBindDN: "绑定DN", + ldapBindPassword: "绑定密码", + smtpHost: '服务器地址', + smtpHostPlease: '请正确输入SMTP 服务器地址', + smtpPort: '端口号', + smtpPortPlease: '请正确输入SMTP 端口号', + oauth2ClientID: '客户端ID', + oauth2ClientIDPlease: '请正确输入OAuth2 客户端ID', + oauth2ClientSecret: '客户端密钥', + oauth2ClientSecretPlease: '请正确输入OAuth2 客户端密钥', + oauth2AuthURL: '授权URL', + oauth2AuthURLPlease: '请正确输入OAuth2 授权URL', + oauth2TokenURL: '令牌URL', + oauth2TokenURLPlease: '请正确输入OAuth2 令牌URL', + oauth2UserURL: '用户信息URL', + oauth2UserURLPlease: '请正确输入OAuth2 用户信息URL', + oauth2AccountField: '账号字段', + oauth2AccountFieldPlease: '请正确输入OAuth2 账号字段', + oauth2Scopes: '作用域', + oauth2ScopesPlease: '请正确输入OAuth2 作用域', + oauth2RedirectURL: '重定向URL', + oauth2RedirectURLPlease: '请正确输入OAuth2 重定向URL', + oauth2RedirectURLTip: '请跳转指定路径(omchost/#/login/oauth2), 重定向携带code和state地址参数', + uploadFileTip: '确认要上传认证源图标吗?', + uploadFileOk: '认证源图标上传成功', + uploadFileErr: '认证源图标上传失败', + viewInfoErr: "获取认证源信息失败", + addInfo: "添加认证源", + editInfo: "修改认证源", + delTip: "确认删除认证源编号为 【{num}】 的数据项?", + delOk: "删除成功", + }, setting: { charMaxLen: '位字符长度', saveSubmit: '提交保存', diff --git a/src/layouts/components/RightContent.vue b/src/layouts/components/RightContent.vue index 7ca4ad41..64b85eb4 100644 --- a/src/layouts/components/RightContent.vue +++ b/src/layouts/components/RightContent.vue @@ -80,7 +80,12 @@ function fnChangeLocale(e: any) { - + + + + + diff --git a/src/views/dashboard/overview2/components/NeResources/index.vue b/src/views/dashboard/overview2/components/NeResources/index.vue new file mode 100644 index 00000000..1915fab4 --- /dev/null +++ b/src/views/dashboard/overview2/components/NeResources/index.vue @@ -0,0 +1,369 @@ + + + + + diff --git a/src/views/dashboard/overview2/components/Topology/index.vue b/src/views/dashboard/overview2/components/Topology/index.vue new file mode 100644 index 00000000..6c4c36fd --- /dev/null +++ b/src/views/dashboard/overview2/components/Topology/index.vue @@ -0,0 +1,337 @@ + + + + + diff --git a/src/views/dashboard/overview2/components/UPFFlow/index.vue b/src/views/dashboard/overview2/components/UPFFlow/index.vue new file mode 100644 index 00000000..482aff9d --- /dev/null +++ b/src/views/dashboard/overview2/components/UPFFlow/index.vue @@ -0,0 +1,290 @@ + + + + + diff --git a/src/views/dashboard/overview2/components/UserActivity/index.vue b/src/views/dashboard/overview2/components/UserActivity/index.vue new file mode 100644 index 00000000..ed46022f --- /dev/null +++ b/src/views/dashboard/overview2/components/UserActivity/index.vue @@ -0,0 +1,314 @@ + + + + + diff --git a/src/views/dashboard/overview2/css/index.css b/src/views/dashboard/overview2/css/index.css new file mode 100644 index 00000000..13d639c6 --- /dev/null +++ b/src/views/dashboard/overview2/css/index.css @@ -0,0 +1,506 @@ +.viewport { + /* 限定大小 */ + min-width: 1024px; + max-width: 1920px; + min-height: 780px; + margin: 0 auto; + position: relative; + display: flex; + padding: 5rem 0.833rem 0; + line-height: 1.15; + background-image: + linear-gradient(rgba(0, 0, 0, 0.75), rgba(0, 0, 0, 0.75)), + url(../images/bj.png); + height: 100vh; + margin-bottom: -20px; + background-size:80% 80%; + background-attachment:fixed; + -webkit-background-size: cover; +} +.column { + flex: 2; + position: relative; + display: flex; + flex-direction: column; +} + +/* 边框 */ +.panel { + box-sizing: border-box; + border: 2px solid rgba(252, 252, 252, 0); + border-width: 2.125rem 1.583rem 0.875rem 5.5rem; + position: relative; + margin-bottom: 0.833rem; + +} +/* 使用伪元素创建L形角框 */ +/* 添加L形角框边框效果 */ +.panel::before, +.panel::after { + content: ''; + position: absolute; + pointer-events: none; + z-index: 10; + display: none; /* 隐藏所有角框 */ +} + +/* 左上角L形 - 相对于inner的实际边界 */ +.panel::before { + top: -2.125rem; + left: -5.5rem; + width: 10px; + height: 10px; + border-top: 3px solid #4c9bfd; + border-left: 3px solid #4c9bfd; +} + +/* 右下角L形 - 相对于inner的实际边界 */ +.panel::after { + bottom: -0.875rem; + right: -1.583rem; + width: 10px; + height: 10px; + border-bottom: 3px solid #4c9bfd; + border-right: 3px solid #4c9bfd; +} + +/* 右上角L形 - 相对于inner的实际边界 */ +.panel .inner::before { + content: ''; + position: absolute; + top: 0; + right: 0; + width: 10px; + height: 10px; + border-top: 3px solid #4c9bfd; + border-right: 3px solid #4c9bfd; + pointer-events: none; + z-index: 10; + display: none; /* 隐藏所有角框 */ +} + +/* 左下角L形 - 相对于inner的实际边界 */ +.panel .inner::after { + content: ''; + position: absolute; + bottom: 0; + left: 0; + width: 10px; + height: 10px; + border-bottom: 3px solid #4c9bfd; + border-left: 3px solid #4c9bfd; + pointer-events: none; + z-index: 10; + display: none; /* 隐藏所有角框 */ +} + +/* 为base模块调整角框显示 */ +/* 第一个base模块:只显示上方角框(左上角和右上角) */ +.skim.panel.base:first-of-type::after, +.skim.panel.base:first-of-type .inner::after { + display: none; +} + +/* 第二个base模块:只显示下方角框(左下角和右下角) */ +.skim.panel.base:not(:first-of-type)::before, +.skim.panel.base:not(:first-of-type) .inner::before { + display: none; +} +.panel .inner { + /* 装内容 */ + /* height: 60px; */ + position: absolute; + top: -2.125rem; + right: -1.583rem; + bottom: -0.875rem; + left: -5.5rem; + padding: 1rem 0.3rem; +} +.panel h3 { + font-size: 0.833rem; + color: #fff; + background: rgba(76, 155, 253, 0.1); /* 为所有模块标题添加淡蓝色背景 */ + padding: 0.5rem 1.2rem; + border-radius: 0.7rem 0.7rem 0 0; + margin: 0; + box-sizing: border-box; +} + +.leftright { + width: 100%; + min-height: 2.5rem; + /*background: url(../images/title.png) no-repeat center center;*/ + background: rgba(76, 155, 253, 0.1); /* 添加淡蓝色背景 */ + background-size: 100%; + color: #4c9bfd; + display: flex; + align-items: center; + justify-content: center; + font-weight: bold; + padding: 0.5rem 1.2rem; + border-radius: 0.7rem 0.7rem 0 0; + margin: 0; + box-sizing: border-box; + text-shadow: 0 1px 4px #000a; + flex-wrap: nowrap; + /* 保证内容不换行且居中 */ +} + +.leftright .title { + display: flex; + align-items: center; + justify-content: center; + width: 100%; + font-size: 1.2rem; + padding-left: 0; +} + +.centerStyle { + width: 100%; + min-height: 2.5rem; + /*background: url(../images/title.png) no-repeat center center;*/ + background: rgba(76, 155, 253, 0.1); /* 添加淡蓝色背景 */ + background-size: 90%; + color: #4c9bfd; + display: flex; + align-items: center; + justify-content: center; + font-weight: bold; + padding: 0.5rem 1.2rem; + border-radius: 0.7rem 0.7rem 0 0; + margin: 0; + box-sizing: border-box; + text-shadow: 0 1px 4px #000a; + flex-wrap: nowrap; + /* 保证内容不换行且居中 */ +} + +.centerStyle .title { + display: flex; + align-items: center; + justify-content: center; + width: 100%; + font-size: 1.2rem; + padding-left: 0; +} + +/* 总览标题 */ +.brand { + background-image: url(../images/newBrand.png); + background-repeat: no-repeat; + background-size: cover; + background-position: center center; + position: absolute; + top: 0.833rem; + left: 0; + right: 0; + width: 100%; + height: 5rem; + display: flex; + flex-direction: column; + align-items: center; + cursor: pointer; +} +.brand .brand-title { + color: #ffffff; + font-size: 1.4rem; + font-weight: 600; + padding-top: 1rem; + padding-bottom: 0.5rem; +} +.brand .brand-desc { + color: #d9d9d9; + font-size: 0.9rem; +} + +/* 实时流量 */ +.upfFlow { + /* min-height: 16rem; */ + height: 40%; +} +.upfFlow .inner .chart { + width: 100%; + height: 100%; + margin-top: 0rem; +} + +/* 网络拓扑 */ +.topology { + /* min-height: 27.8rem; */ + height: 46.4%; + flex: 1; +} +.topology .inner h3 { + display: flex; + flex-direction: row; + justify-content: space-between; + align-items: baseline; + background: rgba(76, 155, 253, 0.1); /* 为网络拓扑模块标题添加淡蓝色背景 */ + padding: 0.5rem 1.2rem; + border-radius: 0.7rem 0.7rem 0 0; + margin: 0; + box-sizing: border-box; +} +.topology .inner h3 .normal { + color: #52c41a; + font-size: 1.1rem; + margin-right: 8px; +} +.topology .inner h3 .abnormal { + color: #f5222d; + font-size: 1.1rem; +} +.topology .inner .chart { + width: 100%; + height: 100%; + margin-top: 0.1rem; +} + +/* 概览区域 */ +.skim { + /* min-height: 7.78rem; */ + height: 14.4%; +} +.skim .inner .data { + display: flex; + flex-direction: row; + align-items: center; + height: 90%; +} +.skim .inner .data .item { + display: flex; + flex-direction: column; + align-items: baseline; + width: 33%; +} +.skim .inner .data .item div { + font-size: 1.467rem; + color: #fff; + margin-bottom: 0; + display: flex; + align-items: baseline; + line-height: 2rem; +} +.skim .inner .data .item span { + color: #4c9bfd; + font-size: 0.833rem; + width: 100%; + position: relative; + line-height: 2rem; + white-space: nowrap; + text-align: start; + text-overflow: ellipsis; + overflow: hidden; +} +.skim .inner .data .item span::before { + content: ' '; + position: absolute; + top: 2px; + left: 0; + right: 0; + bottom: 0; + z-index: 0; + background-image: linear-gradient(to right, #fff, #fff0); + height: 1px; + border-radius: 4px; +} + +/* 概览区域 衍生基站信息 */ +.skim.base { + height: 11.25%; +} + +.skim.base .inner .data { + display: flex; + flex-direction: row; + align-items: center; + height: 75%; +} +.skim.base .inner .data .item { + display: flex; + flex-direction: column; + align-items: baseline; + width: 50%; +} + +/* 用户行为 */ +.userActivity { + /* min-height: 35.8rem; */ + height: 54.6%; + flex: 1; +} +.userActivity .inner .chart { + width: 100%; + height: 90%;/*生效了底部边距*/ + margin-top: 1rem; + padding-bottom: 1rem; + box-sizing: border-box;/*不知道为啥没生效*/ +} + +/* 流量统计 */ +.upfFlowTotal1 { + /* min-height: 7.5rem; */ + height: 14.4%; +} +.upfFlowTotal1 .inner h3 { + display: flex; + justify-content: space-between; + background: rgba(76, 155, 253, 0.1); /* 为流量统计模块标题添加淡蓝色背景 */ + padding: 0.5rem 1.2rem; + border-radius: 0.7rem 0.7rem 0 0; + margin: 0; + box-sizing: border-box; +} +.upfFlowTotal1 .inner h3 .filter { + display: flex; +} +.upfFlowTotal1 .inner h3 .filter span { + display: block; + height: 0.75rem; + line-height: 1; + padding: 0 0.75rem; + color: #1950c4; + font-size: 0.75rem; + border-right: 0.083rem solid #00f2f1; + cursor: pointer; +} +.upfFlowTotal1 .inner h3 .filter span:first-child { + padding-left: 0; +} +.upfFlowTotal1 .inner h3 .filter span:last-child { + border-right: none; +} +.upfFlowTotal1 .inner h3 .filter span.active { + color: #fff; + font-size: 0.833rem; +} +.upfFlowTotal1 .inner .chart { + width: 100%; + height: 100%; + margin-top: 0.1rem; +} +.upfFlowTotal1 .inner .chart .data { + display: flex; + flex-direction: column; + justify-content: space-around; + height: 60%; +} +.upfFlowTotal1 .inner .chart .data .item { + display: flex; + justify-content: space-between; + align-items: baseline; +} +.upfFlowTotal1 .inner .chart .data .item h4 { + font-size: 1.467rem; + color: #fff; + margin-bottom: 0; +} +.upfFlowTotal1 .inner .chart .data .item span { + color: #4c9bfd; + font-size: 0.867rem; +} + + +/* 流量统计 */ +.upfFlowTotal { + /* min-height: 7.5rem; */ + height: 14.4%; +} +.upfFlowTotal .inner h3 { + display: flex; + justify-content: space-between; + background: rgba(76, 155, 253, 0.1); /* 为流量统计模块标题添加淡蓝色背景 */ + padding: 0.5rem 1.2rem; + border-radius: 0.7rem 0.7rem 0 0; + margin: 0; + box-sizing: border-box; +} +.upfFlowTotal .inner h3 .filter { + display: flex; +} +.upfFlowTotal .inner h3 .filter span { + display: block; + height: 0.75rem; + line-height: 1; + padding: 0 0.75rem; + color: #1950c4; + font-size: 0.75rem; + border-right: 0.083rem solid #00f2f1; + cursor: pointer; +} +.upfFlowTotal .inner h3 .filter span:first-child { + padding-left: 0; +} +.upfFlowTotal .inner h3 .filter span:last-child { + border-right: none; +} +.upfFlowTotal .inner h3 .filter span.active { + color: #fff; + font-size: 0.833rem; +} +.upfFlowTotal .inner .chart { + width: 100%; + height: 100%; + margin-top: 0.1rem; +} +.upfFlowTotal .inner .chart .data { + display: flex; + flex-direction: column; + justify-content: space-around; + height: 60%; +} +.upfFlowTotal .inner .chart .data .item { + display: flex; + justify-content: space-between; + align-items: baseline; +} +.upfFlowTotal .inner .chart .data .item h4 { + font-size: 1.467rem; + color: #fff; + margin-bottom: 0; +} +.upfFlowTotal .inner .chart .data .item span { + color: #4c9bfd; + font-size: 0.867rem; +} + +/* 资源情况 */ +.resources { + /* min-height: 18rem; */ + height: 24.4%; +} +.resources .inner .chart { + width: 100%; + height: 100%; + margin-top: 2rem; +} + + +/* 告警统计 */ +.alarmType { + /* min-height: 25rem; */ + height: 35%; +} +.alarmType .inner .chart { + width: 100%; + height: 100%; +} + +/* 为base模块的第二个模块(4G部分)添加标题样式 */ +.skim.panel.base:not(:first-of-type) h3 { + background: transparent; /* 移除背景,避免阴影问题 */ + padding: 0; + margin: 0; + min-height: 0; + display: none; /* 完全隐藏空的h3元素 */ +} + +/* 跳转鼠标悬浮 */ +.toRouter:hover { + cursor: pointer; + color: #fff !important; +} +.toRouter:hover > *, +.toRouter:hover > * > * { + color: #fff !important; +} diff --git a/src/views/dashboard/overview2/hooks/useTopology.ts b/src/views/dashboard/overview2/hooks/useTopology.ts new file mode 100644 index 00000000..ff83a840 --- /dev/null +++ b/src/views/dashboard/overview2/hooks/useTopology.ts @@ -0,0 +1,197 @@ +import { parseDateToStr } from '@/utils/date-utils'; +import { computed, reactive, ref } from 'vue'; + +/**非网元元素 */ +export const notNeNodes = [ + '5GC', + 'DN', + 'UE', + 'Base', + 'lan', + 'lan1', + 'lan2', + 'lan3', + 'lan4', + 'lan5', + 'lan6', + 'lan7', + 'LAN', + 'NR', +]; + +/**图状态 */ +export const graphState = reactive>({ + /**当前图组名 */ + group: '5GC System Architecture', + /**图数据 */ + data: { + combos: [], + edges: [], + nodes: [], + }, +}); + +/**图实例对象 */ +export const graphG6 = ref(null); + +/**图点击选择 */ +export const graphNodeClickID = ref('UPF_001'); + +/**图节点网元信息状态 */ +export const graphNodeState = computed(() =>{ + return graphState.data.nodes.map((item: any) => ({ + id: item.id, + label: item.label, + neInfo: item.neInfo, + neState: item.neState, + neInfoList:item.neInfoList, + neStateMap: item.neStateMap, + })) +} + +); + +/**图节点网元状态数量 */ +export const graphNodeStateNum = computed(() => { + let normal = 0; + let abnormal = 0; + for (const item of graphState.data.nodes) { + const neId = item.neState.neId; + if (neId) { + if (item.neState.online) { + normal += 1; + } else { + abnormal += 1; + } + } + } + return [normal, abnormal]; +}); + +/**网元状态请求标记 */ +export const neStateRequestMap = ref>(new Map()); + +/**neStateParse 网元状态 数据解析 */ +export function neStateParse(neType: string, data: Record,neId: string) { + // console.log('neStateParse',neType, data, neId); + + const { combos, edges, nodes } = graphState.data; + + const node = nodes.find((item: Record) => item.id === neType); + //console.log('neStateParse',node); + + if (!node) return; + + // 初始化状态映射 + if (!node.neStateMap) node.neStateMap = {}; + + // 更新网元状态 + const newNeState :any = { + ...data, // 先展开data对象 + refreshTime: parseDateToStr(data.refreshTime, 'HH:mm:ss'), + online: !!data.cpu, + neId: neId + }; + // 如果是001,更新节点状态。neInfo为主要的网元信息 + if (node.neInfo && node.neInfo.neId === neId) { + Object.assign(node.neState, newNeState); + } + + //console.log(node.neState) + // 无论是否为主要网元,都更新状态映射 + node.neStateMap[neId] = {...newNeState}; + // 通过 ID 查询节点实例 + const item = graphG6.value.findById(node.id); + if (item) { + // 检查当前节点下所有网元的状态 + const allStates = Object.values(node.neStateMap); + // 判断状态颜色 + let stateColor = '#52c41a'; // 默认绿色(所有网元都正常) + if (allStates.some((state: any) => !state.online)) { + // 如果有任何一个网元不正常 + stateColor = allStates.every((state: any) => !state.online) ? '#f5222d' : '#faad14'; // 红色(全部不正常)或黄色(部分不正常) + } + + // 图片类型不能填充 + if (node.type && node.type.startsWith('image')) { + // 更新节点 + if (node.label !== newNeState.neType) { + graphG6.value.updateItem(item, { + label: newNeState.neType, + }); + } + // 设置状态 + graphG6.value.setItemState(item, 'top-right-dot', stateColor); + } else { + // 更新节点 + graphG6.value.updateItem(item, { + label: newNeState.neType, + style: { + fill: stateColor, // 填充色 + stroke: stateColor, // 填充色 + }, + }); + // 设置状态 + graphG6.value.setItemState(item, 'stroke', newNeState.online); + } + + } + + // 设置边状态 + for (const edge of edges) { + const edgeSource: string = edge.source; + const edgeTarget: string = edge.target; + const neS = nodes.find((n: any) => n.id === edgeSource); + const neT = nodes.find((n: any) => n.id === edgeTarget); + // console.log(neS, edgeSource, neT, edgeTarget); + + if (neS && neT) { + // 通过 ID 查询节点实例 + // const item = graphG6.value.findById(edge.id); + // console.log( + // `${edgeSource} - ${edgeTarget}`, + // neS.neState.online && neT.neState.online + // ); + // const stateColor = neS.neState.online && neT.neState.online ? '#000000' : '#ff4d4f'; // 状态颜色 + // 更新边 + // graphG6.value.updateItem(item, { + // label: `${edgeSource} - ${edgeTarget}`, + // style: { + // stroke: stateColor, // 填充色 + // }, + // labelCfg: { + // style: { + // fill: '#ffffff', // 标签文本色 + // }, + // }, + // }); + // 设置状态 + graphG6.value.setItemState( + edge.id, + 'circle-move', + neS.neState.online && neT.neState.online + ); + } + if (neS && notNeNodes.includes(edgeTarget)) { + graphG6.value.setItemState(edge.id, 'line-dash', neS.neState.online); + } + if (neT && notNeNodes.includes(edgeSource)) { + graphG6.value.setItemState(edge.id, 'line-dash', neT.neState.online); + } + } + + // 请求标记复位 + neStateRequestMap.value.set(neType, false); +} + +/**属性复位 */ +export function topologyReset() { + graphState.data = { + combos: [], + edges: [], + nodes: [], + }; + graphG6.value = null; + graphNodeClickID.value = 'UPF_001'; + neStateRequestMap.value = new Map(); +} diff --git a/src/views/dashboard/overview2/hooks/useUPFTotalFlow.ts b/src/views/dashboard/overview2/hooks/useUPFTotalFlow.ts new file mode 100644 index 00000000..4366405d --- /dev/null +++ b/src/views/dashboard/overview2/hooks/useUPFTotalFlow.ts @@ -0,0 +1,110 @@ +import { parseDateToStr } from '@/utils/date-utils'; +import { parseSizeFromBits, parseSizeFromKbs } from '@/utils/parse-utils'; +import { ref } from 'vue'; + +type FDType = { + /**时间 */ + lineXTime: string[]; + /**上行 N3 */ + lineYUp: number[]; + /**下行 N6 */ + lineYDown: number[]; + /**容量 */ + cap: number; +}; + +/**UPF-流量数据 */ +export const upfFlowData = ref({ + lineXTime: [], + lineYUp: [], + lineYDown: [], + cap: 0, +}); + +/**UPF-流量数据 数据解析 */ +export function upfFlowParse(data: Record) { + 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); + upfFlowData.value.lineYDown.push(downN6[0]); + upfFlowData.value.cap += 1; + // 超过 25 弹出 + if (upfFlowData.value.cap > 25) { + upfFlowData.value.lineXTime.shift(); + upfFlowData.value.lineYUp.shift(); + upfFlowData.value.lineYDown.shift(); + upfFlowData.value.cap -= 1; + } +} + +type TFType = { + /**上行 N3 */ + up: number; + upFrom: string; + /**下行 N6 */ + down: number; + downFrom: string; + /**请求标记 */ + requestFlag: boolean; +}; + +/**UPF-总流量数 */ +export const upfTotalFlow = ref>({ + '0': { + up: 0, + upFrom: '0 B', + down: 0, + downFrom: '0 B', + requestFlag: false, + }, + '7': { + up: 0, + upFrom: '0 B', + down: 0, + downFrom: '0 B', + requestFlag: false, + }, + '30': { + up: 0, + upFrom: '0 B', + down: 0, + downFrom: '0 B', + requestFlag: false, + }, +}); + +/**UPF-总流量数 数据解析 */ +export function upfTFParse(day: string, data: Record) { + let { up, down } = data; + upfTotalFlow.value[day] = { + up: up, + upFrom: parseSizeFromBits(up), + down: down, + downFrom: parseSizeFromBits(down), + requestFlag: false, + }; +} + +/**UPF-总流量数 选中 */ +export const upfTFActive = ref('0'); + +/**属性复位 */ +export function upfTotalFlowReset() { + upfFlowData.value = { + lineXTime: [], + lineYUp: [], + lineYDown: [], + cap: 0, + }; + for (const key of Object.keys(upfTotalFlow.value)) { + upfTotalFlow.value[key] = { + up: 0, + upFrom: '0 B', + down: 0, + downFrom: '0 B', + requestFlag: false, + }; + } + upfTFActive.value = '0'; +} diff --git a/src/views/dashboard/overview2/hooks/useUserActivity.ts b/src/views/dashboard/overview2/hooks/useUserActivity.ts new file mode 100644 index 00000000..76ffd23e --- /dev/null +++ b/src/views/dashboard/overview2/hooks/useUserActivity.ts @@ -0,0 +1,144 @@ +import { ref } from 'vue'; + +/**ueEventAMFParse UE会话事件AMF 数据解析 */ +function ueEventAMFParse( + item: Record +): false | Record { + let evData: Record = item.eventJSON; + if (typeof evData === 'string') { + try { + evData = JSON.parse(evData); + } catch (error) { + console.error(error); + } + } + + return { + eType: 'amf_ue', + eId: `amf_ue_${item.id}_${Date.now()}`, + eTime: +item.timestamp, + id: item.id, + type: item.eventType, + data: evData, + }; +} + +/**ueEventMMEParse UE会话事件MME 数据解析 */ +function ueEventMMEParse( + item: Record +): false | Record { + let evData: Record = item.eventJSON; + if (typeof evData === 'string') { + try { + evData = JSON.parse(evData); + } catch (error) { + console.error(error); + } + } + + return { + eType: 'mme_ue', + eId: `mme_ue_${item.id}_${Date.now()}`, + eTime: +item.timestamp, + id: item.id, + type: item.eventType, + data: evData, + }; +} + +/**cdrEventIMSParse CDR会话事件IMS 数据解析 */ +function cdrEventIMSParse( + item: Record +): false | Record { + let evData: Record = item.cdrJSON || item.CDR; + if (typeof evData === 'string') { + try { + evData = JSON.parse(evData); + } catch (error) { + console.error(error); + return false; + } + } + + // 指定显示CDR类型MOC/MTSM + if (!['MOC', 'MTSM'].includes(evData.recordType)) { + return false; + } + + return { + eType: 'ims_cdr', + eId: `ims_cdr_${item.id}_${Date.now()}`, + eTime: +item.timestamp, + id: item.id, + data: evData, + }; +} + +/**eventListParse 事件列表解析 */ +export function eventListParse( + type: 'ims_cdr' | 'amf_ue' | 'mme_ue', + data: any +) { + eventTotal.value += data.total; + for (const item of data.rows) { + let v: false | Record = false; + if (type === 'ims_cdr') { + v = cdrEventIMSParse(item); + } + if (type === 'amf_ue') { + v = ueEventAMFParse(item); + } + if (type === 'mme_ue') { + v = ueEventMMEParse(item); + } + + if (v) { + eventData.value.push(v); + } + } + // 激活选中 + if (eventData.value.length > 0) { + eventId.value = eventData.value[0].eId; + } +} + +/**eventItemParseAndPush 事件项解析并添加 */ +export async function eventItemParseAndPush( + type: 'ims_cdr' | 'amf_ue' | 'mme_ue', + item: any +) { + let v: false | Record = false; + if (type === 'ims_cdr') { + v = cdrEventIMSParse(item); + } + if (type === 'amf_ue') { + v = ueEventAMFParse(item); + } + if (type === 'mme_ue') { + v = ueEventMMEParse(item); + } + + if (v) { + eventData.value.unshift(v); + eventTotal.value += 1; + eventId.value = v.eId; + await new Promise(resolve => setTimeout(resolve, 800)); + if (eventData.value.length > 20) { + eventData.value.pop(); + } + } +} + +/**CDR+UE事件数据 */ +export const eventData = ref[]>([]); +/**CDR+UE事件总量 */ +export const eventTotal = ref(0); +/**CDR/UE事件推送id */ +export const eventId = ref(''); + +/**属性复位 */ +export function userActivityReset() { + eventData.value = []; + eventTotal.value = 0; + eventId.value = ''; +} diff --git a/src/views/dashboard/overview2/hooks/useWS.ts b/src/views/dashboard/overview2/hooks/useWS.ts new file mode 100644 index 00000000..c926e44f --- /dev/null +++ b/src/views/dashboard/overview2/hooks/useWS.ts @@ -0,0 +1,222 @@ +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, +} from './useUserActivity'; +import { + upfTotalFlow, + upfTFParse, + upfFlowParse, + upfTotalFlowReset, +} from './useUPFTotalFlow'; +import { topologyReset, neStateParse, neStateRequestMap } from './useTopology'; +import PQueue from 'p-queue'; + +/**UPF-的Id */ +export const upfWhoId = ref(''); + +/**websocket连接 */ +export default function useWS() { + const ws = new WS(); + const queue = new PQueue({ concurrency: 1, autoStart: true }); + + /**发消息 */ + function wsSend(data: Record) { + ws.send(data); + } + + /**接收数据后回调 */ + function wsMessage(res: Record) { + //console.log(res); + const { code, requestId, data } = res; + if (code === RESULT_CODE_ERROR) { + console.warn(res.msg); + return; + } + // 网元状态 + if (requestId && requestId.startsWith('neState')) { + const neType = requestId.split('_')[1]; + const neId = requestId.split('_')[2]; + neStateParse(neType, data,neId); + return; + } + + // 普通信息 + switch (requestId) { + // AMF_UE会话事件 + 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-总流量数 + case `upf_${upfWhoId.value}_0`: + upfTFParse('0', data); + break; + case `upf_${upfWhoId.value}_7`: + upfTFParse('7', data); + break; + case `upf_${upfWhoId.value}_30`: + upfTFParse('30', data); + break; + } + // 订阅组信息 + if (!data?.groupId) { + return; + } + switch (data.groupId) { + // kpiEvent 指标UPF + case `10_UPF_${upfWhoId.value}`: + if (data.data) { + upfFlowParse(data.data); + } + break; + // AMF_UE会话事件 + case '1010_001': + if (data.data) { + queue.add(() => eventItemParseAndPush('amf_ue', data.data)); + } + break; + // MME_UE会话事件 + case '1011_001': + if (data.data) { + queue.add(() => eventItemParseAndPush('mme_ue', data.data)); + } + break; + // IMS_CDR会话事件 + case '1005_001': + if (data.data) { + queue.add(() => eventItemParseAndPush('ims_cdr', data.data)); + } + break; + } + } + + /**UPF-总流量数 发消息*/ + function upfTFSend(day: '0' | '7' | '30') { + // 请求标记检查避免重复发送 + if (upfTotalFlow.value[day].requestFlag) { + return; + } + upfTotalFlow.value[day].requestFlag = true; + + ws.send({ + requestId: `upf_${upfWhoId.value}_${day}`, + type: 'upf_tf', + data: { + neType: 'UPF', + neId: upfWhoId.value, + day: Number(day), + }, + }); + } + + /**userActivitySend 用户行为事件基础列表数据 发消息*/ + function userActivitySend() { + // AMF_UE会话事件 + ws.send({ + requestId: 'amf_1010_001', + type: 'amf_ue', + data: { + neType: 'AMF', + neId: '001', + sortField: 'timestamp', + sortOrder: 'desc', + pageNum: 1, + pageSize: 20, + }, + }); + // MME_UE会话事件 + ws.send({ + requestId: 'mme_1011_001', + type: 'mme_ue', + data: { + neType: 'MME', + neId: '001', + sortField: 'timestamp', + sortOrder: 'desc', + pageNum: 1, + pageSize: 20, + }, + }); + // IMS_CDR会话事件 + ws.send({ + requestId: 'ims_1005_001', + type: 'ims_cdr', + data: { + neType: 'IMS', + neId: '001', + recordType: 'MOC', + sortField: 'timestamp', + sortOrder: 'desc', + pageNum: 1, + pageSize: 20, + }, + }); + } + + /**重新发送至UPF 10_UPF_neId */ + function reSendUPF(neId: string) { + upfWhoId.value = neId; + //初始时时无需还原全部属性以及关闭 + if (ws.state() === WebSocket.OPEN) { + ws.close(); + // userActivityReset(); + upfTotalFlowReset(); + neStateRequestMap.value = new Map(); + //topologyReset(); + } + const options: OptionsType = { + url: '/ws', + params: { + /**订阅通道组 + * + * 指标UPF (GroupID:10_neType_neId) + * AMF_UE会话事件(GroupID:1010_neId) + * MME_UE会话事件(GroupID:1011_neId) + * IMS_CDR会话事件(GroupID:1005_neId) + */ + subGroupID: `10_UPF_${neId},1010_001,1011_001,1005_001`, + }, + onmessage: wsMessage, + onerror: (ev: any) => { + console.error(ev); + }, + }; + ws.connect(options); + } + + onBeforeUnmount(() => { + ws.close(); + userActivityReset(); + upfTotalFlowReset(); + topologyReset(); + upfWhoId.value = ''; + }); + + return { + wsSend, + userActivitySend, + upfTFSend, + reSendUPF, + }; +} diff --git a/src/views/dashboard/overview2/images/bj.png b/src/views/dashboard/overview2/images/bj.png new file mode 100644 index 00000000..a1de24e7 Binary files /dev/null and b/src/views/dashboard/overview2/images/bj.png differ diff --git a/src/views/dashboard/overview2/images/border.png b/src/views/dashboard/overview2/images/border.png new file mode 100644 index 00000000..b854cea4 Binary files /dev/null and b/src/views/dashboard/overview2/images/border.png differ diff --git a/src/views/dashboard/overview2/images/brand.png b/src/views/dashboard/overview2/images/brand.png new file mode 100644 index 00000000..2f6fb6a0 Binary files /dev/null and b/src/views/dashboard/overview2/images/brand.png differ diff --git a/src/views/dashboard/overview2/images/line.png b/src/views/dashboard/overview2/images/line.png new file mode 100644 index 00000000..34e99aca Binary files /dev/null and b/src/views/dashboard/overview2/images/line.png differ diff --git a/src/views/dashboard/overview2/images/newBrand.png b/src/views/dashboard/overview2/images/newBrand.png new file mode 100644 index 00000000..c7311574 Binary files /dev/null and b/src/views/dashboard/overview2/images/newBrand.png differ diff --git a/src/views/dashboard/overview2/images/rect.png b/src/views/dashboard/overview2/images/rect.png new file mode 100644 index 00000000..6c0ebf00 Binary files /dev/null and b/src/views/dashboard/overview2/images/rect.png differ diff --git a/src/views/dashboard/overview2/images/title.png b/src/views/dashboard/overview2/images/title.png new file mode 100644 index 00000000..797b3351 Binary files /dev/null and b/src/views/dashboard/overview2/images/title.png differ diff --git a/src/views/dashboard/overview2/index.vue b/src/views/dashboard/overview2/index.vue new file mode 100644 index 00000000..9c10bf27 --- /dev/null +++ b/src/views/dashboard/overview2/index.vue @@ -0,0 +1,875 @@ + + + + + diff --git a/src/views/dashboard/sgwcCDR/index.vue b/src/views/dashboard/sgwcCDR/index.vue index b436d566..a1f4cd3f 100644 --- a/src/views/dashboard/sgwcCDR/index.vue +++ b/src/views/dashboard/sgwcCDR/index.vue @@ -260,14 +260,11 @@ function fnTableSelectedRowKeys(keys: (string | number)[]) { type ModalStateType = { /**确定按钮 loading */ confirmLoading: boolean; - /**最大ID值 */ - maxId: number; }; /**对话框对象信息状态 */ let modalState: ModalStateType = reactive({ confirmLoading: false, - maxId: 0, }); /** @@ -369,11 +366,6 @@ function fnGetList(pageNum?: number) { return item; }); - - // 取最大值ID用作实时累加 - if (total > 0) { - modalState.maxId = Number(rows[0].id); - } } tableState.loading = false; }); @@ -460,15 +452,18 @@ function wsMessage(res: Record) { // cdrEvent CDR会话事件 if (data.groupId === `1008_${queryParams.neId}`) { const cdrEvent = data.data; + let cdrJSON = {}; + try { + cdrJSON = JSON.parse(cdrEvent.cdrJSON); + } catch (e) {} queue.add(async () => { - modalState.maxId += 1; tableState.data.unshift({ - id: modalState.maxId, + id: cdrEvent.id, neType: cdrEvent.neType, neName: cdrEvent.neName, rmUID: cdrEvent.rmUID, timestamp: cdrEvent.timestamp, - cdrJSON: cdrEvent.CDR, + cdrJSON: cdrJSON, }); tablePagination.total += 1; if (tableState.data.length > 100) { diff --git a/src/views/dashboard/smfCDR/index.vue b/src/views/dashboard/smfCDR/index.vue index dee1bde8..222e1b47 100644 --- a/src/views/dashboard/smfCDR/index.vue +++ b/src/views/dashboard/smfCDR/index.vue @@ -287,14 +287,11 @@ function fnTableSelectedRowKeys(keys: (string | number)[]) { type ModalStateType = { /**确定按钮 loading */ confirmLoading: boolean; - /**最大ID值 */ - maxId: number; }; /**对话框对象信息状态 */ let modalState: ModalStateType = reactive({ confirmLoading: false, - maxId: 0, }); /** @@ -396,11 +393,6 @@ function fnGetList(pageNum?: number) { return item; }); - - // 取最大值ID用作实时累加 - if (total > 0) { - modalState.maxId = Number(rows[0].id); - } } tableState.loading = false; }); @@ -487,15 +479,18 @@ function wsMessage(res: Record) { // cdrEvent CDR会话事件 if (data.groupId === `1006_${queryParams.neId}`) { const cdrEvent = data.data; + let cdrJSON = {}; + try { + cdrJSON = JSON.parse(cdrEvent.cdrJSON); + } catch (e) {} queue.add(async () => { - modalState.maxId += 1; tableState.data.unshift({ - id: modalState.maxId, + id: cdrEvent.id, neType: cdrEvent.neType, neName: cdrEvent.neName, rmUID: cdrEvent.rmUID, timestamp: cdrEvent.timestamp, - cdrJSON: cdrEvent.CDR, + cdrJSON: cdrJSON, }); tablePagination.total += 1; if (tableState.data.length > 100) { diff --git a/src/views/dashboard/smfCDRByIMSI/index.vue b/src/views/dashboard/smfCDRByIMSI/index.vue index 90e45b92..cbbd79c0 100644 --- a/src/views/dashboard/smfCDRByIMSI/index.vue +++ b/src/views/dashboard/smfCDRByIMSI/index.vue @@ -37,6 +37,7 @@ import { parseSizeFromByte } from '@/utils/parse-utils'; import { message } from 'ant-design-vue'; import useNeListStore from '@/store/modules/ne_list'; import dayjs, { Dayjs } from 'dayjs'; +import { parseDateToStr } from '@/utils/date-utils'; const { t, currentLocale } = useI18n(); const neListStore = useNeListStore(); const ws = new WS(); @@ -48,7 +49,7 @@ let cdrChart: echarts.ECharts | null = null; /**图表配置 */ const option = { title: { - text: 'Data Usage Report', + text: t('views.dashboard.chart.charttitle'), left: 'left', }, tooltip: { @@ -148,12 +149,12 @@ const option = { ], yAxis: [ { - name: 'Downlink (Byte)', + name: t('views.dashboard.chart.downlink'), type: 'value', }, { gridIndex: 1, - name: 'Uplink (Byte)', + name: t('views.dashboard.chart.uplink'), type: 'value', inverse: true, }, @@ -381,7 +382,7 @@ function fnRanderChartDataLoad() { break; } // 时间 - const dataTime = item.cdrJSON.invocationTimestamp; + const dataTime = parseDateToStr(item.cdrJSON.invocationTimestamp); const listOfMultipleUnitUsage = item.cdrJSON.listOfMultipleUnitUsage; if ( !Array.isArray(listOfMultipleUnitUsage) || @@ -504,6 +505,10 @@ function fnRealTime() { // cdrEvent CDR会话事件 if (data.groupId === `1006_${queryParams.neId}`) { const cdrEvent = data.data; + let cdrJSON: any = {}; + try { + cdrJSON = JSON.parse(cdrEvent.cdrJSON); + } catch (e) {} // 对应结束时间内 if (queryParams.endTime) { const endTime = Math.round(queryParams.endTime / 1000); @@ -511,7 +516,6 @@ function fnRealTime() { return; } } - const cdrJSON = cdrEvent.CDR; if (!cdrJSON.invocationTimestamp) { return; } @@ -683,11 +687,11 @@ onBeforeUnmount(() => {
- - + + {{ state.dataUsage[0] }} - + {{ state.dataUsage[1] }} diff --git a/src/views/dashboard/smscCDR/index.vue b/src/views/dashboard/smscCDR/index.vue index 2b17344d..9b3d034e 100644 --- a/src/views/dashboard/smscCDR/index.vue +++ b/src/views/dashboard/smscCDR/index.vue @@ -254,14 +254,11 @@ function fnTableSelectedRowKeys(keys: (string | number)[]) { type ModalStateType = { /**确定按钮 loading */ confirmLoading: boolean; - /**最大ID值 */ - maxId: number; }; /**对话框对象信息状态 */ let modalState: ModalStateType = reactive({ confirmLoading: false, - maxId: 0, }); /** @@ -363,11 +360,6 @@ function fnGetList(pageNum?: number) { return item; }); - - // 取最大值ID用作实时累加 - if (total > 0) { - modalState.maxId = Number(rows[0].id); - } } tableState.loading = false; }); @@ -454,15 +446,18 @@ function wsMessage(res: Record) { // cdrEvent CDR会话事件 if (data.groupId === `1007_${queryParams.neId}`) { const cdrEvent = data.data; + let cdrJSON = {}; + try { + cdrJSON = JSON.parse(cdrEvent.cdrJSON); + } catch (e) {} queue.add(async () => { - modalState.maxId += 1; tableState.data.unshift({ - id: modalState.maxId, + id: cdrEvent.id, neType: cdrEvent.neType, neName: cdrEvent.neName, rmUID: cdrEvent.rmUID, timestamp: cdrEvent.timestamp, - cdrJSON: cdrEvent.CDR, + cdrJSON: cdrJSON, }); tablePagination.total += 1; if (tableState.data.length > 100) { diff --git a/src/views/faultManage/active-alarm/index.vue b/src/views/faultManage/active-alarm/index.vue index bce1180d..7d9efbd9 100644 --- a/src/views/faultManage/active-alarm/index.vue +++ b/src/views/faultManage/active-alarm/index.vue @@ -70,7 +70,7 @@ let rangePickerPresets = ref([ /**查询参数 */ let queryParams = reactive({ - alarmStatus: 1, + alarmStatus: 'Active', sortField: 'event_time', sortOrder: 'desc', /**告警设备类型 */ @@ -102,7 +102,7 @@ let queryParams = reactive({ /**查询参数重置 */ function fnQueryReset() { queryParams = Object.assign(queryParams, { - alarmStatus: 1, + alarmStatus: 'Active', /**告警设备类型 */ neType: '', /**告警网元名称 */ @@ -386,7 +386,7 @@ let modalState: ModalStateType = reactive({ objectName: '', locationInfo: '', province: '', - alarmStatus: '', + alarmStatus: 'Active', specificProblemId: '', specificProblem: '', addInfo: '', diff --git a/src/views/faultManage/alarm-overview/images/bg.png b/src/views/faultManage/alarm-overview/images/bg.png new file mode 100644 index 00000000..2c52f488 Binary files /dev/null and b/src/views/faultManage/alarm-overview/images/bg.png differ diff --git a/src/views/faultManage/alarm-overview/index.vue b/src/views/faultManage/alarm-overview/index.vue new file mode 100644 index 00000000..0489e6c0 --- /dev/null +++ b/src/views/faultManage/alarm-overview/index.vue @@ -0,0 +1,1338 @@ + + + + + diff --git a/src/views/faultManage/event/index.vue b/src/views/faultManage/event/index.vue index df4aca93..13caf5ba 100644 --- a/src/views/faultManage/event/index.vue +++ b/src/views/faultManage/event/index.vue @@ -680,7 +680,7 @@ onMounted(() => { :label="t('views.faultManage.activeAlarm.eventTime')" name="eventTime" > - {{ modalState.from.eventTime }} + {{ parseDateToStr(modalState.from.eventTime) }} diff --git a/src/views/faultManage/history-alarm/index.vue b/src/views/faultManage/history-alarm/index.vue index 3c085bb5..7833ac68 100644 --- a/src/views/faultManage/history-alarm/index.vue +++ b/src/views/faultManage/history-alarm/index.vue @@ -61,7 +61,7 @@ let rangePickerPresets = ref([ /**查询参数 */ let queryParams = reactive({ - alarmStatus: 0, + alarmStatus: 'Clear', sortField: 'event_time', sortOrder: 'desc', /**告警设备类型 */ @@ -91,7 +91,7 @@ let queryParams = reactive({ /**查询参数重置 */ function fnQueryReset() { queryParams = Object.assign(queryParams, { - alarmStatus: 0, + alarmStatus: 'Clear', /**告警设备类型 */ neType: '', /**告警网元名称 */ @@ -317,7 +317,7 @@ let modalState: ModalStateType = reactive({ objectName: '', locationInfo: '', province: '', - alarmStatus: '', + alarmStatus: 'Clear', specificProblemId: '', specificProblem: '', addInfo: '', diff --git a/src/views/logManage/mml/index.vue b/src/views/logManage/mml/index.vue index ae69cf66..0a0097e3 100644 --- a/src/views/logManage/mml/index.vue +++ b/src/views/logManage/mml/index.vue @@ -6,7 +6,7 @@ import { MenuInfo } from 'ant-design-vue/es/menu/src/interface'; import { ColumnsType } from 'ant-design-vue/es/table'; import { parseDateToStr } from '@/utils/date-utils'; import { RESULT_CODE_SUCCESS } from '@/constants/result-constants'; -import { listMML } from '@/api/logManage/mml'; +import { mmlLogList } from '@/api/tool/mml'; import useI18n from '@/hooks/useI18n'; const { t } = useI18n(); @@ -16,7 +16,7 @@ let queryRangePicker = ref<[string, string]>(['', '']); /**查询参数 */ let queryParams = reactive({ /**登录账号 */ - accountName: '', + user: '', /**记录时间 */ beginTime: '', endTime: '', @@ -105,8 +105,8 @@ let tableColumns: ColumnsType = reactive([ }, { title: t('views.logManage.mml.MML'), - dataIndex: 'mml', - key: 'mml', + dataIndex: 'command', + key: 'command', align: 'left', ellipsis: true, }, @@ -157,8 +157,8 @@ function fnGetList(pageNum?: number) { } queryParams.beginTime = queryRangePicker.value[0]; queryParams.endTime = queryRangePicker.value[1]; - listMML(toRaw(queryParams)).then(res => { - if (res.code === RESULT_CODE_SUCCESS) { + mmlLogList(toRaw(queryParams)).then(res => { + if (res.code === RESULT_CODE_SUCCESS) { const { total, rows } = res.data; tablePagination.total = total; tableState.data = rows; @@ -192,13 +192,11 @@ onMounted(() => { - + @@ -294,7 +292,7 @@ onMounted(() => { :loading="tableState.loading" :data-source="tableState.data" :size="tableState.size" - :pagination="tablePagination" + :pagination="tablePagination" > + + + + diff --git a/src/views/system/log/operate/index.vue b/src/views/system/log/operate/index.vue index 42152083..e8abc665 100644 --- a/src/views/system/log/operate/index.vue +++ b/src/views/system/log/operate/index.vue @@ -245,6 +245,21 @@ let modalState: ModalStateType = reactive({ */ function fnModalVisibleByVive(row: Record) { modalState.from = Object.assign(modalState.from, row); + try { + modalState.from.operaParam = JSON.stringify( + JSON.parse(modalState.from.operaParam), + null, + 4 + ); + } catch (_) {} + try { + modalState.from.operaMsg = JSON.stringify( + JSON.parse(modalState.from.operaMsg), + null, + 4 + ); + } catch (_) {} + modalState.title = t('views.system.log.operate.logInfo'); modalState.openByView = true; } diff --git a/src/views/system/login-source/index.vue b/src/views/system/login-source/index.vue new file mode 100644 index 00000000..b7400175 --- /dev/null +++ b/src/views/system/login-source/index.vue @@ -0,0 +1,1122 @@ + + + + + diff --git a/src/views/system/user/index.vue b/src/views/system/user/index.vue index 5e8e33b5..f0cc6558 100644 --- a/src/views/system/user/index.vue +++ b/src/views/system/user/index.vue @@ -44,10 +44,13 @@ const { t } = useI18n(); let dict: { /**状态 */ sysNormalDisable: DictType[]; + /**用户类型 */ + sysUserType: DictType[]; /**性别 */ sysUserSex: DictType[]; } = reactive({ sysNormalDisable: [], + sysUserType: [], sysUserSex: [], }); @@ -64,6 +67,8 @@ let queryParams = reactive({ deptId: undefined, /**用户状态 */ statusFlag: undefined, + /**用户类型 */ + userType: undefined, /**记录开始时间 */ beginTime: undefined as number | undefined, /**记录结束时间 */ @@ -81,6 +86,7 @@ function fnQueryReset() { phone: '', deptId: undefined, statusFlag: undefined, + userType: undefined, beginTime: undefined, endTime: undefined, pageNum: 1, @@ -148,6 +154,13 @@ let tableColumns: ColumnsType = [ align: 'left', width: 200, }, + { + title: t('views.system.user.userType'), + dataIndex: 'userType', + key: 'userType', + align: 'left', + width: 200, + }, { title: t('views.system.user.loginIp'), dataIndex: 'loginIp', @@ -792,13 +805,17 @@ onMounted(() => { // 初始字典数据 Promise.allSettled([ getDict('sys_normal_disable'), + getDict('sys_user_type'), getDict('sys_user_sex'), ]).then(resArr => { if (resArr[0].status === 'fulfilled') { dict.sysNormalDisable = resArr[0].value; } if (resArr[1].status === 'fulfilled') { - dict.sysUserSex = resArr[1].value; + dict.sysUserType = resArr[1].value; + } + if (resArr[2].status === 'fulfilled') { + dict.sysUserSex = resArr[2].value; } }); // 获取列表数据 @@ -841,7 +858,7 @@ onMounted(() => { > - + { + + + + + + { {{ r.roleName }} + @@ -1072,7 +1109,9 @@ onMounted(() => {
{ diff --git a/src/views/traceManage/task/components/TaskInfoIcon.vue b/src/views/traceManage/task/components/TaskInfoIcon.vue index 093be150..cbebadc5 100644 --- a/src/views/traceManage/task/components/TaskInfoIcon.vue +++ b/src/views/traceManage/task/components/TaskInfoIcon.vue @@ -9,7 +9,7 @@ const { t } = useI18n(); const { getDict } = useDictStore(); const props = defineProps({ - traceId: { + id: { type: [String, Number], required: true, }, @@ -50,7 +50,7 @@ onMounted(() => { }) .finally(() => { // 获取信息 - fnGetTaskInfo(props.traceId); + fnGetTaskInfo(props.id); }); }); diff --git a/src/views/traceManage/task/data.vue b/src/views/traceManage/task/data.vue index ff7d0ddf..00fc8512 100644 --- a/src/views/traceManage/task/data.vue +++ b/src/views/traceManage/task/data.vue @@ -23,6 +23,8 @@ const route = useRoute(); /**跟踪编号 */ const traceId = ref(route.query.traceId as string); +/**任务编号 */ +const id = ref(route.query.id as string); /**关闭跳转 */ function fnClose() { @@ -431,7 +433,7 @@ onMounted(() => { {{ traceId }} - +
diff --git a/src/views/traceManage/task/index.vue b/src/views/traceManage/task/index.vue index dbf2eb19..4f9999ca 100644 --- a/src/views/traceManage/task/index.vue +++ b/src/views/traceManage/task/index.vue @@ -592,10 +592,10 @@ function fnModalCancel() { } /**跳转内嵌详情页面 */ -function fnRecordView(traceId: any, type: 'analyze' | 'data') { +function fnRecordView(record: any, type: 'analyze' | 'data') { router.push({ path: `${route.path}${MENU_PATH_INLINE}/${type}`, - query: { traceId }, + query: { traceId: record.traceId, id: record.id }, }); } @@ -795,7 +795,7 @@ onMounted(() => { @@ -808,7 +808,7 @@ onMounted(() => {