Merge branch 'main-v2' into lichang

This commit is contained in:
TsMask
2025-06-26 17:30:28 +08:00
12 changed files with 574 additions and 59 deletions

View File

@@ -1,5 +1,11 @@
# 版本发布日志 # 版本发布日志
## 2.2506.3-20250620
- 新增 UDM签约cnType新增可选1仅5G/2仅4G
- 新增 给AMF/MME对应的IMEI白名单添加批量导入和批量删除功能
- 新增 UDM voup/ims导入失败文件下载
## 2.2506.2-20250613 ## 2.2506.2-20250613
- 修复 数值控件属性maxlength拼写错误 - 修复 数值控件属性maxlength拼写错误

Binary file not shown.

View File

@@ -71,13 +71,16 @@ export function batchAddUDMVolteIMS(data: Record<string, any>, num: number) {
/** /**
* UDMVolteIMS用户删除 * UDMVolteIMS用户删除
* @param data 签约对象 * @param neId 网元ID
* @param imsi_msisdn IMSI/MSISDN
* @param tag 标签 0-voip 1-volte
* @returns object * @returns object
*/ */
export function delUDMVolteIMS(neId: string, imsi: string) { export function delUDMVolteIMS(neId: string, imsi_msisdn: string, tag: string) {
return request({ return request({
url: `/neData/udm/volte-ims/${neId}/${imsi}`, url: `/neData/udm/volte-ims/${neId}/${imsi_msisdn}`,
method: 'DELETE', method: 'DELETE',
params: { volte: tag },
timeout: 180_000, timeout: 180_000,
}); });
} }
@@ -87,12 +90,19 @@ export function delUDMVolteIMS(neId: string, imsi: string) {
* @param neId 网元ID * @param neId 网元ID
* @param imsi IMSI * @param imsi IMSI
* @param num 数量 * @param num 数量
* @param tag 标签 0-voip 1-volte
* @returns object * @returns object
*/ */
export function batchDelUDMVolteIMS(neId: string, imsi: string, num: number) { export function batchDelUDMVolteIMS(
neId: string,
imsi: string,
num: number,
tag: string
) {
return request({ return request({
url: `/neData/udm/volte-ims/${neId}/${imsi}/${num}`, url: `/neData/udm/volte-ims/${neId}/${imsi}/${num}`,
method: 'DELETE', method: 'DELETE',
params: { volte: tag },
timeout: 180_000, timeout: 180_000,
}); });
} }

View File

@@ -877,6 +877,10 @@ export default {
rfspTip:'RFSP index, in NG-RAN, the index of a specific RRM configuration, parameter between 0 and 127', rfspTip:'RFSP index, in NG-RAN, the index of a specific RRM configuration, parameter between 0 and 127',
ueTypeTip: 'Operator-defined subscriber UE Usage Type, integer, parameter between 0 and 127', ueTypeTip: 'Operator-defined subscriber UE Usage Type, integer, parameter between 0 and 127',
cnFlag: 'Whether to enable 5G Core Network service', cnFlag: 'Whether to enable 5G Core Network service',
cnFlag0: 'No Access Allowed',
cnFlag1: 'Access Only 5G',
cnFlag2: 'Access Only 4G',
cnFlag3: 'Access 4G/5G',
epsFlagTip: 'Whether to enable 4G EPS service', epsFlagTip: 'Whether to enable 4G EPS service',
contextIdTip: 'To sign up for an APN Context ID, you must select it from the APN Context list.', contextIdTip: 'To sign up for an APN Context ID, you must select it from the APN Context list.',
apnContextTip: 'The list of APNs available to the phone, up to six, is defined in the HSS.', apnContextTip: 'The list of APNs available to the phone, up to six, is defined in the HSS.',

View File

@@ -877,6 +877,10 @@ export default {
rfspTip:'RFSP 索引,在 NG-RAN 中,特定 RRM 配置的索引,参数介于0到127之间', rfspTip:'RFSP 索引,在 NG-RAN 中,特定 RRM 配置的索引,参数介于0到127之间',
ueTypeTip: '运营商定义的用户 UE Usage Type整型参数介于0到127之间', ueTypeTip: '运营商定义的用户 UE Usage Type整型参数介于0到127之间',
cnFlag: '是否开启 5G Core Network 服务', cnFlag: '是否开启 5G Core Network 服务',
cnFlag0: '不允许接入',
cnFlag1: '只能接入 5G',
cnFlag2: '只能接入 4G',
cnFlag3: '允许接入 4G/5G',
epsFlagTip: '是否开启 4G EPS 服务', epsFlagTip: '是否开启 4G EPS 服务',
contextIdTip: '签约APN 上下文ID必须从APN Context list 中选择。', contextIdTip: '签约APN 上下文ID必须从APN Context list 中选择。',
apnContextTip: '手机可用的APN列表最多六个在HSS中定义。', apnContextTip: '手机可用的APN列表最多六个在HSS中定义。',

View File

@@ -0,0 +1,85 @@
import { delNeConfigData } from '@/api/ne/neConfig';
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
import { message } from 'ant-design-vue';
import { reactive, toRaw } from 'vue';
/**
* 批量删除array
* @param param 父级传入 { t, neTypeSelect, fnActiveConfigNode }
* @returns
*/
export default function useArrayBatch({
t,
neTypeSelect,
fnActiveConfigNode,
}: any) {
/**状态属性 */
const batchState = reactive({
open: false,
loading: false, //批量删除
paramName: '',
startIndex: 1,
num: 1,
});
/**对话框表格信息导入弹出窗口 */
function modalBatchOpen(paramName: string) {
batchState.paramName = paramName;
batchState.open = true;
}
function modalBatchClose() {
if (batchState.loading) {
message.error({
content: 'Delete is in progress, please wait for it to complete',
duration: 3,
});
return;
}
batchState.open = false;
batchState.loading = false;
batchState.startIndex = 1;
batchState.num = 1;
fnActiveConfigNode('#');
}
async function modalBatchOk() {
let okNum = 0;
let failNum = 0;
const endIndex = batchState.startIndex + batchState.num - 1;
for (let i = endIndex; i >= batchState.startIndex; i--) {
const res = await delNeConfigData({
neType: neTypeSelect.value[0],
neId: neTypeSelect.value[1],
paramName: batchState.paramName,
loc: `${i}`,
});
if (res.code === RESULT_CODE_SUCCESS) {
okNum++;
} else {
failNum++;
break;
}
}
if (okNum > 0) {
message.success({
content: `Successfully deleted ${okNum} items`,
duration: 3,
});
}
if (failNum > 0) {
message.error({
content: `Delete failed, please check the index range`,
duration: 3,
});
}
modalBatchClose();
}
return {
batchState,
modalBatchOpen,
modalBatchClose,
modalBatchOk,
};
}

View File

@@ -0,0 +1,205 @@
import { addNeConfigData, editNeConfigData } from '@/api/ne/neConfig';
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
import { readSheet } from '@/utils/execl-utils';
import { message } from 'ant-design-vue';
import { reactive, toRaw } from 'vue';
import saveAs from 'file-saver';
/**
* 导入文件加array
* @param param 父级传入 { t, neTypeSelect, arrayState, fnActiveConfigNode }
* @returns
*/
export default function useArrayImport({
t,
neTypeSelect,
arrayState,
fnActiveConfigNode,
}: any) {
/**网元导入模板解析 */
const m: Record<string, any> = {
AMF: {
imeiWhitelist: {
filename: 'import_amf_imeiWhitelist_template',
fileetx: '.xlsx',
itemKey: 'imeiPrefixValue',
item: (row: Record<string, any>) => {
return {
imeiPrefixValue: row['IMEI Prefix'],
index: 0,
};
},
},
whitelist: {
filename: 'import_amf_whitelist_template',
fileetx: '.xlsx',
itemKey: 'imsiValue',
item: (row: Record<string, any>) => {
return {
imsiValue: row['IMSI Value'],
imeiValue: row['IMEI Value/Prefix'],
index: 0,
};
},
},
},
MME: {
white_list: {
filename: 'import_mme_imeiWhitelist_template',
fileetx: '.xlsx',
itemKey: 'imei',
item: (row: Record<string, any>) => {
return {
imei: row['IMEI'],
index: 0,
};
},
},
},
};
/**状态属性 */
const importState = reactive({
open: false,
msgArr: [] as string[],
loading: false, //开始导入
itemKey: '', // 解析item的key
item: null as any, // 解析item方法
paramName: '',
filename: '',
fileetx: '',
});
/**对话框表格信息导入弹出窗口 */
function modalImportOpen(neType: string, paramName: string) {
const tmpM = m[neType][paramName];
importState.itemKey = tmpM.itemKey;
importState.item = tmpM.item;
importState.paramName = paramName;
importState.filename = tmpM.filename;
importState.fileetx = tmpM.fileetx;
importState.open = true;
}
function modalImportClose() {
if (importState.loading) {
message.error({
content: 'Import is in progress, please wait for it to complete',
duration: 3,
});
return;
}
importState.open = false;
importState.msgArr = [];
importState.loading = false;
fnActiveConfigNode('#');
}
/**对话框表格信息导入上传 */
async function modalImportUpload(file: File) {
const hide = message.loading(t('common.loading'), 0);
const [neType, neId] = neTypeSelect.value;
importState.msgArr = [];
// 获取最大index
let index = 0;
if (arrayState.columnsData.length <= 0) {
index = 0;
} else {
const last = arrayState.columnsData[arrayState.columnsData.length - 1];
index = last.index.value + 1;
}
const reader = new FileReader();
reader.onload = function (e: any) {
const arrayBuffer = e.target.result;
readSheet(arrayBuffer).then(async rows => {
if (rows.length <= 0) {
hide();
message.error({
content: t('views.neData.baseStation.importDataEmpty'),
duration: 3,
});
return;
}
// 开始导入
importState.loading = true;
for (const row of rows) {
const rowItem = importState.item(row);
const rowKey = rowItem[importState.itemKey];
let result: any = null;
// 检查index是否定义
const has = arrayState.columnsData.find(
(item: any) => item[importState.itemKey].value === rowKey
);
if (has) {
// 已定义则更新
rowItem.index = has.index.value;
result = await editNeConfigData({
neType: neType,
neId: neId,
paramName: importState.paramName,
paramData: rowItem,
loc: `${rowItem.index}`,
});
let msg = `index:${rowItem.index} update fail`;
if (result.code === RESULT_CODE_SUCCESS) {
msg = `index:${rowItem.index} update success`;
}
importState.msgArr.push(msg);
} else {
// 未定义则新增
result = await addNeConfigData({
neType: neType,
neId: neId,
paramName: importState.paramName,
paramData: Object.assign(rowItem, { index }),
loc: `${index}`,
});
let msg = `index:${index} add fail`;
if (result.code === RESULT_CODE_SUCCESS) {
msg = `index:${index} add success`;
index += 1;
}
importState.msgArr.push(msg);
}
}
hide();
importState.loading = false;
});
};
reader.onerror = function (e) {
hide();
console.error('reader file error:', e);
};
reader.readAsArrayBuffer(file);
}
/**对话框表格信息导入模板 */
function modalImportTemplate() {
const hide = message.loading(t('common.loading'), 0);
const baseUrl = import.meta.env.VITE_HISTORY_BASE_URL;
const templateUrl = `${
baseUrl.length === 1 && baseUrl.indexOf('/') === 0
? ''
: baseUrl.indexOf('/') === -1
? '/' + baseUrl
: baseUrl
}/neDataImput`;
saveAs(
`${templateUrl}/${importState.filename}${importState.fileetx}`,
`${importState.filename}_${Date.now()}${importState.fileetx}`
);
hide();
}
return {
importState,
modalImportOpen,
modalImportClose,
modalImportUpload,
modalImportTemplate,
};
}

View File

@@ -12,6 +12,8 @@ import useOptions from './hooks/useOptions';
import useConfigList from './hooks/useConfigList'; import useConfigList from './hooks/useConfigList';
import useConfigArray from './hooks/useConfigArray'; import useConfigArray from './hooks/useConfigArray';
import useConfigArrayChild from './hooks/useConfigArrayChild'; import useConfigArrayChild from './hooks/useConfigArrayChild';
import useArrayImport from './hooks/useArrayImport';
import useArrayBatchDel from './hooks/useArrayBatchDel';
import { getAllNeConfig, getNeConfigData } from '@/api/ne/neConfig'; import { getAllNeConfig, getNeConfigData } from '@/api/ne/neConfig';
const neListStore = useNeStore(); const neListStore = useNeStore();
const { t } = useI18n(); const { t } = useI18n();
@@ -225,10 +227,13 @@ function fnGetNeConfig() {
} else { } else {
paramPerms = ['post', 'put', 'delete']; paramPerms = ['post', 'put', 'delete'];
} }
const title = item.paramDisplay;
// 处理字符串开头特殊字符
item.paramDisplay = title.replace(/[└─]+/, '');
arr.push({ arr.push({
...item, ...item,
children: undefined, children: undefined,
title: item.paramDisplay, title: title,
key: item.paramName, key: item.paramName,
paramPerms, paramPerms,
}); });
@@ -362,6 +367,21 @@ const {
arrayEditClose, arrayEditClose,
}); });
const {
importState,
modalImportOpen,
modalImportClose,
modalImportUpload,
modalImportTemplate,
} = useArrayImport({ t, neTypeSelect, arrayState, fnActiveConfigNode });
const { batchState, modalBatchOpen, modalBatchClose, modalBatchOk } =
useArrayBatchDel({
t,
neTypeSelect,
fnActiveConfigNode,
});
onMounted(() => { onMounted(() => {
// 获取网元网元列表 // 获取网元网元列表
neCascaderOptions.value = neListStore.getNeCascaderOptions.filter( neCascaderOptions.value = neListStore.getNeCascaderOptions.filter(
@@ -428,7 +448,7 @@ onMounted(() => {
<a-card <a-card
size="small" size="small"
:bordered="false" :bordered="false"
:body-style="{ maxHeight: '600px', 'overflow-y': 'auto' }" :body-style="{ maxHeight: '680px', 'overflow-y': 'auto' }"
:loading="treeState.selectLoading" :loading="treeState.selectLoading"
> >
<template #title> <template #title>
@@ -578,7 +598,8 @@ onMounted(() => {
{{ JSON.parse(record['filter'])[text] }} {{ JSON.parse(record['filter'])[text] }}
</template> </template>
<template v-else>{{ `${text}` }}</template> <template v-else>{{ `${text}` }}</template>
&nbsp; <!-- 空格占位 --> &nbsp;
<!-- 空格占位 -->
<EditOutlined <EditOutlined
class="editable-cell__icon" class="editable-cell__icon"
@click="listEdit(record)" @click="listEdit(record)"
@@ -605,7 +626,7 @@ onMounted(() => {
:size="arrayState.size" :size="arrayState.size"
:pagination="tablePagination" :pagination="tablePagination"
:bordered="true" :bordered="true"
:scroll="{ x: arrayState.columnsDnd.length * 200, y: 480 }" :scroll="{ x: arrayState.columnsDnd.length * 200, y: '500px' }"
@resizeColumn="(w:number, col:any) => (col.width = w)" @resizeColumn="(w:number, col:any) => (col.width = w)"
:show-expand-column="false" :show-expand-column="false"
v-model:expanded-row-keys="arrayState.arrayChildExpandKeys" v-model:expanded-row-keys="arrayState.arrayChildExpandKeys"
@@ -628,6 +649,38 @@ onMounted(() => {
:columns="treeState.selectNode.paramPerms.includes('get') ? [...arrayState.columns.filter((s:any)=>s.key !== 'index')] : arrayState.columns" :columns="treeState.selectNode.paramPerms.includes('get') ? [...arrayState.columns.filter((s:any)=>s.key !== 'index')] : arrayState.columns"
v-model:columns-dnd="arrayState.columnsDnd" v-model:columns-dnd="arrayState.columnsDnd"
></TableColumnsDnd> ></TableColumnsDnd>
<!-- 特殊导入删除-->
<template
v-if="
['AMF', 'MME'].includes(neTypeSelect[0]) &&
['white_list', 'imeiWhitelist', 'whitelist'].includes(
treeState.selectNode.paramName
)
"
>
<a-button
@click.prevent="
modalImportOpen(
neTypeSelect[0],
treeState.selectNode.paramName
)
"
size="small"
>
<template #icon><ImportOutlined /></template>
{{ t('common.import') }}
</a-button>
<a-button
danger
@click.prevent="
modalBatchOpen(treeState.selectNode.paramName)
"
size="small"
>
<template #icon><DeleteOutlined /></template>
{{ t('views.neData.common.batchDelText') }}
</a-button>
</template>
</a-space> </a-space>
</template> </template>
@@ -905,6 +958,84 @@ onMounted(() => {
</a-form-item> </a-form-item>
</a-form> </a-form>
</ProModal> </ProModal>
<!-- 上传导入表格数据文件框 -->
<UploadModal
:title="t('common.import')"
@upload="modalImportUpload"
@close="modalImportClose"
v-model:open="importState.open"
: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="modalImportTemplate"
>
{{ t('views.system.user.downloadObj') }}
</a-button>
</a-col>
</a-row>
<a-textarea
:disabled="true"
:hidden="importState.msgArr.length <= 0"
:value="importState.msgArr.join('\r\n')"
:auto-size="{ minRows: 2, maxRows: 8 }"
style="background-color: transparent; color: rgba(0, 0, 0, 0.85)"
/>
</template>
</UploadModal>
<!-- 批量删除框 -->
<ProModal
:drag="true"
:destroyOnClose="true"
:keyboard="false"
:mask-closable="false"
:open="batchState.open"
:title="t('views.neData.common.batchDelText')"
:confirm-loading="batchState.loading"
@ok="modalBatchOk"
@cancel="modalBatchClose"
>
<a-form
name="batchStateForm"
:model="batchState"
layout="horizontal"
:label-col="{ span: 6 }"
:labelWrap="true"
>
<a-row>
<a-col :lg="24" :md="24" :xs="24">
<a-form-item label="Start Index" name="startIndex" required>
<a-input-number
v-model:value="batchState.startIndex"
style="width: 100%"
allow-clear
:min="0"
:maxlength="5"
></a-input-number>
</a-form-item>
</a-col>
<a-col :lg="24" :md="24" :xs="24">
<a-form-item label="Num" name="num" required>
<a-input-number
v-model:value="batchState.num"
style="width: 100%"
:min="1"
:maxlength="5"
placeholder="<=500"
></a-input-number>
</a-form-item>
</a-col>
</a-row>
</a-form>
</ProModal>
</PageContainer> </PageContainer>
</template> </template>

View File

@@ -1668,10 +1668,16 @@ onMounted(() => {
> >
<a-select v-model:value="modalState.from.cnType"> <a-select v-model:value="modalState.from.cnType">
<a-select-option value="3"> <a-select-option value="3">
{{ t('views.neUser.sub.enable') }} {{ t('views.neUser.sub.cnFlag3') }}
</a-select-option>
<a-select-option value="2">
{{ t('views.neUser.sub.cnFlag2') }}
</a-select-option>
<a-select-option value="1">
{{ t('views.neUser.sub.cnFlag1') }}
</a-select-option> </a-select-option>
<a-select-option value="0"> <a-select-option value="0">
{{ t('views.neUser.sub.disable') }} {{ t('views.neUser.sub.cnFlag0') }}
</a-select-option> </a-select-option>
</a-select> </a-select>
</a-form-item> </a-form-item>

View File

@@ -94,7 +94,7 @@ type TabeStateType = {
data: object[]; data: object[];
/**勾选记录 */ /**勾选记录 */
selectedRowKeys: (string | number)[]; selectedRowKeys: (string | number)[];
selectedRowIMSIs: (string | number)[]; selectedRowIMSIs: Record<string, any>[];
}; };
/**表格状态 */ /**表格状态 */
@@ -203,7 +203,13 @@ function fnTableSize({ key }: MenuInfo) {
/**表格多选 */ /**表格多选 */
function fnTableSelectedRowKeys(keys: (string | number)[], rows: any[]) { function fnTableSelectedRowKeys(keys: (string | number)[], rows: any[]) {
tableState.selectedRowKeys = keys; tableState.selectedRowKeys = keys;
tableState.selectedRowIMSIs = rows.map(item => item.imsi); tableState.selectedRowIMSIs = rows.map(item => {
return {
imsi: item.imsi,
msisdn: item.msisdn,
tag: item.tag,
};
});
} }
/**对话框对象信息状态类型 */ /**对话框对象信息状态类型 */
@@ -309,7 +315,12 @@ function fnModalOk() {
result = batchAddUDMVolteIMS(from, from.num); result = batchAddUDMVolteIMS(from, from.num);
} }
if (modalState.type === 'delete') { if (modalState.type === 'delete') {
result = batchDelUDMVolteIMS(from.neId, from.imsi, from.num); result = batchDelUDMVolteIMS(
from.neId,
`${from.imsi}_${from.msisdn}`,
from.num,
from.tag
);
} }
} else { } else {
if (modalState.type === 'add') { if (modalState.type === 'add') {
@@ -375,15 +386,14 @@ function fnModalVisibleByBatch(type: 'delete' | 'add') {
/** /**
* 记录删除 * 记录删除
* @param imsi 网元编号ID * @param id 记录ID
*/ */
function fnRecordDelete(imsi: string) { function fnRecordDelete(id: string) {
const neID = queryParams.neId; const neID = queryParams.neId;
if (!neID) return; if (!neID) return;
let msg = imsi; let msg = id;
if (imsi === '0') { if (id === '0') {
msg = `${tableState.selectedRowIMSIs[0]}... ${tableState.selectedRowIMSIs.length}`; msg = `${tableState.selectedRowIMSIs[0].imsi}... ${tableState.selectedRowIMSIs.length}`;
imsi = tableState.selectedRowIMSIs.join(',');
} }
Modal.confirm({ Modal.confirm({
@@ -391,17 +401,34 @@ function fnRecordDelete(imsi: string) {
content: t('views.neData.udmVolteIMS.delTip', { num: msg }), content: t('views.neData.udmVolteIMS.delTip', { num: msg }),
onOk() { onOk() {
const hide = message.loading(t('common.loading'), 0); const hide = message.loading(t('common.loading'), 0);
delUDMVolteIMS(neID, imsi) let reqArr: any[] = [];
.then(res => { if (id === '0') {
if (res.code === RESULT_CODE_SUCCESS) { const volteArr = tableState.selectedRowIMSIs
message.success(t('common.operateOk'), 3); .filter(item => item.tag == '1')
fnGetList(); .map(item => `${item.imsi}_${item.msisdn}`)
} else { .join(',');
message.error({ if (volteArr.length > 0) {
content: `${res.msg}`, reqArr.push(delUDMVolteIMS(neID, volteArr, '1'));
duration: 3, }
}); const voipArr = tableState.selectedRowIMSIs
} .filter(item => item.tag == '0')
.map(item => `${item.imsi}_${item.msisdn}`)
.join(',');
if (voipArr.length > 0) {
reqArr.push(delUDMVolteIMS(neID, voipArr, '0'));
}
} else {
const record: any = tableState.data.find((item: any) => item.id === id);
if (record) {
reqArr = [
delUDMVolteIMS(neID, `${record.imsi}_${record.msisdn}`, record.tag),
];
}
}
Promise.all(reqArr)
.then(() => {
message.success(t('common.operateOk'), 3);
fnGetList();
}) })
.finally(() => { .finally(() => {
hide(); hide();
@@ -887,7 +914,7 @@ onMounted(() => {
<template #title>{{ t('common.deleteText') }}</template> <template #title>{{ t('common.deleteText') }}</template>
<a-button <a-button
type="link" type="link"
@click.prevent="fnRecordDelete(record.imsi)" @click.prevent="fnRecordDelete(record.id)"
> >
<template #icon> <template #icon>
<DeleteOutlined /> <DeleteOutlined />
@@ -946,36 +973,73 @@ onMounted(() => {
> >
</a-select> </a-select>
</a-form-item> </a-form-item>
<a-form-item
v-if="modalState.from.tag === '1'" <template v-if="modalState.from.tag === '1'">
:label=" <a-form-item
modalState.isBatch ? t('views.neData.common.startIMSI') : 'IMSI' :label="
" modalState.isBatch ? t('views.neData.common.startIMSI') : 'IMSI'
name="imsi" "
v-bind="modalStateFrom.validateInfos.imsi" name="imsi"
> v-bind="modalStateFrom.validateInfos.imsi"
<a-input
v-model:value="modalState.from.imsi"
allow-clear
:maxlength="15"
> >
<template #prefix> <a-input
<a-tooltip placement="topLeft"> v-model:value="modalState.from.imsi"
<template #title> allow-clear
{{ t('views.neData.common.imsiTip') }}<br /> :maxlength="15"
{{ t('views.neData.common.imsiTip1') }}<br /> >
{{ t('views.neData.common.imsiTip2') }}<br /> <template #prefix>
{{ t('views.neData.common.imsiTip3') }} <a-tooltip placement="topLeft">
</template> <template #title>
<InfoCircleOutlined style="opacity: 0.45; color: inherit" /> {{ t('views.neData.common.imsiTip') }}<br />
</a-tooltip> {{ t('views.neData.common.imsiTip1') }}<br />
</template> {{ t('views.neData.common.imsiTip2') }}<br />
</a-input> {{ t('views.neData.common.imsiTip3') }}
</a-form-item> </template>
<InfoCircleOutlined style="opacity: 0.45; color: inherit" />
</a-tooltip>
</template>
</a-input>
</a-form-item>
<a-form-item
:extra="
modalState.from.tag == '0'
? t('views.neData.udmVolteIMS.voipTip')
: ''
"
:label="
modalState.isBatch
? t('views.neData.udmVolteIMS.startMSISDN')
: '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>
{{ t('views.neData.common.msisdn') }}
</template>
<InfoCircleOutlined style="opacity: 0.45; color: inherit" />
</a-tooltip>
</template>
</a-input>
</a-form-item>
</template>
<a-form-item <a-form-item
v-else v-if="modalState.from.tag === '0'"
:extra="
modalState.from.tag == '0'
? t('views.neData.udmVolteIMS.voipTip')
: ''
"
:label=" :label="
modalState.isBatch && modalState.from.tag === '0' modalState.isBatch
? t('views.neData.udmVolteIMS.startMSISDN') ? t('views.neData.udmVolteIMS.startMSISDN')
: 'MSISDN' : 'MSISDN'
" "
@@ -1061,7 +1125,7 @@ onMounted(() => {
: '' : ''
" "
:label=" :label="
modalState.isBatch && modalState.from.tag === '0' modalState.isBatch
? t('views.neData.udmVolteIMS.startMSISDN') ? t('views.neData.udmVolteIMS.startMSISDN')
: 'MSISDN' : 'MSISDN'
" "