Merge remote-tracking branch 'origin/main' into multi-tenant
This commit is contained in:
@@ -11,7 +11,7 @@ VITE_APP_NAME = "Core Network OMC"
|
||||
VITE_APP_CODE = "OMC"
|
||||
|
||||
# 应用版本
|
||||
VITE_APP_VERSION = "2.250124"
|
||||
VITE_APP_VERSION = "2.250214"
|
||||
|
||||
# 接口基础URL地址-不带/后缀
|
||||
VITE_API_BASE_URL = "/omc-api"
|
||||
|
||||
@@ -11,7 +11,7 @@ VITE_APP_NAME = "Core Network OMC"
|
||||
VITE_APP_CODE = "OMC"
|
||||
|
||||
# 应用版本
|
||||
VITE_APP_VERSION = "2.250124"
|
||||
VITE_APP_VERSION = "2.250214"
|
||||
|
||||
# 接口基础URL地址-不带/后缀
|
||||
VITE_API_BASE_URL = "/omc-api"
|
||||
|
||||
10
package.json
10
package.json
@@ -19,12 +19,12 @@
|
||||
"@codemirror/merge": "^6.8.0",
|
||||
"@codemirror/theme-one-dark": "^6.1.2",
|
||||
"@tato30/vue-pdf": "^1.11.3",
|
||||
"@vueuse/core": "^12.3.0",
|
||||
"@vueuse/core": "^12.5.0",
|
||||
"@xterm/addon-fit": "^0.10.0",
|
||||
"@xterm/xterm": "^5.5.0",
|
||||
"ant-design-vue": "^4.2.6",
|
||||
"antdv-pro-layout": "^4.2.0",
|
||||
"antdv-pro-modal": "^4.0.5",
|
||||
"antdv-pro-modal": "^4.0.6",
|
||||
"codemirror": "^6.0.1",
|
||||
"crypto-js": "^4.2.0",
|
||||
"dayjs": "^1.11.11",
|
||||
@@ -39,7 +39,7 @@
|
||||
"p-queue": "~8.0.1",
|
||||
"pinia": "^2.3.0",
|
||||
"vue": "^3.5.13",
|
||||
"vue-i18n": "^11.0.1",
|
||||
"vue-i18n": "^11.1.0",
|
||||
"vue-router": "^4.5.0",
|
||||
"vue3-smooth-dnd": "^0.0.6",
|
||||
"xlsx": "~0.18.5"
|
||||
@@ -54,8 +54,8 @@
|
||||
"less": "^4.2.1",
|
||||
"typescript": "~5.6.3",
|
||||
"unplugin-vue-components": "^0.28.0",
|
||||
"vite": "^6.0.6",
|
||||
"vite": "^6.1.0",
|
||||
"vite-plugin-compression": "~0.5.1",
|
||||
"vue-tsc": "~2.1.10"
|
||||
"vue-tsc": "^2.2.0"
|
||||
}
|
||||
}
|
||||
|
||||
BIN
public/nbStateImput/en.xlsx
Normal file
BIN
public/nbStateImput/en.xlsx
Normal file
Binary file not shown.
BIN
public/nbStateImput/zh.xlsx
Normal file
BIN
public/nbStateImput/zh.xlsx
Normal file
Binary file not shown.
@@ -1,3 +1,5 @@
|
||||
import { CACHE_SESSION_CRYPTO_API } from '@/constants/cache-keys-constants';
|
||||
import { sessionGet } from '@/utils/cache-session-utils';
|
||||
import { request } from '@/plugins/http-fetch';
|
||||
|
||||
/**
|
||||
@@ -62,6 +64,7 @@ export function updateFTPInfo(data: Record<string, any>) {
|
||||
url: `/lm/table/ftp`,
|
||||
method: 'post',
|
||||
data: data,
|
||||
crypto: sessionGet(CACHE_SESSION_CRYPTO_API) !== 'false',
|
||||
});
|
||||
}
|
||||
|
||||
@@ -74,6 +77,7 @@ export function getFTPInfo() {
|
||||
return request({
|
||||
url: `/lm/table/ftp`,
|
||||
method: 'get',
|
||||
crypto: sessionGet(CACHE_SESSION_CRYPTO_API) !== 'false',
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
30
src/api/neData/nb-state.ts
Normal file
30
src/api/neData/nb-state.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
import { request } from '@/plugins/http-fetch';
|
||||
|
||||
/**
|
||||
* 历史记录列表
|
||||
* @param query 查询参数
|
||||
* @returns object
|
||||
*/
|
||||
export function listNBState(query: Record<string, any>) {
|
||||
return request({
|
||||
url: '/neData/nb-state/list',
|
||||
method: 'get',
|
||||
params: query,
|
||||
timeout: 60_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 历史记录列表导出
|
||||
* @param data 查询列表条件
|
||||
* @returns object
|
||||
*/
|
||||
export function exportNBState(data: Record<string, any>) {
|
||||
return request({
|
||||
url: '/neData/nb-state/export',
|
||||
method: 'post',
|
||||
data,
|
||||
responseType: 'blob',
|
||||
timeout: 60_000,
|
||||
});
|
||||
}
|
||||
@@ -726,6 +726,9 @@ export default {
|
||||
time: "Change Time",
|
||||
addRadio: "Add Radio Info",
|
||||
editRadio: "Edit Radio Info",
|
||||
history: "Status History",
|
||||
exportTip: "Confirm exporting xlsx table files based on search criteria?",
|
||||
importDataEmpty: "Imported data is empty",
|
||||
},
|
||||
},
|
||||
neUser: {
|
||||
@@ -738,6 +741,7 @@ export default {
|
||||
checkExport : 'Check Export',
|
||||
checkExportConfirm: 'Confirm exporting the checked authenticated user data?',
|
||||
import: 'Import',
|
||||
importFail: 'Failure Record',
|
||||
loadDataConfirm: 'Are you sure you want to reload the 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!!!!!.',
|
||||
@@ -766,6 +770,7 @@ export default {
|
||||
checkExport : 'Check Export',
|
||||
checkExportConfirm: 'Are you sure to export the data of the checked subscribers?',
|
||||
import: 'Import',
|
||||
importFail: 'Failure Record',
|
||||
loadDataConfirm: 'Are you sure you want to reload the 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!!!!!.',
|
||||
@@ -968,6 +973,7 @@ export default {
|
||||
expressionModal:'Expression Modal',
|
||||
expressionErrorTip:'Please check the expression, the wrong indicator is {kpiId}',
|
||||
expressionNoIdTip:'Please check the expression, no valid indicator is found',
|
||||
unitSelect:'To better display the image, the same unit needs to be selected. The current unit is:',
|
||||
},
|
||||
kpiKeyTarget:{
|
||||
"time":"Time",
|
||||
|
||||
@@ -726,6 +726,9 @@ export default {
|
||||
time: "变更时间",
|
||||
addRadio: "添加基站信息",
|
||||
editRadio: "更新基站信息",
|
||||
history: "历史记录",
|
||||
exportTip: "确认根据搜索条件导出xlsx表格文件吗?",
|
||||
importDataEmpty: "导入数据为空",
|
||||
},
|
||||
},
|
||||
neUser: {
|
||||
@@ -738,6 +741,7 @@ export default {
|
||||
checkExport : '勾选导出',
|
||||
checkExportConfirm: '确认导出已勾选的鉴权用户数据吗?',
|
||||
import: '导入',
|
||||
importFail: '失败记录',
|
||||
loadDataConfirm: '确认要重新加载数据吗?',
|
||||
loadData: '加载数据',
|
||||
loadDataTip: '成功获取加载数据:{num}条,系统内部正在进行数据更新,大约需要{timer}秒,请稍候!!!',
|
||||
@@ -766,6 +770,7 @@ export default {
|
||||
checkExport : '勾选导出',
|
||||
checkExportConfirm: '确认导出已勾选的签约用户数据吗?',
|
||||
import: '导入',
|
||||
importFail: '失败记录',
|
||||
loadDataConfirm: '确认要重新加载数据吗?',
|
||||
loadData: '加载数据',
|
||||
loadDataTip: '成功获取加载数据:{num}条,系统内部正在进行数据更新,大约需要{timer}秒,请稍候!!!',
|
||||
@@ -968,6 +973,7 @@ export default {
|
||||
expressionModal:'表达式模块',
|
||||
expressionErrorTip:'请检查表达式,错误的指标为{kpiId}',
|
||||
expressionNoIdTip:'请检查表达式,没有找到任何有效的指标',
|
||||
unitSelect:'为更好展示图需选择相同单位,当前单位为:',
|
||||
},
|
||||
kpiKeyTarget:{
|
||||
"time":"时间",
|
||||
|
||||
@@ -42,7 +42,7 @@ export async function readLoalXlsx(
|
||||
/**
|
||||
* 读取表格数据 工作表
|
||||
* @param fileBolb 文件对象
|
||||
* @param index 文件保存路径
|
||||
* @param index SheetName索引
|
||||
* @return 表格对象列表
|
||||
*/
|
||||
export async function readSheet(
|
||||
|
||||
@@ -290,13 +290,13 @@ type ModalStateType = {
|
||||
/**FTP日志对象信息状态 */
|
||||
let modalState: ModalStateType = reactive({
|
||||
openByEdit: false,
|
||||
title: 'FTP上报服务设置',
|
||||
title: '设置远程备份配置',
|
||||
from: {
|
||||
useranme: '',
|
||||
username: '',
|
||||
password: '',
|
||||
toIp: '',
|
||||
toPort: 22,
|
||||
protocol: 'ftp',
|
||||
enable: false,
|
||||
dir: '',
|
||||
},
|
||||
confirmLoading: false,
|
||||
@@ -343,12 +343,12 @@ function fnModalVisibleByEdit() {
|
||||
hide();
|
||||
if (res.code === RESULT_CODE_SUCCESS && res.data) {
|
||||
modalState.from = Object.assign(modalState.from, res.data);
|
||||
modalState.title = 'FTP Info';
|
||||
modalState.title = 'Setting Remote Backup';
|
||||
modalState.openByEdit = true;
|
||||
} else {
|
||||
message.error(res.msg, 3);
|
||||
modalState.title = 'FTP Info';
|
||||
modalState.openByEdit = true;
|
||||
modalState.title = 'Setting Remote Backup';
|
||||
modalState.openByEdit = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -361,9 +361,10 @@ function fnModalOk() {
|
||||
updateFTPInfo(from)
|
||||
.then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS) {
|
||||
message.success(`FTP configuration saved successfully`, 3);
|
||||
message.success(`Configuration saved successfully`, 3);
|
||||
fnModalCancel();
|
||||
} else {
|
||||
message.warning(`FTP configuration save exception`, 3);
|
||||
message.warning(`Configuration save exception`, 3);
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
@@ -389,7 +390,7 @@ function fnSyncFileToFTP(row: Record<string, any>) {
|
||||
putFTPInfo(row.filePath, row.fileName)
|
||||
.then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS) {
|
||||
message.success(`OK`, 3);
|
||||
message.success(t('common.operateOk'), 3);
|
||||
} else {
|
||||
message.warning(res.msg, 3);
|
||||
}
|
||||
@@ -435,7 +436,7 @@ function fnSyncFileToFTP(row: Record<string, any>) {
|
||||
<template #extra>
|
||||
<a-space :size="8" align="center">
|
||||
<a-tooltip>
|
||||
<template #title>Setting</template>
|
||||
<template #title>Setting Remote Backup</template>
|
||||
<a-button type="text" @click.prevent="fnModalVisibleByEdit()">
|
||||
<template #icon><DeliveredProcedureOutlined /></template>
|
||||
</a-button>
|
||||
@@ -512,91 +513,84 @@ function fnSyncFileToFTP(row: Record<string, any>) {
|
||||
:label-col="{ span: 6 }"
|
||||
:label-wrap="true"
|
||||
>
|
||||
<a-row>
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
<a-form-item
|
||||
label="Service IP"
|
||||
name="toIp"
|
||||
v-bind="modalStateFrom.validateInfos.toIp"
|
||||
>
|
||||
<a-input
|
||||
v-model:value="modalState.from.toIp"
|
||||
allow-clear
|
||||
:placeholder="t('common.inputPlease')"
|
||||
></a-input>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
<a-form-item
|
||||
label="Service Port"
|
||||
name="toPort"
|
||||
v-bind="modalStateFrom.validateInfos.toPort"
|
||||
>
|
||||
<a-input-number
|
||||
v-model:value="modalState.from.toPort"
|
||||
allow-clear
|
||||
:placeholder="t('common.inputPlease')"
|
||||
></a-input-number>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
<a-row>
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
<a-form-item
|
||||
label="UserName"
|
||||
name="username"
|
||||
v-bind="modalStateFrom.validateInfos.username"
|
||||
>
|
||||
<a-input
|
||||
v-model:value="modalState.from.username"
|
||||
allow-clear
|
||||
:placeholder="t('common.inputPlease')"
|
||||
></a-input>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
<a-form-item
|
||||
label="Password"
|
||||
name="password"
|
||||
v-bind="modalStateFrom.validateInfos.password"
|
||||
>
|
||||
<a-input-password
|
||||
v-model:value="modalState.from.password"
|
||||
allow-clear
|
||||
:placeholder="t('common.inputPlease')"
|
||||
></a-input-password>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
<a-row>
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
<a-form-item label="Protocol" name="protocol">
|
||||
<a-select
|
||||
v-model:value="modalState.from.protocol"
|
||||
default-value="N"
|
||||
:placeholder="t('common.selectPlease')"
|
||||
:options="[
|
||||
{ value: 'ftp', label: 'FTP' },
|
||||
{ value: 'ssh', label: 'SSH' },
|
||||
]"
|
||||
<a-form-item label="Enable" name="enable" :label-col="{ span: 3 }">
|
||||
<a-switch
|
||||
v-model:checked="modalState.from.enable"
|
||||
:checked-children="t('common.switch.open')"
|
||||
:un-checked-children="t('common.switch.shut')"
|
||||
/>
|
||||
</a-form-item>
|
||||
|
||||
<template v-if="modalState.from.enable">
|
||||
<a-row>
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
<a-form-item
|
||||
label="Service IP"
|
||||
name="toIp"
|
||||
v-bind="modalStateFrom.validateInfos.toIp"
|
||||
>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
<a-form-item
|
||||
label="Save Dir"
|
||||
name="dir"
|
||||
v-bind="modalStateFrom.validateInfos.dir"
|
||||
>
|
||||
<a-input
|
||||
v-model:value="modalState.from.dir"
|
||||
allow-clear
|
||||
:placeholder="t('common.inputPlease')"
|
||||
></a-input>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
<a-input
|
||||
v-model:value="modalState.from.toIp"
|
||||
allow-clear
|
||||
:placeholder="t('common.inputPlease')"
|
||||
></a-input>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
<a-form-item
|
||||
label="Service Port"
|
||||
name="toPort"
|
||||
v-bind="modalStateFrom.validateInfos.toPort"
|
||||
>
|
||||
<a-input-number
|
||||
v-model:value="modalState.from.toPort"
|
||||
allow-clear
|
||||
:placeholder="t('common.inputPlease')"
|
||||
></a-input-number>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
<a-row>
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
<a-form-item
|
||||
label="UserName"
|
||||
name="username"
|
||||
v-bind="modalStateFrom.validateInfos.username"
|
||||
>
|
||||
<a-input
|
||||
v-model:value="modalState.from.username"
|
||||
allow-clear
|
||||
:placeholder="t('common.inputPlease')"
|
||||
></a-input>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
<a-form-item
|
||||
label="Password"
|
||||
name="password"
|
||||
v-bind="modalStateFrom.validateInfos.password"
|
||||
>
|
||||
<a-input-password
|
||||
v-model:value="modalState.from.password"
|
||||
allow-clear
|
||||
:placeholder="t('common.inputPlease')"
|
||||
></a-input-password>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
<a-form-item
|
||||
label="Save Dir"
|
||||
name="dir"
|
||||
v-bind="modalStateFrom.validateInfos.dir"
|
||||
:label-col="{ span: 3 }"
|
||||
>
|
||||
<a-input
|
||||
v-model:value="modalState.from.dir"
|
||||
allow-clear
|
||||
:placeholder="t('common.inputPlease')"
|
||||
></a-input>
|
||||
</a-form-item>
|
||||
</template>
|
||||
</a-form>
|
||||
</ProModal>
|
||||
</PageContainer>
|
||||
|
||||
383
src/views/ne-data/base-station/components/history.vue
Normal file
383
src/views/ne-data/base-station/components/history.vue
Normal file
@@ -0,0 +1,383 @@
|
||||
<script setup lang="ts">
|
||||
import { reactive, ref, toRaw, watch } from 'vue';
|
||||
import { ProModal } from 'antdv-pro-modal';
|
||||
import { message, Modal } from 'ant-design-vue/es';
|
||||
import { SizeType } from 'ant-design-vue/es/config-provider';
|
||||
import { ColumnsType } from 'ant-design-vue/es/table';
|
||||
import { saveAs } from 'file-saver';
|
||||
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
||||
import useI18n from '@/hooks/useI18n';
|
||||
import { exportNBState, listNBState } from '@/api/neData/nb-state';
|
||||
import { Dayjs } from 'dayjs';
|
||||
const { t } = useI18n();
|
||||
const emit = defineEmits(['cancel', 'update:open']);
|
||||
const props = defineProps({
|
||||
title: {
|
||||
type: String,
|
||||
default: '标题',
|
||||
},
|
||||
open: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
/**网元ID */
|
||||
neId: {
|
||||
type: String,
|
||||
default: false,
|
||||
},
|
||||
neType: {
|
||||
type: String,
|
||||
default: false,
|
||||
},
|
||||
});
|
||||
|
||||
/**开始结束时间 */
|
||||
let queryRangePicker = ref<[Dayjs, Dayjs] | undefined>(undefined);
|
||||
/**状态字典 */
|
||||
const nbStateOptions = ref<DictType[]>([
|
||||
{
|
||||
value: 'ON',
|
||||
label: t('views.neData.baseStation.online'),
|
||||
tagType: 'green',
|
||||
tagClass: '',
|
||||
},
|
||||
{
|
||||
value: 'OFF',
|
||||
label: t('views.neData.baseStation.offline'),
|
||||
tagType: 'red',
|
||||
tagClass: '',
|
||||
},
|
||||
]);
|
||||
|
||||
/**查询参数 */
|
||||
let queryParams = reactive({
|
||||
/**网元 */
|
||||
neType: '',
|
||||
neId: '',
|
||||
/**排序字段 */
|
||||
sortField: 'id',
|
||||
sortOrder: 'desc',
|
||||
/**状态 */
|
||||
status: undefined as undefined | string,
|
||||
/**开始时间 */
|
||||
startTime: undefined as undefined | number,
|
||||
/**结束时间 */
|
||||
endTime: undefined as undefined | number,
|
||||
/**当前页数 */
|
||||
pageNum: 1,
|
||||
/**每页条数 */
|
||||
pageSize: 20,
|
||||
});
|
||||
|
||||
/**查询参数重置 */
|
||||
function fnQueryReset() {
|
||||
queryParams = Object.assign(queryParams, {
|
||||
status: undefined,
|
||||
startTime: undefined,
|
||||
endTime: undefined,
|
||||
pageNum: 1,
|
||||
pageSize: 20,
|
||||
});
|
||||
queryRangePicker.value = undefined;
|
||||
tablePagination.current = 1;
|
||||
tablePagination.pageSize = 20;
|
||||
fnGetList();
|
||||
}
|
||||
|
||||
/**表格状态类型 */
|
||||
type TabeStateType = {
|
||||
/**加载等待 */
|
||||
loading: boolean;
|
||||
/**紧凑型 */
|
||||
size: SizeType;
|
||||
/**搜索栏 */
|
||||
seached: boolean;
|
||||
/**记录数据 */
|
||||
data: object[];
|
||||
/**勾选记录 */
|
||||
selectedRowKeys: (string | number)[];
|
||||
};
|
||||
|
||||
/**表格状态 */
|
||||
let tableState: TabeStateType = reactive({
|
||||
loading: false,
|
||||
size: 'middle',
|
||||
seached: true,
|
||||
data: [],
|
||||
selectedRowKeys: [],
|
||||
});
|
||||
|
||||
/**表格字段列 */
|
||||
let tableColumns = ref<ColumnsType>([
|
||||
{
|
||||
title: t('common.rowId'),
|
||||
dataIndex: 'id',
|
||||
align: 'left',
|
||||
width: 80,
|
||||
},
|
||||
{
|
||||
title: t('views.neData.baseStation.name'),
|
||||
dataIndex: 'name',
|
||||
align: 'left',
|
||||
resizable: true,
|
||||
width: 120,
|
||||
minWidth: 100,
|
||||
maxWidth: 250,
|
||||
ellipsis: true,
|
||||
},
|
||||
{
|
||||
title: t('views.neData.baseStation.position'),
|
||||
dataIndex: 'position',
|
||||
align: 'left',
|
||||
resizable: true,
|
||||
width: 150,
|
||||
minWidth: 100,
|
||||
maxWidth: 400,
|
||||
ellipsis: true,
|
||||
},
|
||||
{
|
||||
title: t('views.neData.baseStation.address'),
|
||||
dataIndex: 'address',
|
||||
align: 'left',
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
title: t('views.neData.baseStation.nbName'),
|
||||
dataIndex: 'nbName',
|
||||
align: 'left',
|
||||
resizable: true,
|
||||
width: 100,
|
||||
minWidth: 100,
|
||||
maxWidth: 200,
|
||||
},
|
||||
{
|
||||
title: t('views.neData.baseStation.state'),
|
||||
dataIndex: 'state',
|
||||
key: 'state',
|
||||
align: 'left',
|
||||
width: 80,
|
||||
},
|
||||
{
|
||||
title: t('views.neData.baseStation.time'),
|
||||
dataIndex: 'time',
|
||||
align: 'left',
|
||||
width: 150,
|
||||
},
|
||||
]);
|
||||
|
||||
/**表格分页器参数 */
|
||||
let tablePagination = reactive({
|
||||
/**当前页数 */
|
||||
current: 1,
|
||||
/**每页条数 */
|
||||
pageSize: 20,
|
||||
/**默认的每页条数 */
|
||||
defaultPageSize: 20,
|
||||
/**指定每页可以显示多少条 */
|
||||
pageSizeOptions: ['10', '20', '50', '100'],
|
||||
/**只有一页时是否隐藏分页器 */
|
||||
hideOnSinglePage: false,
|
||||
/**是否可以快速跳转至某页 */
|
||||
showQuickJumper: true,
|
||||
/**是否可以改变 pageSize */
|
||||
showSizeChanger: true,
|
||||
/**数据总数 */
|
||||
total: 0,
|
||||
showTotal: (total: number) =>
|
||||
t('common.tablePaginationTotal', { total: total }),
|
||||
onChange: (page: number, pageSize: number) => {
|
||||
tablePagination.current = page;
|
||||
tablePagination.pageSize = pageSize;
|
||||
queryParams.pageNum = page;
|
||||
queryParams.pageSize = pageSize;
|
||||
fnGetList();
|
||||
},
|
||||
});
|
||||
|
||||
/**列表导出 */
|
||||
function fnExportList() {
|
||||
Modal.confirm({
|
||||
title: t('common.tipTitle'),
|
||||
content: t('views.neData.baseStation.exportTip'),
|
||||
onOk() {
|
||||
const hide = message.loading(t('common.loading'), 0);
|
||||
const querys = toRaw(queryParams);
|
||||
exportNBState(querys)
|
||||
.then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS) {
|
||||
message.success({
|
||||
content: t('common.operateOk'),
|
||||
duration: 3,
|
||||
});
|
||||
saveAs(res.data, `nb_state_history_records_export_${Date.now()}.xlsx`);
|
||||
} else {
|
||||
message.error({
|
||||
content: `${res.msg}`,
|
||||
duration: 3,
|
||||
});
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
hide();
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**查询字典数据列表, pageNum初始页数 */
|
||||
function fnGetList(pageNum?: number) {
|
||||
if (tableState.loading) return;
|
||||
tableState.loading = true;
|
||||
if (pageNum) {
|
||||
queryParams.pageNum = pageNum;
|
||||
}
|
||||
|
||||
// 时间范围
|
||||
if (
|
||||
Array.isArray(queryRangePicker.value) &&
|
||||
queryRangePicker.value.length > 0
|
||||
) {
|
||||
queryParams.startTime = queryRangePicker.value[0].valueOf();
|
||||
queryParams.endTime = queryRangePicker.value[1].valueOf();
|
||||
} else {
|
||||
queryParams.startTime = undefined;
|
||||
queryParams.endTime = undefined;
|
||||
}
|
||||
|
||||
listNBState(toRaw(queryParams)).then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.rows)) {
|
||||
// 取消勾选
|
||||
if (tableState.selectedRowKeys.length > 0) {
|
||||
tableState.selectedRowKeys = [];
|
||||
}
|
||||
|
||||
tablePagination.total = res.total;
|
||||
tableState.data = res.rows;
|
||||
if (
|
||||
tablePagination.total <=
|
||||
(queryParams.pageNum - 1) * tablePagination.pageSize &&
|
||||
queryParams.pageNum !== 1
|
||||
) {
|
||||
tableState.loading = false;
|
||||
fnGetList(queryParams.pageNum - 1);
|
||||
}
|
||||
}
|
||||
tableState.loading = false;
|
||||
});
|
||||
}
|
||||
|
||||
/**弹框取消按钮事件 */
|
||||
function fnModalCancel() {
|
||||
emit('update:open', false);
|
||||
emit('cancel');
|
||||
}
|
||||
|
||||
/**监听是否显示,初始数据 */
|
||||
watch(
|
||||
() => props.open,
|
||||
val => {
|
||||
if (val) {
|
||||
queryParams.neType = props.neType;
|
||||
queryParams.neId = props.neId;
|
||||
// 获取列表数据
|
||||
fnGetList();
|
||||
}
|
||||
}
|
||||
);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ProModal
|
||||
:drag="true"
|
||||
:destroyOnClose="true"
|
||||
:width="1200"
|
||||
:title="props.title"
|
||||
:open="props.open"
|
||||
:keyboard="false"
|
||||
:mask-closable="false"
|
||||
@cancel="fnModalCancel"
|
||||
:footer="null"
|
||||
>
|
||||
<!-- 表格搜索栏 -->
|
||||
<a-form :model="queryParams" name="queryParams" layout="horizontal">
|
||||
<a-row :gutter="16" style="margin-left: 0; margin-right: 0">
|
||||
<a-col :lg="6" :md="12" :xs="24">
|
||||
<a-form-item
|
||||
:label="t('views.neData.baseStation.state')"
|
||||
name="status"
|
||||
>
|
||||
<a-select
|
||||
v-model:value="queryParams.status"
|
||||
allow-clear
|
||||
:placeholder="t('common.selectPlease')"
|
||||
:options="nbStateOptions"
|
||||
>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="16" :md="12" :xs="24">
|
||||
<a-form-item
|
||||
:label="t('views.neData.baseStation.time')"
|
||||
name="queryRangePicker"
|
||||
>
|
||||
<a-range-picker
|
||||
v-model:value="queryRangePicker"
|
||||
:bordered="true"
|
||||
:allow-clear="true"
|
||||
style="width: 100%"
|
||||
:show-time="{ format: 'HH:mm:ss' }"
|
||||
format="YYYY-MM-DD HH:mm:ss"
|
||||
></a-range-picker>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="24" :md="24" :xs="24">
|
||||
<a-form-item>
|
||||
<a-space :size="8">
|
||||
<a-button type="primary" @click.prevent="fnGetList(1)">
|
||||
<template #icon><SearchOutlined /></template>
|
||||
{{ t('common.search') }}
|
||||
</a-button>
|
||||
<a-button type="default" @click.prevent="fnQueryReset">
|
||||
<template #icon><ClearOutlined /></template>
|
||||
{{ t('common.reset') }}
|
||||
</a-button>
|
||||
<a-button type="dashed" @click.prevent="fnExportList()">
|
||||
<template #icon><ExportOutlined /></template>
|
||||
{{ t('common.export') }}
|
||||
</a-button>
|
||||
</a-space>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-form>
|
||||
|
||||
<!-- 表格列表 -->
|
||||
<a-table
|
||||
class="table"
|
||||
row-key="id"
|
||||
:columns="tableColumns"
|
||||
:loading="tableState.loading"
|
||||
:data-source="tableState.data"
|
||||
:size="tableState.size"
|
||||
:pagination="tablePagination"
|
||||
:scroll="{ x: tableColumns.length * 120, y: 'calc(100vh - 480px)' }"
|
||||
@resizeColumn="(w:number, col:any) => (col.width = w)"
|
||||
>
|
||||
<template #bodyCell="{ column, record }">
|
||||
<template v-if="column.key === 'state'">
|
||||
<DictTag
|
||||
:options="nbStateOptions"
|
||||
:value="record.state"
|
||||
value-default="OFF"
|
||||
/>
|
||||
</template>
|
||||
</template>
|
||||
</a-table>
|
||||
</ProModal>
|
||||
</template>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.table :deep(.ant-pagination) {
|
||||
padding: 0 24px;
|
||||
}
|
||||
</style>
|
||||
@@ -1,8 +1,8 @@
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
import { PageContainer } from 'antdv-pro-layout';
|
||||
import ListComponent from '@/views/ne-data/base-station/components/list.vue';
|
||||
import TopologyComponent from '@/views/ne-data/base-station/components/topology.vue';
|
||||
import ListComponent from './list.vue';
|
||||
import TopologyComponent from './topology.vue';
|
||||
import useI18n from '@/hooks/useI18n';
|
||||
const { t } = useI18n();
|
||||
const value = ref<string>('list');
|
||||
|
||||
@@ -1,27 +1,39 @@
|
||||
<script setup lang="ts">
|
||||
import { reactive, ref, onMounted, toRaw, computed } from 'vue';
|
||||
import {
|
||||
reactive,
|
||||
ref,
|
||||
onMounted,
|
||||
toRaw,
|
||||
computed,
|
||||
defineAsyncComponent,
|
||||
} from 'vue';
|
||||
import { Form, message, Modal } from 'ant-design-vue';
|
||||
import { SizeType } from 'ant-design-vue/es/config-provider';
|
||||
import { ColumnsType } from 'ant-design-vue/es/table';
|
||||
import { ProModal } from 'antdv-pro-modal';
|
||||
import UploadModal from '@/components/UploadModal/index.vue';
|
||||
import useNeInfoStore from '@/store/modules/neinfo';
|
||||
import useI18n from '@/hooks/useI18n';
|
||||
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
||||
const { t, currentLocale } = useI18n();
|
||||
import {
|
||||
addAMFNbState,
|
||||
delAMFNbState,
|
||||
editAMFNbState,
|
||||
listAMFNbStatelist,
|
||||
} from '@/api/neData/amf';
|
||||
const { t } = useI18n();
|
||||
import { useRoute } from 'vue-router';
|
||||
import {
|
||||
addMMENbState,
|
||||
delMMENbState,
|
||||
editMMENbState,
|
||||
listMMENbStatelist,
|
||||
} from '@/api/neData/mme';
|
||||
const route = useRoute();
|
||||
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
||||
import saveAs from 'file-saver';
|
||||
import { readSheet, writeSheet } from '@/utils/execl-utils';
|
||||
// 异步加载组件
|
||||
const HistoryModal = defineAsyncComponent(
|
||||
() => import('./components/history.vue')
|
||||
);
|
||||
|
||||
const nbState = ref<DictType[]>([
|
||||
{
|
||||
@@ -308,6 +320,11 @@ type ModalStateType = {
|
||||
from: Record<string, any>;
|
||||
/**确定按钮 loading */
|
||||
confirmLoading: boolean;
|
||||
/**历史框 */
|
||||
openByHistory: boolean;
|
||||
/**导入框 */
|
||||
openByImport: boolean;
|
||||
importMsgArr: string[];
|
||||
};
|
||||
|
||||
/**对话框对象信息状态 */
|
||||
@@ -326,6 +343,9 @@ let modalState: ModalStateType = reactive({
|
||||
ueNum: undefined,
|
||||
},
|
||||
confirmLoading: false,
|
||||
openByHistory: false,
|
||||
openByImport: false,
|
||||
importMsgArr: [],
|
||||
});
|
||||
|
||||
/**对话框内表单属性和校验规则 */
|
||||
@@ -432,9 +452,205 @@ function fnModalOk() {
|
||||
*/
|
||||
function fnModalCancel() {
|
||||
modalState.openByEdit = false;
|
||||
modalState.openByHistory = false;
|
||||
modalStateFrom.resetFields();
|
||||
}
|
||||
|
||||
/**导出当前列表 */
|
||||
function fnExportList() {
|
||||
Modal.confirm({
|
||||
title: t('common.tipTitle'),
|
||||
content: t('views.neData.baseStation.exportTip'),
|
||||
onOk: async () => {
|
||||
if (modalState.confirmLoading) return;
|
||||
modalState.confirmLoading = true;
|
||||
|
||||
let rows: Record<string, any>[] = [];
|
||||
// 勾选的网元数据
|
||||
if (tableState.selectedRowKeys.length > 0) {
|
||||
rows = tableState.data.filter(item =>
|
||||
tableState.selectedRowKeys.includes(item.index)
|
||||
);
|
||||
} else {
|
||||
rows = tableState.data;
|
||||
}
|
||||
|
||||
const dataArr: Record<string, any>[] = [];
|
||||
for (const row of rows) {
|
||||
let data: any = {};
|
||||
data[t('views.neData.baseStation.name')] = row.name;
|
||||
data[t('views.neData.baseStation.position')] = row.position;
|
||||
data[t('views.neData.baseStation.address')] = row.address;
|
||||
data[t('views.neData.baseStation.nbName')] = row.nbName;
|
||||
data[t('views.neData.baseStation.ueNum')] = row.ueNum;
|
||||
nbState.value.find(item => {
|
||||
if (item.value === row.state) {
|
||||
data[t('views.neData.baseStation.state')] = item.label;
|
||||
}
|
||||
});
|
||||
data[t('views.neData.baseStation.time')] = row.time || '-';
|
||||
dataArr.push(data);
|
||||
}
|
||||
|
||||
// 导出
|
||||
writeSheet(dataArr, 'Sheet1', {
|
||||
header: [
|
||||
t('views.neData.baseStation.name'),
|
||||
t('views.neData.baseStation.position'),
|
||||
t('views.neData.baseStation.address'),
|
||||
t('views.neData.baseStation.nbName'),
|
||||
t('views.neData.baseStation.ueNum'),
|
||||
t('views.neData.baseStation.state'),
|
||||
t('views.neData.baseStation.time'),
|
||||
],
|
||||
}).then(fileBlob =>
|
||||
saveAs(fileBlob, `nb_state_records_export_${Date.now()}.xlsx`)
|
||||
);
|
||||
|
||||
modalState.confirmLoading = false;
|
||||
tableState.selectedRowKeys = [];
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**对话框弹出历史窗口 */
|
||||
function fnHistoryView() {
|
||||
modalState.openByHistory = true;
|
||||
}
|
||||
|
||||
/**对话框表格信息导入弹出窗口 */
|
||||
function fnModalImportOpen() {
|
||||
modalState.openByImport = true;
|
||||
}
|
||||
function fnModalImportClose() {
|
||||
modalState.openByImport = false;
|
||||
fnQueryReset();
|
||||
}
|
||||
|
||||
/**对话框表格信息导入上传 */
|
||||
function fnModalImportUpload(file: File) {
|
||||
const hide = message.loading(t('common.loading'), 0);
|
||||
const [neType, neId] = neTypeAndId.value;
|
||||
modalState.importMsgArr = [];
|
||||
|
||||
// 获取最大index
|
||||
let index = 0;
|
||||
if (tableState.data.length <= 0) {
|
||||
index = 1;
|
||||
} else {
|
||||
const last = tableState.data[tableState.data.length - 1];
|
||||
index = last.index + 1;
|
||||
}
|
||||
|
||||
const reader = new FileReader();
|
||||
reader.onload = function (e: any) {
|
||||
const arrayBuffer = e.target.result;
|
||||
readSheet(arrayBuffer).then(async rows => {
|
||||
console.log(rows);
|
||||
if (rows.length <= 0) {
|
||||
hide();
|
||||
message.error({
|
||||
content: t('views.neData.baseStation.importDataEmpty'),
|
||||
duration: 3,
|
||||
});
|
||||
return;
|
||||
}
|
||||
// 开始导入
|
||||
modalState.confirmLoading = true;
|
||||
for (const row of rows) {
|
||||
const rowId = row[t('common.rowId')];
|
||||
const name = row[t('views.neData.baseStation.name')];
|
||||
const position = row[t('views.neData.baseStation.position')];
|
||||
const address = row[t('views.neData.baseStation.address')];
|
||||
let result: any = null;
|
||||
// 检查IP地址是否定义
|
||||
const hasAddress = tableState.data.find(
|
||||
item => item.address === address
|
||||
);
|
||||
if (hasAddress) {
|
||||
// 定义则更新名称位置
|
||||
if (neType === 'MME') {
|
||||
result = await editMMENbState(
|
||||
neId,
|
||||
Object.assign({}, hasAddress, {
|
||||
name,
|
||||
position,
|
||||
})
|
||||
);
|
||||
}
|
||||
if (neType === 'AMF') {
|
||||
result = await editAMFNbState(
|
||||
neId,
|
||||
Object.assign({}, hasAddress, {
|
||||
name,
|
||||
position,
|
||||
})
|
||||
);
|
||||
}
|
||||
let msg = `${t('common.rowId')}: ${rowId} ${t(
|
||||
'views.neData.baseStation.editRadio'
|
||||
)}${t('common.operateErr')}`;
|
||||
if (result.code === RESULT_CODE_SUCCESS) {
|
||||
msg = `${t('common.rowId')}: ${rowId} ${t(
|
||||
'views.neData.baseStation.editRadio'
|
||||
)}${t('common.operateOk')}`;
|
||||
}
|
||||
modalState.importMsgArr.push(msg);
|
||||
} else {
|
||||
// 未定义则新增
|
||||
const form = {
|
||||
index,
|
||||
name: `${name}`,
|
||||
position: `${position}`,
|
||||
address: `${address}`,
|
||||
};
|
||||
if (neType === 'MME') {
|
||||
result = await addMMENbState(neId, form);
|
||||
}
|
||||
if (neType === 'AMF') {
|
||||
result = await addAMFNbState(neId, form);
|
||||
}
|
||||
let msg = `${t('common.rowId')}: ${rowId} ${t(
|
||||
'views.neData.baseStation.addRadio'
|
||||
)}${t('common.operateErr')}`;
|
||||
if (result.code === RESULT_CODE_SUCCESS) {
|
||||
index += 1;
|
||||
msg = `${t('common.rowId')}: ${rowId} ${t(
|
||||
'views.neData.baseStation.addRadio'
|
||||
)}${t('common.operateOk')}`;
|
||||
}
|
||||
modalState.importMsgArr.push(msg);
|
||||
}
|
||||
}
|
||||
|
||||
hide();
|
||||
modalState.confirmLoading = false;
|
||||
});
|
||||
};
|
||||
reader.onerror = function (e) {
|
||||
hide();
|
||||
console.error('reader file error:', e);
|
||||
};
|
||||
reader.readAsArrayBuffer(file);
|
||||
}
|
||||
|
||||
/**对话框表格信息导入模板 */
|
||||
async function fnModalImportTemplate() {
|
||||
const baseUrl = import.meta.env.VITE_HISTORY_BASE_URL;
|
||||
const xlsxUrl = `${
|
||||
baseUrl.length === 1 && baseUrl.indexOf('/') === 0
|
||||
? ''
|
||||
: baseUrl.indexOf('/') === -1
|
||||
? '/' + baseUrl
|
||||
: baseUrl
|
||||
}/nbStateImput`;
|
||||
const lang = currentLocale.value.split('_')[0];
|
||||
saveAs(
|
||||
`${xlsxUrl}/${lang}.xlsx`,
|
||||
`nb_state_records_import_template_${Date.now()}.xlsx`
|
||||
);
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
// 获取网元网元列表
|
||||
useNeInfoStore()
|
||||
@@ -450,8 +666,7 @@ onMounted(() => {
|
||||
});
|
||||
neCascaderOptions.value = arr;
|
||||
// 无查询参数neType时 默认选择AMF
|
||||
const queryNeType = (route.query.neType as string) || 'AMF';
|
||||
const item = arr.find(s => s.value === queryNeType);
|
||||
const item = arr.find(s => s.value === 'AMF');
|
||||
if (item && item.children) {
|
||||
const info = item.children[0];
|
||||
neTypeAndId.value = [info.neType, info.neId];
|
||||
@@ -554,6 +769,18 @@ onMounted(() => {
|
||||
<template #icon><DeleteOutlined /></template>
|
||||
{{ t('common.deleteText') }}
|
||||
</a-button>
|
||||
<a-button type="dashed" @click.prevent="fnModalImportOpen()">
|
||||
<template #icon><ImportOutlined /></template>
|
||||
{{ t('common.import') }}
|
||||
</a-button>
|
||||
<a-button type="dashed" @click.prevent="fnExportList()">
|
||||
<template #icon><ExportOutlined /></template>
|
||||
{{ t('common.export') }}
|
||||
</a-button>
|
||||
<a-button type="default" @click.prevent="fnHistoryView()">
|
||||
<template #icon><ContainerOutlined /></template>
|
||||
{{ t('views.neData.baseStation.history') }}
|
||||
</a-button>
|
||||
</a-space>
|
||||
</template>
|
||||
|
||||
@@ -677,6 +904,47 @@ onMounted(() => {
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</ProModal>
|
||||
|
||||
<!-- 状态历史框 -->
|
||||
<HistoryModal
|
||||
v-model:open="modalState.openByHistory"
|
||||
:title="t('views.neData.baseStation.history')"
|
||||
:ne-type="neTypeAndId[0]"
|
||||
:ne-id="neTypeAndId[1]"
|
||||
@cancel="fnModalCancel"
|
||||
></HistoryModal>
|
||||
|
||||
<!-- 上传导入表格数据文件框 -->
|
||||
<UploadModal
|
||||
:title="t('common.import')"
|
||||
@upload="fnModalImportUpload"
|
||||
@close="fnModalImportClose"
|
||||
v-model:open="modalState.openByImport"
|
||||
:ext="['.xls', '.xlsx']"
|
||||
:size="10"
|
||||
>
|
||||
<template #default>
|
||||
<a-row justify="space-between" align="middle">
|
||||
<a-col :span="12"> </a-col>
|
||||
<a-col :span="6">
|
||||
<a-button
|
||||
type="link"
|
||||
:title="t('views.system.user.downloadObj')"
|
||||
@click.prevent="fnModalImportTemplate"
|
||||
>
|
||||
{{ t('views.system.user.downloadObj') }}
|
||||
</a-button>
|
||||
</a-col>
|
||||
</a-row>
|
||||
<a-textarea
|
||||
:disabled="true"
|
||||
:hidden="modalState.importMsgArr.length <= 0"
|
||||
:value="modalState.importMsgArr.join('\r\n')"
|
||||
:auto-size="{ minRows: 2, maxRows: 8 }"
|
||||
style="background-color: transparent; color: rgba(0, 0, 0, 0.85)"
|
||||
/>
|
||||
</template>
|
||||
</UploadModal>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -25,6 +25,7 @@ import {
|
||||
listUDMAuth,
|
||||
} from '@/api/neData/udm_auth';
|
||||
import { uploadFile } from '@/api/tool/file';
|
||||
import { getNeViewFile } from '@/api/tool/neFile';
|
||||
const { t } = useI18n();
|
||||
|
||||
/**网元参数 */
|
||||
@@ -98,12 +99,6 @@ let tableColumns = ref<ColumnsType>([
|
||||
align: 'center',
|
||||
width: 80,
|
||||
},
|
||||
{
|
||||
title: 'Status',
|
||||
dataIndex: 'status',
|
||||
align: 'center',
|
||||
width: 80,
|
||||
},
|
||||
// {
|
||||
// title: 'KI',
|
||||
// dataIndex: 'ki',
|
||||
@@ -598,6 +593,8 @@ type ModalUploadImportStateType = {
|
||||
loading: boolean;
|
||||
/**上传结果信息 */
|
||||
msg: string;
|
||||
/**含失败信息 */
|
||||
hasFail: boolean;
|
||||
/**导入类型 */
|
||||
typeOptions: { label: string; value: string }[];
|
||||
/**表单 */
|
||||
@@ -610,6 +607,7 @@ let uploadImportState: ModalUploadImportStateType = reactive({
|
||||
title: t('components.UploadModal.uploadTitle'),
|
||||
loading: false,
|
||||
msg: '',
|
||||
hasFail: false,
|
||||
typeOptions: [
|
||||
{ label: 'Default', value: 'default' },
|
||||
{ label: 'K4', value: 'k4' },
|
||||
@@ -626,9 +624,37 @@ function fnModalUploadImportTypeChange() {
|
||||
uploadImportState.msg = '';
|
||||
}
|
||||
|
||||
/**对话框表格信息导入失败原因 */
|
||||
function fnModalUploadImportFailReason() {
|
||||
const neId = queryParams.neId;
|
||||
if (!neId) return;
|
||||
const hide = message.loading(t('common.loading'), 0);
|
||||
getNeViewFile({
|
||||
neType: 'UDM',
|
||||
neId: neId,
|
||||
path: '/tmp',
|
||||
fileName: 'import_authdata_err_records.txt',
|
||||
})
|
||||
.then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS) {
|
||||
message.success(t('common.operateOk'), 3);
|
||||
const blob = new Blob([res.data], {
|
||||
type: 'text/plain',
|
||||
});
|
||||
saveAs(blob, `import_authdata_err_records_${Date.now()}.txt`);
|
||||
} else {
|
||||
message.error(`${res.msg}`, 3);
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
hide();
|
||||
});
|
||||
}
|
||||
|
||||
/**对话框表格信息导入弹出窗口 */
|
||||
function fnModalUploadImportOpen() {
|
||||
uploadImportState.msg = '';
|
||||
uploadImportState.hasFail = false;
|
||||
uploadImportState.from.typeVal = 'default';
|
||||
uploadImportState.from.typeData = undefined;
|
||||
uploadImportState.loading = false;
|
||||
@@ -675,6 +701,14 @@ function fnModalUploadImportUpload(file: File) {
|
||||
.then(res => {
|
||||
if (!res) return;
|
||||
uploadImportState.msg = res.msg;
|
||||
const regex = /fail num: (\d+)/;
|
||||
const match = res.msg.match(regex);
|
||||
if (match) {
|
||||
const failNum = Number(match[1]);
|
||||
uploadImportState.hasFail = failNum > 0;
|
||||
} else {
|
||||
uploadImportState.hasFail = false;
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
hide();
|
||||
@@ -973,25 +1007,7 @@ onMounted(() => {
|
||||
:label-col="{ span: 6 }"
|
||||
:labelWrap="true"
|
||||
>
|
||||
<a-row>
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
<a-form-item
|
||||
:label="t('views.neUser.auth.numAdd')"
|
||||
name="num"
|
||||
v-bind="modalStateFrom.validateInfos.num"
|
||||
v-show="!modalState.from.id"
|
||||
>
|
||||
<a-input-number
|
||||
v-model:value="modalState.from.num"
|
||||
style="width: 100%"
|
||||
:min="1"
|
||||
:max="10000"
|
||||
placeholder="<=10000"
|
||||
></a-input-number>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
<a-row>
|
||||
<a-row v-show="!modalState.from.id">
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
<a-form-item
|
||||
label="IMSI"
|
||||
@@ -1019,11 +1035,20 @@ onMounted(() => {
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
<a-form-item label="Status" name="status">
|
||||
<a-select value="1">
|
||||
<a-select-option value="1">Active</a-select-option>
|
||||
<a-select-option value="0">Inactive</a-select-option>
|
||||
</a-select>
|
||||
<a-form-item
|
||||
:label="t('views.neUser.auth.numAdd')"
|
||||
name="num"
|
||||
v-bind="modalStateFrom.validateInfos.num"
|
||||
:label-col="{ span: 10 }"
|
||||
:labelWrap="false"
|
||||
>
|
||||
<a-input-number
|
||||
v-model:value="modalState.from.num"
|
||||
style="width: 100%"
|
||||
:min="1"
|
||||
:max="10000"
|
||||
placeholder="<=10000"
|
||||
></a-input-number>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
@@ -1056,6 +1081,8 @@ onMounted(() => {
|
||||
label="Algo Index"
|
||||
name="algo"
|
||||
v-bind="modalStateFrom.validateInfos.algoIndex"
|
||||
:label-col="{ span: 10 }"
|
||||
:labelWrap="false"
|
||||
>
|
||||
<a-input-number
|
||||
v-model:value="modalState.from.algoIndex"
|
||||
@@ -1141,7 +1168,7 @@ onMounted(() => {
|
||||
<a-form
|
||||
name="modalStateBatchDelFrom"
|
||||
layout="horizontal"
|
||||
:label-col="{ span: 6 }"
|
||||
:label-col="{ span: 8 }"
|
||||
:labelWrap="true"
|
||||
>
|
||||
<a-row>
|
||||
@@ -1210,13 +1237,23 @@ onMounted(() => {
|
||||
v-model:value="uploadImportState.from.typeData"
|
||||
:placeholder="t('common.inputPlease')"
|
||||
/>
|
||||
<a-textarea
|
||||
:disabled="true"
|
||||
:hidden="!uploadImportState.msg"
|
||||
:value="uploadImportState.msg"
|
||||
:auto-size="{ minRows: 2, maxRows: 8 }"
|
||||
style="background-color: transparent; color: rgba(0, 0, 0, 0.85)"
|
||||
/>
|
||||
<a-alert
|
||||
:message="uploadImportState.msg"
|
||||
:type="uploadImportState.hasFail ? 'warning' : 'info'"
|
||||
v-show="uploadImportState.msg.length > 0"
|
||||
>
|
||||
<template #action>
|
||||
<a-button
|
||||
size="small"
|
||||
type="link"
|
||||
danger
|
||||
@click="fnModalUploadImportFailReason"
|
||||
v-if="uploadImportState.hasFail"
|
||||
>
|
||||
{{ t('views.neUser.auth.importFail') }}
|
||||
</a-button>
|
||||
</template>
|
||||
</a-alert>
|
||||
</template>
|
||||
</UploadModal>
|
||||
</PageContainer>
|
||||
|
||||
@@ -26,6 +26,7 @@ import {
|
||||
} from '@/api/neData/udm_sub';
|
||||
import { listTenant } from '@/api/system/tenant';
|
||||
import { uploadFile } from '@/api/tool/file';
|
||||
import { getNeViewFile } from '@/api/tool/neFile';
|
||||
const { t } = useI18n();
|
||||
|
||||
/**网元参数 */
|
||||
@@ -577,7 +578,8 @@ function transformFormData(data: any) {
|
||||
if (isValid) {
|
||||
smStaticIpArr.push(dnnParts);
|
||||
}
|
||||
} else {//无/ 无:也有可能为dnn的字符串
|
||||
} else {
|
||||
//无/ 无:也有可能为dnn的字符串
|
||||
smallRowJson.dnn += '-' + dnnParts;
|
||||
}
|
||||
}
|
||||
@@ -668,8 +670,8 @@ function fnModalOk() {
|
||||
const result = from.id
|
||||
? updateUDMSub(from)
|
||||
: from.num === 1
|
||||
? addUDMSub(from)
|
||||
: batchAddUDMSub(from, from.num);
|
||||
? addUDMSub(from)
|
||||
: batchAddUDMSub(from, from.num);
|
||||
const hide = message.loading(t('common.loading'), 0);
|
||||
result
|
||||
.then(res => {
|
||||
@@ -999,7 +1001,7 @@ function fnGetList(pageNum?: number) {
|
||||
tableState.data = res.rows;
|
||||
if (
|
||||
tablePagination.total <=
|
||||
(queryParams.pageNum - 1) * tablePagination.pageSize &&
|
||||
(queryParams.pageNum - 1) * tablePagination.pageSize &&
|
||||
queryParams.pageNum !== 1
|
||||
) {
|
||||
tableState.loading = false;
|
||||
@@ -1020,6 +1022,8 @@ type ModalUploadImportStateType = {
|
||||
loading: boolean;
|
||||
/**上传结果信息 */
|
||||
msg: string;
|
||||
/**含失败信息 */
|
||||
hasFail: boolean;
|
||||
};
|
||||
|
||||
/**对话框表格信息导入对象信息状态 */
|
||||
@@ -1028,11 +1032,40 @@ let uploadImportState: ModalUploadImportStateType = reactive({
|
||||
title: t('components.UploadModal.uploadTitle'),
|
||||
loading: false,
|
||||
msg: '',
|
||||
hasFail: false,
|
||||
});
|
||||
|
||||
/**对话框表格信息导入失败原因 */
|
||||
function fnModalUploadImportFailReason() {
|
||||
const neId = queryParams.neId;
|
||||
if (!neId) return;
|
||||
const hide = message.loading(t('common.loading'), 0);
|
||||
getNeViewFile({
|
||||
neType: 'UDM',
|
||||
neId: neId,
|
||||
path: '/tmp',
|
||||
fileName: 'import_udmuser_err_records.txt',
|
||||
})
|
||||
.then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS) {
|
||||
message.success(t('common.operateOk'), 3);
|
||||
const blob = new Blob([res.data], {
|
||||
type: 'text/plain',
|
||||
});
|
||||
saveAs(blob, `import_udmuser_err_records_${Date.now()}.txt`);
|
||||
} else {
|
||||
message.error(`${res.msg}`, 3);
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
hide();
|
||||
});
|
||||
}
|
||||
|
||||
/**对话框表格信息导入弹出窗口 */
|
||||
function fnModalUploadImportOpen() {
|
||||
uploadImportState.msg = '';
|
||||
uploadImportState.hasFail = false;
|
||||
uploadImportState.loading = false;
|
||||
uploadImportState.open = true;
|
||||
}
|
||||
@@ -1076,6 +1109,14 @@ function fnModalUploadImportUpload(file: File) {
|
||||
.then(res => {
|
||||
if (!res) return;
|
||||
uploadImportState.msg = res.msg;
|
||||
const regex = /fail num: (\d+)/;
|
||||
const match = res.msg.match(regex);
|
||||
if (match) {
|
||||
const failNum = Number(match[1]);
|
||||
uploadImportState.hasFail = failNum > 0;
|
||||
} else {
|
||||
uploadImportState.hasFail = false;
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
hide();
|
||||
@@ -1174,14 +1215,22 @@ onMounted(() => {
|
||||
|
||||
<template>
|
||||
<PageContainer>
|
||||
<a-card v-show="tableState.seached" :bordered="false" :body-style="{ marginBottom: '24px', paddingBottom: 0 }">
|
||||
<a-card
|
||||
v-show="tableState.seached"
|
||||
:bordered="false"
|
||||
:body-style="{ marginBottom: '24px', paddingBottom: 0 }"
|
||||
>
|
||||
<!-- 表格搜索栏 -->
|
||||
<a-form :model="queryParams" name="queryParams" layout="horizontal">
|
||||
<a-row :gutter="16">
|
||||
<a-col :lg="6" :md="12" :xs="24">
|
||||
<a-form-item :label="t('views.neUser.sub.neType')" name="neId ">
|
||||
<a-select v-model:value="queryParams.neId" :options="neOtions" :placeholder="t('common.selectPlease')"
|
||||
@change="fnGetList(1)" />
|
||||
<a-select
|
||||
v-model:value="queryParams.neId"
|
||||
:options="neOtions"
|
||||
:placeholder="t('common.selectPlease')"
|
||||
@change="fnGetList(1)"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
|
||||
@@ -1258,16 +1307,31 @@ onMounted(() => {
|
||||
{{ t('common.addText') }}
|
||||
</a-button>
|
||||
|
||||
<a-button type="primary" danger ghost @click.prevent="fnModalVisibleByBatch()">
|
||||
<a-button
|
||||
type="primary"
|
||||
danger
|
||||
ghost
|
||||
@click.prevent="fnModalVisibleByBatch()"
|
||||
>
|
||||
<template #icon>
|
||||
<DeleteOutlined />
|
||||
</template>
|
||||
{{ t('views.neUser.auth.batchDelText') }}
|
||||
</a-button>
|
||||
|
||||
<a-popconfirm :title="t('views.neUser.sub.loadDataConfirm')" :ok-text="t('common.ok')"
|
||||
:cancel-text="t('common.cancel')" :disabled="modalState.loadDataLoading" @confirm="fnLoadData">
|
||||
<a-button type="dashed" danger :disabled="modalState.loadDataLoading" :loading="modalState.loadDataLoading">
|
||||
<a-popconfirm
|
||||
:title="t('views.neUser.sub.loadDataConfirm')"
|
||||
:ok-text="t('common.ok')"
|
||||
:cancel-text="t('common.cancel')"
|
||||
:disabled="modalState.loadDataLoading"
|
||||
@confirm="fnLoadData"
|
||||
>
|
||||
<a-button
|
||||
type="dashed"
|
||||
danger
|
||||
:disabled="modalState.loadDataLoading"
|
||||
:loading="modalState.loadDataLoading"
|
||||
>
|
||||
<template #icon>
|
||||
<SyncOutlined />
|
||||
</template>
|
||||
@@ -1282,8 +1346,13 @@ onMounted(() => {
|
||||
{{ t('views.neUser.sub.import') }}
|
||||
</a-button>
|
||||
|
||||
<a-popconfirm :title="t('views.neUser.sub.exportConfirm')" placement="topRight" ok-text="TXT"
|
||||
ok-type="default" @confirm="fnExportList('txt')">
|
||||
<a-popconfirm
|
||||
:title="t('views.neUser.sub.exportConfirm')"
|
||||
placement="topRight"
|
||||
ok-text="TXT"
|
||||
ok-type="default"
|
||||
@confirm="fnExportList('txt')"
|
||||
>
|
||||
<a-button type="dashed">
|
||||
<template #icon>
|
||||
<ExportOutlined />
|
||||
@@ -1292,17 +1361,31 @@ onMounted(() => {
|
||||
</a-button>
|
||||
</a-popconfirm>
|
||||
|
||||
<a-button type="default" danger :disabled="tableState.selectedRowKeys.length <= 0"
|
||||
:loading="modalState.loadDataLoading" @click.prevent="fnRecordDelete('0')">
|
||||
<a-button
|
||||
type="default"
|
||||
danger
|
||||
:disabled="tableState.selectedRowKeys.length <= 0"
|
||||
:loading="modalState.loadDataLoading"
|
||||
@click.prevent="fnRecordDelete('0')"
|
||||
>
|
||||
<template #icon>
|
||||
<DeleteOutlined />
|
||||
</template>
|
||||
{{ t('views.neUser.sub.checkDel') }}
|
||||
</a-button>
|
||||
|
||||
<a-popconfirm :title="t('views.neUser.sub.checkExportConfirm')" placement="topRight" ok-text="TXT"
|
||||
ok-type="default" @confirm="fnRecordExport('txt')" :disabled="tableState.selectedRowKeys.length <= 0">
|
||||
<a-button type="default" :disabled="tableState.selectedRowKeys.length <= 0">
|
||||
<a-popconfirm
|
||||
:title="t('views.neUser.sub.checkExportConfirm')"
|
||||
placement="topRight"
|
||||
ok-text="TXT"
|
||||
ok-type="default"
|
||||
@confirm="fnRecordExport('txt')"
|
||||
:disabled="tableState.selectedRowKeys.length <= 0"
|
||||
>
|
||||
<a-button
|
||||
type="default"
|
||||
:disabled="tableState.selectedRowKeys.length <= 0"
|
||||
>
|
||||
<template #icon>
|
||||
<ExportOutlined />
|
||||
</template>
|
||||
@@ -1317,8 +1400,12 @@ onMounted(() => {
|
||||
<a-space :size="8" align="center">
|
||||
<a-tooltip>
|
||||
<template #title>{{ t('common.searchBarText') }}</template>
|
||||
<a-switch v-model:checked="tableState.seached" :checked-children="t('common.switch.show')"
|
||||
:un-checked-children="t('common.switch.hide')" size="small" />
|
||||
<a-switch
|
||||
v-model:checked="tableState.seached"
|
||||
:checked-children="t('common.switch.show')"
|
||||
:un-checked-children="t('common.switch.hide')"
|
||||
size="small"
|
||||
/>
|
||||
</a-tooltip>
|
||||
<a-tooltip>
|
||||
<template #title>{{ t('common.reloadText') }}</template>
|
||||
@@ -1328,7 +1415,11 @@ onMounted(() => {
|
||||
</template>
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
<TableColumnsDnd cache-id="udmSubData" :columns="tableColumns" v-model:columns-dnd="tableColumnsDnd">
|
||||
<TableColumnsDnd
|
||||
cache-id="udmSubData"
|
||||
:columns="tableColumns"
|
||||
v-model:columns-dnd="tableColumnsDnd"
|
||||
>
|
||||
</TableColumnsDnd>
|
||||
<a-tooltip placement="topRight">
|
||||
<template #title>{{ t('common.sizeText') }}</template>
|
||||
@@ -1339,7 +1430,10 @@ onMounted(() => {
|
||||
</template>
|
||||
</a-button>
|
||||
<template #overlay>
|
||||
<a-menu :selected-keys="[tableState.size as string]" @click="fnTableSize">
|
||||
<a-menu
|
||||
:selected-keys="[tableState.size as string]"
|
||||
@click="fnTableSize"
|
||||
>
|
||||
<a-menu-item key="default">
|
||||
{{ t('common.size.default') }}
|
||||
</a-menu-item>
|
||||
@@ -1357,14 +1451,23 @@ onMounted(() => {
|
||||
</template>
|
||||
|
||||
<!-- 表格列表 -->
|
||||
<a-table class="table" row-key="imsi" :columns="tableColumnsDnd" :loading="tableState.loading"
|
||||
:data-source="tableState.data" :size="tableState.size" :pagination="tablePagination"
|
||||
:scroll="{ y: 'calc(100vh - 480px)' }" @change="fnTableChange"
|
||||
@resizeColumn="(w: number, col: any) => (col.width = w)" :row-selection="{
|
||||
<a-table
|
||||
class="table"
|
||||
row-key="imsi"
|
||||
:columns="tableColumnsDnd"
|
||||
:loading="tableState.loading"
|
||||
:data-source="tableState.data"
|
||||
:size="tableState.size"
|
||||
:pagination="tablePagination"
|
||||
:scroll="{ y: 'calc(100vh - 480px)' }"
|
||||
@change="fnTableChange"
|
||||
@resizeColumn="(w: number, col: any) => (col.width = w)"
|
||||
:row-selection="{
|
||||
type: 'checkbox',
|
||||
selectedRowKeys: tableState.selectedRowKeys,
|
||||
onChange: fnTableSelectedRowKeys,
|
||||
}">
|
||||
}"
|
||||
>
|
||||
<template #bodyCell="{ column, record }">
|
||||
<template v-if="column.key === 'cnFlag'">
|
||||
{{
|
||||
@@ -1384,7 +1487,10 @@ onMounted(() => {
|
||||
<a-space :size="8" align="center">
|
||||
<a-tooltip>
|
||||
<template #title>{{ t('common.editText') }}</template>
|
||||
<a-button type="link" @click.prevent="fnModalVisibleByEdit(record.imsi)">
|
||||
<a-button
|
||||
type="link"
|
||||
@click.prevent="fnModalVisibleByEdit(record.imsi)"
|
||||
>
|
||||
<template #icon>
|
||||
<FormOutlined />
|
||||
</template>
|
||||
@@ -1392,7 +1498,10 @@ onMounted(() => {
|
||||
</a-tooltip>
|
||||
<a-tooltip>
|
||||
<template #title>{{ t('common.deleteText') }}</template>
|
||||
<a-button type="link" @click.prevent="fnRecordDelete(record.imsi)">
|
||||
<a-button
|
||||
type="link"
|
||||
@click.prevent="fnRecordDelete(record.imsi)"
|
||||
>
|
||||
<template #icon>
|
||||
<DeleteOutlined />
|
||||
</template>
|
||||
@@ -1405,26 +1514,59 @@ onMounted(() => {
|
||||
</a-card>
|
||||
|
||||
<!-- 新增框或修改框 -->
|
||||
<ProModal :drag="true" :width="800" :destroyOnClose="true" style="top: 0px"
|
||||
:body-style="{ maxHeight: '600px', 'overflow-y': 'auto' }" :keyboard="false" :mask-closable="false"
|
||||
:open="modalState.openByEdit" :title="modalState.title" :confirm-loading="modalState.confirmLoading"
|
||||
@ok="fnModalOk" @cancel="fnModalCancel">
|
||||
<a-form name="modalStateFrom" layout="horizontal" :label-col="{ span: 6 }" :labelWrap="true">
|
||||
<ProModal
|
||||
:drag="true"
|
||||
:width="800"
|
||||
:destroyOnClose="true"
|
||||
style="top: 0px"
|
||||
:body-style="{ maxHeight: '600px', 'overflow-y': 'auto' }"
|
||||
:keyboard="false"
|
||||
:mask-closable="false"
|
||||
:open="modalState.openByEdit"
|
||||
:title="modalState.title"
|
||||
:confirm-loading="modalState.confirmLoading"
|
||||
@ok="fnModalOk"
|
||||
@cancel="fnModalCancel"
|
||||
>
|
||||
<a-form
|
||||
name="modalStateFrom"
|
||||
layout="horizontal"
|
||||
:label-col="{ span: 6 }"
|
||||
:labelWrap="true"
|
||||
>
|
||||
<a-row>
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
<a-form-item :label="t('views.neUser.sub.numAdd')" name="num" v-bind="modalStateFrom.validateInfos.num"
|
||||
v-show="!modalState.from.id">
|
||||
<a-input-number v-model:value="modalState.from.num" style="width: 100%" :min="1" :max="10000"
|
||||
placeholder="<=10000"></a-input-number>
|
||||
<a-col :lg="12" :md="12" :xs="24" v-show="!modalState.from.id">
|
||||
<a-form-item
|
||||
:label="t('views.neUser.sub.numAdd')"
|
||||
name="num"
|
||||
v-bind="modalStateFrom.validateInfos.num"
|
||||
:label-col="{ span: 12 }"
|
||||
:labelWrap="false"
|
||||
>
|
||||
<a-input-number
|
||||
v-model:value="modalState.from.num"
|
||||
style="width: 100%"
|
||||
:min="1"
|
||||
:max="10000"
|
||||
placeholder="<=10000"
|
||||
></a-input-number>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
|
||||
<a-row>
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
<a-form-item label="IMSI" name="imsi" v-bind="modalStateFrom.validateInfos.imsi">
|
||||
<a-input v-model:value="modalState.from.imsi" allow-clear :maxlength="15"
|
||||
:disabled="!!modalState.from.id">
|
||||
<a-form-item
|
||||
label="IMSI"
|
||||
name="imsi"
|
||||
v-bind="modalStateFrom.validateInfos.imsi"
|
||||
>
|
||||
<a-input
|
||||
v-model:value="modalState.from.imsi"
|
||||
allow-clear
|
||||
:maxlength="15"
|
||||
:disabled="!!modalState.from.id"
|
||||
>
|
||||
<template #prefix>
|
||||
<a-tooltip placement="topLeft">
|
||||
<template #title>
|
||||
@@ -1440,8 +1582,16 @@ onMounted(() => {
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
<a-form-item label="MSISDN" name="msisdn" v-bind="modalStateFrom.validateInfos.msisdn">
|
||||
<a-input v-model:value="modalState.from.msisdn" allow-clear :maxlength="32">
|
||||
<a-form-item
|
||||
label="MSISDN"
|
||||
name="msisdn"
|
||||
v-bind="modalStateFrom.validateInfos.msisdn"
|
||||
>
|
||||
<a-input
|
||||
v-model:value="modalState.from.msisdn"
|
||||
allow-clear
|
||||
:maxlength="32"
|
||||
>
|
||||
<template #prefix>
|
||||
<a-tooltip placement="topLeft">
|
||||
<template #title>
|
||||
@@ -1455,24 +1605,49 @@ onMounted(() => {
|
||||
</a-col>
|
||||
</a-row>
|
||||
|
||||
<a-form-item :label="t('common.remark')" :label-col="{ span: 3 }" :label-wrap="true">
|
||||
<a-textarea v-model:value="modalState.from.remark" :auto-size="{ minRows: 1, maxRows: 6 }" :maxlength="500"
|
||||
:show-count="true" :placeholder="t('common.inputPlease')" />
|
||||
<a-form-item
|
||||
:label="t('common.remark')"
|
||||
:label-col="{ span: 3 }"
|
||||
:label-wrap="true"
|
||||
>
|
||||
<a-textarea
|
||||
v-model:value="modalState.from.remark"
|
||||
:auto-size="{ minRows: 1, maxRows: 6 }"
|
||||
:maxlength="500"
|
||||
:show-count="true"
|
||||
:placeholder="t('common.inputPlease')"
|
||||
/>
|
||||
</a-form-item>
|
||||
|
||||
<!-- SM Data ---- S -->
|
||||
<a-divider orientation="left">
|
||||
Subscribed SM Data
|
||||
<a-tooltip title="Add SM Data">
|
||||
<a-button shape="circle" @click="addBigRow" style="margin-left: 10px">
|
||||
<a-button
|
||||
shape="circle"
|
||||
@click="addBigRow"
|
||||
style="margin-left: 10px"
|
||||
>
|
||||
<template #icon><plus-outlined /></template>
|
||||
</a-button> </a-tooltip></a-divider>
|
||||
</a-button> </a-tooltip
|
||||
></a-divider>
|
||||
<!-- 大数组布局 -->
|
||||
<div v-for="(row, index) in bigRows" :key="String(row.id)">
|
||||
<a-row>
|
||||
<a-col :lg="6" :md="6" :xs="24">
|
||||
<a-form-item label="SST" name="row.sst" :label-col="{ span: 12 }" :validateTrigger="[]" :required="true">
|
||||
<a-input-number v-model:value="row.sst" :min="1" :max="3" :step="1" />
|
||||
<a-form-item
|
||||
label="SST"
|
||||
name="row.sst"
|
||||
:label-col="{ span: 12 }"
|
||||
:validateTrigger="[]"
|
||||
:required="true"
|
||||
>
|
||||
<a-input-number
|
||||
v-model:value="row.sst"
|
||||
:min="1"
|
||||
:max="3"
|
||||
:step="1"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
|
||||
@@ -1485,7 +1660,11 @@ onMounted(() => {
|
||||
<a-row>
|
||||
<a-col :span="4">
|
||||
<a-tooltip title="Add DNN">
|
||||
<a-button shape="circle" @click="addSmallRow(row.id)" style="margin-left:10px ;">
|
||||
<a-button
|
||||
shape="circle"
|
||||
@click="addSmallRow(row.id)"
|
||||
style="margin-left: 10px"
|
||||
>
|
||||
<template #icon><plus-square-outlined /></template>
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
@@ -1502,27 +1681,51 @@ onMounted(() => {
|
||||
</a-row>
|
||||
|
||||
<!-- 小数组布局 -->
|
||||
<div v-for="(smallRow, smallIndex) in row.smallRows" :key="String(smallRow.id)">
|
||||
<div
|
||||
v-for="(smallRow, smallIndex) in row.smallRows"
|
||||
:key="String(smallRow.id)"
|
||||
>
|
||||
<a-row>
|
||||
<a-col :lg="6" :md="6" :xs="24">
|
||||
<a-form-item label="DNN/APN" name="dnn" :validateTrigger="[]" :required="true"
|
||||
:label-col="{ span: 12 }">
|
||||
<a-form-item
|
||||
label="DNN/APN"
|
||||
name="dnn"
|
||||
:validateTrigger="[]"
|
||||
:required="true"
|
||||
:label-col="{ span: 12 }"
|
||||
>
|
||||
<a-input v-model:value="smallRow.dnn" allow-clear></a-input>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="8" :md="8" :xs="24">
|
||||
<a-form-item label="Static IP" name="smStaticIp" :label-col="{ span: 5 }">
|
||||
<a-input v-model:value="smallRow.smStaticIp" allow-clear></a-input>
|
||||
<a-form-item
|
||||
label="Static IP"
|
||||
name="smStaticIp"
|
||||
:label-col="{ span: 5 }"
|
||||
>
|
||||
<a-input
|
||||
v-model:value="smallRow.smStaticIp"
|
||||
allow-clear
|
||||
></a-input>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="8" :md="8" :xs="24">
|
||||
<a-form-item label="Routing Behind MS IP" style="margin-left:10px ;" name="msIp">
|
||||
<a-form-item
|
||||
label="Routing Behind MS IP"
|
||||
style="margin-left: 10px"
|
||||
name="msIp"
|
||||
>
|
||||
<a-input v-model:value="smallRow.msIp" allow-clear></a-input>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="2" :md="2" :xs="24" v-if="smallIndex !== 0">
|
||||
<a-tooltip title="Delete DNN">
|
||||
<a-button danger shape="circle" @click="delDNN(smallIndex, row.id)" style="margin-left:10px ;">
|
||||
<a-button
|
||||
danger
|
||||
shape="circle"
|
||||
@click="delDNN(smallIndex, row.id)"
|
||||
style="margin-left: 10px"
|
||||
>
|
||||
<template #icon><close-square-outlined /></template>
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
@@ -1539,7 +1742,11 @@ onMounted(() => {
|
||||
</template>
|
||||
<a-row>
|
||||
<a-col :lg="24" :md="24" :xs="24">
|
||||
<a-form-item label="5GC Flag" name="cnFlag" :help="t('views.neUser.sub.cnFlag')">
|
||||
<a-form-item
|
||||
label="5GC Flag"
|
||||
name="cnFlag"
|
||||
:help="t('views.neUser.sub.cnFlag')"
|
||||
>
|
||||
<a-select v-model:value="modalState.from.cnType">
|
||||
<a-select-option value="3">
|
||||
{{ t('views.neUser.sub.enable') }}
|
||||
@@ -1551,44 +1758,71 @@ onMounted(() => {
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="24" :md="24" :xs="24">
|
||||
<a-form-item label="5G Subscribed UE AMBR Template" name="ambr"
|
||||
v-bind="modalStateFrom.validateInfos.ambr">
|
||||
<a-input v-model:value="modalState.from.ambr" allow-clear :maxlength="50">
|
||||
<a-form-item
|
||||
label="5G Subscribed UE AMBR Template"
|
||||
name="ambr"
|
||||
v-bind="modalStateFrom.validateInfos.ambr"
|
||||
>
|
||||
<a-input
|
||||
v-model:value="modalState.from.ambr"
|
||||
allow-clear
|
||||
:maxlength="50"
|
||||
>
|
||||
<template #prefix>
|
||||
<a-tooltip placement="topLeft">
|
||||
<template #title>
|
||||
{{ t('views.neUser.sub.inputTip', { num: '50' }) }}
|
||||
</template>
|
||||
<InfoCircleOutlined style="opacity: 0.45; color: inherit" />
|
||||
<InfoCircleOutlined
|
||||
style="opacity: 0.45; color: inherit"
|
||||
/>
|
||||
</a-tooltip>
|
||||
</template>
|
||||
</a-input>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="24" :md="24" :xs="24">
|
||||
<a-form-item label="5G Subscribed SNSSAIs Template" name="nssai"
|
||||
v-bind="modalStateFrom.validateInfos.nssai">
|
||||
<a-input v-model:value="modalState.from.nssai" allow-clear :maxlength="50">
|
||||
<a-form-item
|
||||
label="5G Subscribed SNSSAIs Template"
|
||||
name="nssai"
|
||||
v-bind="modalStateFrom.validateInfos.nssai"
|
||||
>
|
||||
<a-input
|
||||
v-model:value="modalState.from.nssai"
|
||||
allow-clear
|
||||
:maxlength="50"
|
||||
>
|
||||
<template #prefix>
|
||||
<a-tooltip placement="topLeft">
|
||||
<template #title>
|
||||
{{ t('views.neUser.sub.inputTip', { num: '50' }) }}
|
||||
</template>
|
||||
<InfoCircleOutlined style="opacity: 0.45; color: inherit" />
|
||||
<InfoCircleOutlined
|
||||
style="opacity: 0.45; color: inherit"
|
||||
/>
|
||||
</a-tooltip>
|
||||
</template>
|
||||
</a-input>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="24" :md="24" :xs="24">
|
||||
<a-form-item label="5G Subscribed SMF Selection Data Template" name="smfSel">
|
||||
<a-input v-model:value="modalState.from.smfSel" allow-clear :maxlength="50">
|
||||
<a-form-item
|
||||
label="5G Subscribed SMF Selection Data Template"
|
||||
name="smfSel"
|
||||
>
|
||||
<a-input
|
||||
v-model:value="modalState.from.smfSel"
|
||||
allow-clear
|
||||
:maxlength="50"
|
||||
>
|
||||
<template #prefix>
|
||||
<a-tooltip placement="topLeft">
|
||||
<template #title>
|
||||
{{ t('views.neUser.sub.inputTip', { num: '50' }) }}
|
||||
</template>
|
||||
<InfoCircleOutlined style="opacity: 0.45; color: inherit" />
|
||||
<InfoCircleOutlined
|
||||
style="opacity: 0.45; color: inherit"
|
||||
/>
|
||||
</a-tooltip>
|
||||
</template>
|
||||
</a-input>
|
||||
@@ -1596,48 +1830,77 @@ onMounted(() => {
|
||||
</a-col>
|
||||
<a-col :lg="24" :md="24" :xs="24">
|
||||
<a-form-item label="5G Forbidden Areas Template" name="arfb">
|
||||
<a-input v-model:value="modalState.from.arfb" allow-clear :maxlength="50">
|
||||
<a-input
|
||||
v-model:value="modalState.from.arfb"
|
||||
allow-clear
|
||||
:maxlength="50"
|
||||
>
|
||||
<template #prefix>
|
||||
<a-tooltip placement="topLeft">
|
||||
<template #title>
|
||||
{{ t('views.neUser.sub.arfbTip') }}
|
||||
</template>
|
||||
<InfoCircleOutlined style="opacity: 0.45; color: inherit" />
|
||||
<InfoCircleOutlined
|
||||
style="opacity: 0.45; color: inherit"
|
||||
/>
|
||||
</a-tooltip>
|
||||
</template>
|
||||
</a-input>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="24" :md="24" :xs="24">
|
||||
<a-form-item label="5G CAG Template" name="cag" v-bind="modalStateFrom.validateInfos.cag">
|
||||
<a-input v-model:value="modalState.from.cag" allow-clear :maxlength="50">
|
||||
<a-form-item
|
||||
label="5G CAG Template"
|
||||
name="cag"
|
||||
v-bind="modalStateFrom.validateInfos.cag"
|
||||
>
|
||||
<a-input
|
||||
v-model:value="modalState.from.cag"
|
||||
allow-clear
|
||||
:maxlength="50"
|
||||
>
|
||||
<template #prefix>
|
||||
<a-tooltip placement="topLeft">
|
||||
<template #title>
|
||||
{{ t('views.neUser.sub.inputTip', { num: '50' }) }}
|
||||
</template>
|
||||
<InfoCircleOutlined style="opacity: 0.45; color: inherit" />
|
||||
<InfoCircleOutlined
|
||||
style="opacity: 0.45; color: inherit"
|
||||
/>
|
||||
</a-tooltip>
|
||||
</template>
|
||||
</a-input>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="24" :md="24" :xs="24">
|
||||
<a-form-item label="5G Service Area Restriction Template" name="sar">
|
||||
<a-input v-model:value="modalState.from.sar" allow-clear :maxlength="50">
|
||||
<a-form-item
|
||||
label="5G Service Area Restriction Template"
|
||||
name="sar"
|
||||
>
|
||||
<a-input
|
||||
v-model:value="modalState.from.sar"
|
||||
allow-clear
|
||||
:maxlength="50"
|
||||
>
|
||||
<template #prefix>
|
||||
<a-tooltip placement="topLeft">
|
||||
<template #title>
|
||||
{{ t('views.neUser.sub.sarTip') }}
|
||||
</template>
|
||||
<InfoCircleOutlined style="opacity: 0.45; color: inherit" />
|
||||
<InfoCircleOutlined
|
||||
style="opacity: 0.45; color: inherit"
|
||||
/>
|
||||
</a-tooltip>
|
||||
</template>
|
||||
</a-input>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="24" :md="24" :xs="24">
|
||||
<a-form-item label="5G MICO Mode" name="mico" :help="t('views.neUser.sub.micoTip')">
|
||||
<a-form-item
|
||||
label="5G MICO Mode"
|
||||
name="mico"
|
||||
:help="t('views.neUser.sub.micoTip')"
|
||||
>
|
||||
<a-select v-model:value="modalState.from.mico">
|
||||
<a-select-option value="1">
|
||||
{{ t('views.neUser.sub.enable') }}
|
||||
@@ -1660,14 +1923,21 @@ onMounted(() => {
|
||||
</a-col>
|
||||
<a-col :lg="24" :md="24" :xs="24">
|
||||
<a-form-item label="5G UE Usage Type" name="ueUsageType">
|
||||
<a-input-number v-model:value="modalState.from.ueUsageType" style="width: 100%" :min="0" :max="127"
|
||||
placeholder="0 ~ 127">
|
||||
<a-input-number
|
||||
v-model:value="modalState.from.ueUsageType"
|
||||
style="width: 100%"
|
||||
:min="0"
|
||||
:max="127"
|
||||
placeholder="0 ~ 127"
|
||||
>
|
||||
<template #prefix>
|
||||
<a-tooltip placement="topLeft">
|
||||
<template #title>
|
||||
{{ t('views.neUser.sub.ueTypeTip') }}
|
||||
</template>
|
||||
<InfoCircleOutlined style="opacity: 0.45; color: inherit" />
|
||||
<InfoCircleOutlined
|
||||
style="opacity: 0.45; color: inherit"
|
||||
/>
|
||||
</a-tooltip>
|
||||
</template>
|
||||
</a-input-number>
|
||||
@@ -1675,14 +1945,21 @@ onMounted(() => {
|
||||
</a-col>
|
||||
<a-col :lg="24" :md="24" :xs="24">
|
||||
<a-form-item label="5G RFSP Index" name="rfspIndex">
|
||||
<a-input-number v-model:value="modalState.from.rfspIndex" style="width: 100%" :min="0" :max="127"
|
||||
placeholder="0 ~ 127">
|
||||
<a-input-number
|
||||
v-model:value="modalState.from.rfspIndex"
|
||||
style="width: 100%"
|
||||
:min="0"
|
||||
:max="127"
|
||||
placeholder="0 ~ 127"
|
||||
>
|
||||
<template #prefix>
|
||||
<a-tooltip placement="topLeft">
|
||||
<template #title>
|
||||
{{ t('views.neUser.sub.rfspTip') }}
|
||||
</template>
|
||||
<InfoCircleOutlined style="opacity: 0.45; color: inherit" />
|
||||
<InfoCircleOutlined
|
||||
style="opacity: 0.45; color: inherit"
|
||||
/>
|
||||
</a-tooltip>
|
||||
</template>
|
||||
</a-input-number>
|
||||
@@ -1697,7 +1974,11 @@ onMounted(() => {
|
||||
</template>
|
||||
<a-row>
|
||||
<a-col :lg="24" :md="24" :xs="24">
|
||||
<a-form-item label="4G EPS Flag" name="epsFlag" :help="t('views.neUser.sub.epsFlagTip')">
|
||||
<a-form-item
|
||||
label="4G EPS Flag"
|
||||
name="epsFlag"
|
||||
:help="t('views.neUser.sub.epsFlagTip')"
|
||||
>
|
||||
<a-select v-model:value="modalState.from.epsFlag">
|
||||
<a-select-option value="1">
|
||||
{{ t('views.neUser.sub.enable') }}
|
||||
@@ -1709,15 +1990,24 @@ onMounted(() => {
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="24" :md="24" :xs="24">
|
||||
<a-form-item label="4G EPS User Template Name" name="epstpl"
|
||||
v-bind="modalStateFrom.validateInfos.epstpl">
|
||||
<a-input v-model:value="modalState.from.epstpl" allow-clear :maxlength="50">
|
||||
<a-form-item
|
||||
label="4G EPS User Template Name"
|
||||
name="epstpl"
|
||||
v-bind="modalStateFrom.validateInfos.epstpl"
|
||||
>
|
||||
<a-input
|
||||
v-model:value="modalState.from.epstpl"
|
||||
allow-clear
|
||||
:maxlength="50"
|
||||
>
|
||||
<template #prefix>
|
||||
<a-tooltip placement="topLeft">
|
||||
<template #title>
|
||||
{{ t('views.neUser.sub.inputTip', { num: '50' }) }}
|
||||
</template>
|
||||
<InfoCircleOutlined style="opacity: 0.45; color: inherit" />
|
||||
<InfoCircleOutlined
|
||||
style="opacity: 0.45; color: inherit"
|
||||
/>
|
||||
</a-tooltip>
|
||||
</template>
|
||||
</a-input>
|
||||
@@ -1726,14 +2016,20 @@ onMounted(() => {
|
||||
</a-row>
|
||||
<a-row>
|
||||
<a-col :lg="24" :md="24" :xs="24">
|
||||
<a-form-item label="4G Static IP" v-bind="modalStateFrom.validateInfos.staticIp" name="staticIp">
|
||||
<a-form-item
|
||||
label="4G Static IP"
|
||||
v-bind="modalStateFrom.validateInfos.staticIp"
|
||||
name="staticIp"
|
||||
>
|
||||
<a-input v-model:value="modalState.from.staticIp" allow-clear>
|
||||
<template #prefix>
|
||||
<a-tooltip placement="topLeft">
|
||||
<template #title>
|
||||
{{ t('views.neUser.sub.staticIpTip') }}
|
||||
</template>
|
||||
<InfoCircleOutlined style="opacity: 0.45; color: inherit" />
|
||||
<InfoCircleOutlined
|
||||
style="opacity: 0.45; color: inherit"
|
||||
/>
|
||||
</a-tooltip>
|
||||
</template>
|
||||
</a-input>
|
||||
@@ -1753,33 +2049,73 @@ onMounted(() => {
|
||||
</a-input>
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item label="4G APN Context List" name="apnContext" :help="t('views.neUser.sub.apnContextTip')">
|
||||
<a-form-item
|
||||
label="4G APN Context List"
|
||||
name="apnContext"
|
||||
:help="t('views.neUser.sub.apnContextTip')"
|
||||
>
|
||||
<a-input-group compact>
|
||||
<a-input-number v-for="(_, i) in modalState.from.apnContext" :key="i" :title="i" style="width: 16.5%"
|
||||
:min="0" :max="99" v-model:value="modalState.from.apnContext[i]"></a-input-number>
|
||||
<a-input-number
|
||||
v-for="(_, i) in modalState.from.apnContext"
|
||||
:key="i"
|
||||
:title="i"
|
||||
style="width: 16.5%"
|
||||
:min="0"
|
||||
:max="99"
|
||||
v-model:value="modalState.from.apnContext[i]"
|
||||
></a-input-number>
|
||||
</a-input-group>
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item label="4G EPS ODB" name="epsOdb" v-bind="modalStateFrom.validateInfos.epsOdb">
|
||||
<a-tooltip :title="t('views.neUser.sub.epsOdbTip')" placement="topLeft">
|
||||
<a-select v-model:value="modalState.from.epsOdb" mode="multiple" style="width: 100%"
|
||||
placeholder="Please select" :options="modalStateFromOption.odbJson" @change="">
|
||||
<a-form-item
|
||||
label="4G EPS ODB"
|
||||
name="epsOdb"
|
||||
v-bind="modalStateFrom.validateInfos.epsOdb"
|
||||
>
|
||||
<a-tooltip
|
||||
:title="t('views.neUser.sub.epsOdbTip')"
|
||||
placement="topLeft"
|
||||
>
|
||||
<a-select
|
||||
v-model:value="modalState.from.epsOdb"
|
||||
mode="multiple"
|
||||
style="width: 100%"
|
||||
placeholder="Please select"
|
||||
:options="modalStateFromOption.odbJson"
|
||||
@change=""
|
||||
>
|
||||
</a-select>
|
||||
</a-tooltip>
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item label="4G HPLMN ODB" name="hplmnOdb">
|
||||
<a-tooltip :title="t('views.neUser.sub.hplmnOdbTip')" placement="topLeft">
|
||||
<a-select v-model:value="modalState.from.hplmnOdb" mode="multiple" style="width: 100%"
|
||||
:options="modalStateFromOption.hplmnOdb" @change="">
|
||||
<a-tooltip
|
||||
:title="t('views.neUser.sub.hplmnOdbTip')"
|
||||
placement="topLeft"
|
||||
>
|
||||
<a-select
|
||||
v-model:value="modalState.from.hplmnOdb"
|
||||
mode="multiple"
|
||||
style="width: 100%"
|
||||
:options="modalStateFromOption.hplmnOdb"
|
||||
@change=""
|
||||
>
|
||||
</a-select>
|
||||
</a-tooltip>
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item label="4G Access Restriction Data" name="ard">
|
||||
<a-tooltip :title="t('views.neUser.sub.ardTip')" placement="topLeft">
|
||||
<a-select v-model:value="modalState.from.ard" mode="multiple" style="width: 100%"
|
||||
:options="modalStateFromOption.ardJson" @change="">
|
||||
<a-tooltip
|
||||
:title="t('views.neUser.sub.ardTip')"
|
||||
placement="topLeft"
|
||||
>
|
||||
<a-select
|
||||
v-model:value="modalState.from.ard"
|
||||
mode="multiple"
|
||||
style="width: 100%"
|
||||
:options="modalStateFromOption.ardJson"
|
||||
@change=""
|
||||
>
|
||||
</a-select>
|
||||
</a-tooltip>
|
||||
</a-form-item>
|
||||
@@ -1789,15 +2125,36 @@ onMounted(() => {
|
||||
</ProModal>
|
||||
|
||||
<!-- 批量删除框 -->
|
||||
<ProModal :drag="true" :destroyOnClose="true" style="top: 0px" :keyboard="false" :mask-closable="false"
|
||||
:open="modalState.openByBatchDel" :title="modalState.title" :confirm-loading="modalState.confirmLoading"
|
||||
@ok="fnBatchDelModalOk" @cancel="fnBatchDelModalCancel">
|
||||
<a-form name="modalStateBatchDelFrom" layout="horizontal" :label-col="{ span: 6 }" :labelWrap="true">
|
||||
<ProModal
|
||||
:drag="true"
|
||||
:destroyOnClose="true"
|
||||
style="top: 0px"
|
||||
:keyboard="false"
|
||||
:mask-closable="false"
|
||||
:open="modalState.openByBatchDel"
|
||||
:title="modalState.title"
|
||||
:confirm-loading="modalState.confirmLoading"
|
||||
@ok="fnBatchDelModalOk"
|
||||
@cancel="fnBatchDelModalCancel"
|
||||
>
|
||||
<a-form
|
||||
name="modalStateBatchDelFrom"
|
||||
layout="horizontal"
|
||||
:label-col="{ span: 8 }"
|
||||
:labelWrap="true"
|
||||
>
|
||||
<a-row>
|
||||
<a-col :lg="24" :md="24" :xs="24">
|
||||
<a-form-item :label="t('views.neUser.sub.startIMSI')" name="imsi"
|
||||
v-bind="modalStateBatchDelFrom.validateInfos.imsi">
|
||||
<a-input v-model:value="modalState.BatchDelForm.imsi" allow-clear :maxlength="15">
|
||||
<a-form-item
|
||||
:label="t('views.neUser.sub.startIMSI')"
|
||||
name="imsi"
|
||||
v-bind="modalStateBatchDelFrom.validateInfos.imsi"
|
||||
>
|
||||
<a-input
|
||||
v-model:value="modalState.BatchDelForm.imsi"
|
||||
allow-clear
|
||||
:maxlength="15"
|
||||
>
|
||||
<template #prefix>
|
||||
<a-tooltip placement="topLeft">
|
||||
<template #title>
|
||||
@@ -1813,10 +2170,18 @@ onMounted(() => {
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="24" :md="24" :xs="24">
|
||||
<a-form-item :label="t('views.neUser.sub.numDel')" name="num"
|
||||
v-bind="modalStateBatchDelFrom.validateInfos.num">
|
||||
<a-input-number v-model:value="modalState.BatchDelForm.num" style="width: 100%" :min="1" :max="10000"
|
||||
placeholder="<=10000"></a-input-number>
|
||||
<a-form-item
|
||||
:label="t('views.neUser.sub.numDel')"
|
||||
name="num"
|
||||
v-bind="modalStateBatchDelFrom.validateInfos.num"
|
||||
>
|
||||
<a-input-number
|
||||
v-model:value="modalState.BatchDelForm.num"
|
||||
style="width: 100%"
|
||||
:min="1"
|
||||
:max="10000"
|
||||
placeholder="<=10000"
|
||||
></a-input-number>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
@@ -1824,12 +2189,33 @@ onMounted(() => {
|
||||
</ProModal>
|
||||
|
||||
<!-- 上传导入表格数据文件框 -->
|
||||
<UploadModal :title="uploadImportState.title" :loading="uploadImportState.loading"
|
||||
@upload="fnModalUploadImportUpload" @close="fnModalUploadImportClose" v-model:open="uploadImportState.open"
|
||||
:ext="['.txt']" :size="10">
|
||||
<UploadModal
|
||||
:title="uploadImportState.title"
|
||||
:loading="uploadImportState.loading"
|
||||
@upload="fnModalUploadImportUpload"
|
||||
@close="fnModalUploadImportClose"
|
||||
v-model:open="uploadImportState.open"
|
||||
:ext="['.txt']"
|
||||
:size="10"
|
||||
>
|
||||
<template #default>
|
||||
<a-textarea :disabled="true" :hidden="!uploadImportState.msg" :value="uploadImportState.msg"
|
||||
:auto-size="{ minRows: 2, maxRows: 8 }" style="background-color: transparent; color: rgba(0, 0, 0, 0.85)" />
|
||||
<a-alert
|
||||
:message="uploadImportState.msg"
|
||||
:type="uploadImportState.hasFail ? 'warning' : 'info'"
|
||||
v-show="uploadImportState.msg.length > 0"
|
||||
>
|
||||
<template #action>
|
||||
<a-button
|
||||
size="small"
|
||||
type="link"
|
||||
danger
|
||||
@click="fnModalUploadImportFailReason"
|
||||
v-if="uploadImportState.hasFail"
|
||||
>
|
||||
{{ t('views.neUser.auth.importFail') }}
|
||||
</a-button>
|
||||
</template>
|
||||
</a-alert>
|
||||
</template>
|
||||
</UploadModal>
|
||||
</PageContainer>
|
||||
|
||||
@@ -242,6 +242,13 @@ const statsColumns: TableColumnType<any>[] = [
|
||||
key: 'title',
|
||||
width: '65%',
|
||||
},
|
||||
{
|
||||
title: t('views.perfManage.kpiOverView.totalValue'),
|
||||
dataIndex: 'total',
|
||||
key: 'total',
|
||||
width: '12%',
|
||||
sortDirections: ['ascend', 'descend'],
|
||||
},
|
||||
{
|
||||
title: t('views.perfManage.kpiOverView.avgValue'),
|
||||
dataIndex: 'avg',
|
||||
@@ -356,6 +363,7 @@ function fnGetListTitle() {
|
||||
dataIndex: kpiValue,
|
||||
align: 'left',
|
||||
key: kpiValue,
|
||||
unit: item[`unit`],
|
||||
resizable: true,
|
||||
width: 100,
|
||||
minWidth: 150,
|
||||
@@ -448,16 +456,17 @@ 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,
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -606,7 +615,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,25 +753,42 @@ function wsMessage(res: Record<string, any>) {
|
||||
// 添加一个变量来跟踪当前选中的行
|
||||
const selectedRow = ref<string[]>([]);
|
||||
|
||||
const selectedUnit = ref<string | null>(null);
|
||||
// 添加处理行点击的方法
|
||||
function handleRowClick(record: any) {
|
||||
const index = selectedRow.value.indexOf(record.kpiId);
|
||||
|
||||
console.log(record)
|
||||
// 如果已经选中,取消选中
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -914,50 +940,28 @@ onBeforeUnmount(() => {
|
||||
|
||||
<template>
|
||||
<PageContainer>
|
||||
<a-card
|
||||
v-show="tableState.seached"
|
||||
:bordered="false"
|
||||
:body-style="{ marginBottom: '24px', paddingBottom: 0 }"
|
||||
>
|
||||
<a-card v-show="tableState.seached" :bordered="false" :body-style="{ marginBottom: '24px', paddingBottom: 0 }">
|
||||
<!-- 表格搜索栏 -->
|
||||
<a-form :model="queryParams" name="queryParamsFrom" layout="horizontal">
|
||||
<a-row :gutter="16">
|
||||
<a-col :lg="6" :md="12" :xs="24">
|
||||
<a-form-item name="neType" :label="t('views.ne.common.neType')">
|
||||
<a-cascader
|
||||
v-model:value="state.neType"
|
||||
:options="neCascaderOptions"
|
||||
:allow-clear="false"
|
||||
:placeholder="t('common.selectPlease')"
|
||||
/>
|
||||
<a-cascader v-model:value="state.neType" :options="neCascaderOptions" :allow-clear="false"
|
||||
:placeholder="t('common.selectPlease')" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="10" :md="12" :xs="24">
|
||||
<a-form-item
|
||||
:label="t('views.perfManage.goldTarget.timeFrame')"
|
||||
name="timeFrame"
|
||||
>
|
||||
<a-range-picker
|
||||
v-model:value="queryRangePicker"
|
||||
bordered
|
||||
:allow-clear="false"
|
||||
:show-time="{ format: 'HH:mm:ss' }"
|
||||
format="YYYY-MM-DD HH:mm:ss"
|
||||
value-format="x"
|
||||
:presets="ranges"
|
||||
style="width: 100%"
|
||||
></a-range-picker>
|
||||
<a-form-item :label="t('views.perfManage.goldTarget.timeFrame')" name="timeFrame">
|
||||
<a-range-picker v-model:value="queryRangePicker" bordered :allow-clear="false"
|
||||
:show-time="{ format: 'HH:mm:ss' }" format="YYYY-MM-DD HH:mm:ss" value-format="x" :presets="ranges"
|
||||
style="width: 100%"></a-range-picker>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
|
||||
<a-col :lg="2" :md="12" :xs="24">
|
||||
<a-form-item>
|
||||
<a-space :size="8">
|
||||
<a-button
|
||||
type="primary"
|
||||
:loading="tableState.loading"
|
||||
@click.prevent="fnGetListTitle()"
|
||||
>
|
||||
<a-button type="primary" :loading="tableState.loading" @click.prevent="fnGetListTitle()">
|
||||
<template #icon>
|
||||
<SearchOutlined />
|
||||
</template>
|
||||
@@ -974,11 +978,7 @@ onBeforeUnmount(() => {
|
||||
<!-- 插槽-卡片左侧侧 -->
|
||||
<template #title>
|
||||
<a-space :size="8" align="center">
|
||||
<a-button
|
||||
type="primary"
|
||||
:loading="tableState.loading"
|
||||
@click.prevent="fnChangShowType()"
|
||||
>
|
||||
<a-button type="primary" :loading="tableState.loading" @click.prevent="fnChangShowType()">
|
||||
<template #icon>
|
||||
<AreaChartOutlined />
|
||||
</template>
|
||||
@@ -988,12 +988,8 @@ onBeforeUnmount(() => {
|
||||
: t('views.perfManage.goldTarget.kpiTableTitle')
|
||||
}}
|
||||
</a-button>
|
||||
<a-button
|
||||
type="dashed"
|
||||
:loading="tableState.loading"
|
||||
@click.prevent="fnRecordExport()"
|
||||
v-show="tableState.showTable"
|
||||
>
|
||||
<a-button type="dashed" :loading="tableState.loading" @click.prevent="fnRecordExport()"
|
||||
v-show="tableState.showTable">
|
||||
<template #icon>
|
||||
<ExportOutlined />
|
||||
</template>
|
||||
@@ -1013,12 +1009,8 @@ onBeforeUnmount(() => {
|
||||
</template>
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
<TableColumnsDnd
|
||||
v-if="tableColumns.length > 0"
|
||||
:cache-id="`kpiTarget_${state.neType[0]}`"
|
||||
:columns="tableColumns"
|
||||
v-model:columns-dnd="tableColumnsDnd"
|
||||
></TableColumnsDnd>
|
||||
<TableColumnsDnd v-if="tableColumns.length > 0" :cache-id="`kpiTarget_${state.neType[0]}`"
|
||||
:columns="tableColumns" v-model:columns-dnd="tableColumnsDnd"></TableColumnsDnd>
|
||||
<a-tooltip>
|
||||
<template #title>{{ t('common.sizeText') }}</template>
|
||||
<a-dropdown trigger="click" placement="bottomRight">
|
||||
@@ -1028,10 +1020,7 @@ onBeforeUnmount(() => {
|
||||
</template>
|
||||
</a-button>
|
||||
<template #overlay>
|
||||
<a-menu
|
||||
:selected-keys="[tableState.size as string]"
|
||||
@click="fnTableSize"
|
||||
>
|
||||
<a-menu :selected-keys="[tableState.size as string]" @click="fnTableSize">
|
||||
<a-menu-item key="default">
|
||||
{{ t('common.size.default') }}
|
||||
</a-menu-item>
|
||||
@@ -1060,61 +1049,32 @@ onBeforeUnmount(() => {
|
||||
size="small"
|
||||
/>
|
||||
</a-form-item> -->
|
||||
<a-form-item
|
||||
:label="t('views.perfManage.goldTarget.realTimeData')"
|
||||
name="chartRealTime"
|
||||
>
|
||||
<a-switch
|
||||
:disabled="tableState.loading"
|
||||
v-model:checked="state.chartRealTime"
|
||||
:checked-children="t('common.switch.open')"
|
||||
:un-checked-children="t('common.switch.shut')"
|
||||
@change="fnRealTimeSwitch"
|
||||
size="small"
|
||||
/>
|
||||
<a-form-item :label="t('views.perfManage.goldTarget.realTimeData')" name="chartRealTime">
|
||||
<a-switch :disabled="tableState.loading" v-model:checked="state.chartRealTime"
|
||||
:checked-children="t('common.switch.open')" :un-checked-children="t('common.switch.shut')"
|
||||
@change="fnRealTimeSwitch" size="small" />
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</template>
|
||||
|
||||
<!-- 表格列表 -->
|
||||
<a-table
|
||||
v-show="tableState.showTable"
|
||||
class="table"
|
||||
row-key="id"
|
||||
:columns="tableColumnsDnd"
|
||||
:loading="tableState.loading"
|
||||
:data-source="tableState.data"
|
||||
:size="tableState.size"
|
||||
:pagination="tablePagination"
|
||||
:scroll="{ x: tableColumnsDnd.length * 200, y: 'calc(100vh - 480px)' }"
|
||||
@resizeColumn="(w: number, col: any) => (col.width = w)"
|
||||
:show-expand-column="false"
|
||||
@change="fnTableChange"
|
||||
>
|
||||
<a-table v-show="tableState.showTable" class="table" row-key="id" :columns="tableColumnsDnd"
|
||||
:loading="tableState.loading" :data-source="tableState.data" :size="tableState.size"
|
||||
:pagination="tablePagination" :scroll="{ x: tableColumnsDnd.length * 200, y: 'calc(100vh - 480px)' }"
|
||||
@resizeColumn="(w: number, col: any) => (col.width = w)" :show-expand-column="false" @change="fnTableChange">
|
||||
</a-table>
|
||||
|
||||
<!-- 图表 -->
|
||||
<div style="padding: 24px" v-show="!tableState.showTable">
|
||||
<div
|
||||
ref="kpiChartDom"
|
||||
class="chart-container"
|
||||
style="height: 450px; width: 100%"
|
||||
></div>
|
||||
<div ref="kpiChartDom" class="chart-container" style="height: 450px; width: 100%"></div>
|
||||
|
||||
<div class="table-container">
|
||||
<a-table
|
||||
:columns="statsColumns"
|
||||
:data-source="kpiStats"
|
||||
:pagination="false"
|
||||
:scroll="{ y: 250 }"
|
||||
size="small"
|
||||
:custom-row="
|
||||
record => ({
|
||||
onClick: () => handleRowClick(record),
|
||||
class: selectedRow.includes(record.kpiId) ? 'selected-row' : '',
|
||||
})
|
||||
"
|
||||
>
|
||||
<a-table :columns="statsColumns" :data-source="kpiStats" :pagination="false" :scroll="{ y: 250 }" size="small"
|
||||
:custom-row="record => ({
|
||||
onClick: () => handleRowClick(record),
|
||||
class: selectedRow.includes(record.kpiId) ? 'selected-row' : '',
|
||||
})
|
||||
">
|
||||
<template #headerCell="{ column }">
|
||||
<template v-if="column.key === 'total'">
|
||||
<span>
|
||||
@@ -1169,6 +1129,14 @@ onBeforeUnmount(() => {
|
||||
</span>
|
||||
</template>
|
||||
</template>
|
||||
<template #bodyCell="{ column, record }">
|
||||
<template v-if="column.key === 'avg'">
|
||||
<span v-if="record.unit !== '%'">-</span>
|
||||
</template>
|
||||
<template v-if="column.key === 'total'">
|
||||
<span v-if="record.unit == '%'">-</span>
|
||||
</template>
|
||||
</template>
|
||||
</a-table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -131,6 +131,9 @@ type TabeStateType = {
|
||||
selectedRowKeys: (string | number)[];
|
||||
};
|
||||
|
||||
//是否显示type框
|
||||
const drawerVisible = ref(true);
|
||||
|
||||
/**表格状态 */
|
||||
let tableState: TabeStateType = reactive({
|
||||
loading: false,
|
||||
@@ -502,9 +505,11 @@ onMounted(() => {
|
||||
message.error(t('views.system.dictData.typeDataErr'), 3);
|
||||
}
|
||||
});
|
||||
drawerVisible.value = true;
|
||||
} else {
|
||||
// 获取列表数据
|
||||
fnGetList();
|
||||
drawerVisible.value = false;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
@@ -881,7 +886,7 @@ onMounted(() => {
|
||||
default-value="sys_oper_type"
|
||||
:placeholder="t('common.selectPlease')"
|
||||
:options="dict.sysDictType"
|
||||
:disabled="true"
|
||||
:disabled="drawerVisible"
|
||||
>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
|
||||
@@ -161,13 +161,13 @@ watchEffect(() => {
|
||||
item.number === props.selectedFrame
|
||||
? 'blue'
|
||||
: item.bg
|
||||
? `#${Number(item.bg).toString(16).padStart(6, '0')}`
|
||||
? `#${Number(item.bg).toString(16)}`
|
||||
: '',
|
||||
color:
|
||||
item.number === props.selectedFrame
|
||||
? 'white'
|
||||
: item.fg
|
||||
? `#${Number(item.fg).toString(16).padStart(6, '0')}`
|
||||
? `#${Number(item.fg).toString(16)}`
|
||||
: '',
|
||||
}"
|
||||
@click="onSelectedFrame(item.number)"
|
||||
@@ -250,8 +250,8 @@ watchEffect(() => {
|
||||
}
|
||||
.thead-item:nth-child(5),
|
||||
.tbody-item:nth-child(5) {
|
||||
flex-basis: 6rem;
|
||||
width: 6rem;
|
||||
flex-basis: 7rem;
|
||||
width: 7rem;
|
||||
}
|
||||
.thead-item:nth-child(6),
|
||||
.tbody-item:nth-child(6) {
|
||||
|
||||
Reference in New Issue
Block a user