Merge remote-tracking branch 'origin/main' into multi-tenant

This commit is contained in:
lai
2024-12-06 18:37:56 +08:00
181 changed files with 6304 additions and 5882 deletions

View File

@@ -11,7 +11,7 @@ VITE_APP_NAME = "Core Network OMC"
VITE_APP_CODE = "OMC"
# 应用版本
VITE_APP_VERSION = "2.241102"
VITE_APP_VERSION = "2.241130"
# 接口基础URL地址-不带/后缀
VITE_API_BASE_URL = "/omc-api"

View File

@@ -11,7 +11,7 @@ VITE_APP_NAME = "Core Network OMC"
VITE_APP_CODE = "OMC"
# 应用版本
VITE_APP_VERSION = "2.241102"
VITE_APP_VERSION = "2.241130"
# 接口基础URL地址-不带/后缀
VITE_API_BASE_URL = "/omc-api"

View File

@@ -5,13 +5,6 @@
- 图标来源 [@ant-design/icons-vue](https://ant.design/components/icon)
- 菜单图标使用自定义 iconfont `font_8d5l8fzk5b87iudi.js`图标文件
## 测试环境
```text
Nginx: http://192.168.2.166:3188/#/index
后端暴露端口: http://192.168.2.166:33030
```
## 程序命令
项目目录下 `.env.[环境]` 文件对应环境的一些配置,启动前请检查文件内是否配置正确。

View File

@@ -16,31 +16,31 @@
"@antv/g6": "~4.8.24",
"@codemirror/lang-javascript": "^6.2.2",
"@codemirror/lang-yaml": "^6.1.1",
"@codemirror/merge": "^6.6.3",
"@codemirror/merge": "^6.7.2",
"@codemirror/theme-one-dark": "^6.1.2",
"@tato30/vue-pdf": "^1.10.0",
"@vueuse/core": "~10.10.1",
"@tato30/vue-pdf": "^1.11.2",
"@vueuse/core": "11.2.0",
"@xterm/addon-fit": "^0.10.0",
"@xterm/xterm": "^5.5.0",
"ant-design-vue": "^3.2.20",
"antdv-pro-layout": "~3.3.5",
"antdv-pro-modal": "^3.1.0",
"ant-design-vue": "^4.2.5",
"antdv-pro-layout": "^4.1.9",
"antdv-pro-modal": "^4.0.5",
"codemirror": "^6.0.1",
"crypto-js": "^4.2.0",
"dayjs": "^1.11.11",
"echarts": "~5.5.0",
"file-saver": "^2.0.5",
"grid-layout-plus": "^1.0.5",
"intl-tel-input": "^23.8.1",
"intl-tel-input": "^24.6.0",
"js-base64": "^3.7.7",
"js-cookie": "^3.0.5",
"localforage": "^1.10.0",
"nprogress": "^0.2.0",
"p-queue": "~8.0.1",
"pinia": "^2.1.7",
"vue": "~3.3.13",
"vue-i18n": "^9.13.1",
"vue-router": "^4.4.0",
"pinia": "2.2.6",
"vue": "^3.5.12",
"vue-i18n": "^10.0.4",
"vue-router": "^4.4.5",
"vue3-smooth-dnd": "^0.0.6",
"xlsx": "~0.18.5"
},
@@ -48,14 +48,14 @@
"@types/crypto-js": "^4.2.2",
"@types/file-saver": "^2.0.7",
"@types/js-cookie": "^3.0.6",
"@types/node": "^18.0.0",
"@types/node": "^22.7.7",
"@types/nprogress": "^0.2.3",
"@vitejs/plugin-vue": "^5.0.5",
"@vitejs/plugin-vue": "^5.1.4",
"less": "^4.2.0",
"typescript": "~5.4.5",
"unplugin-vue-components": "~0.26.0",
"vite": "~5.3.1",
"typescript": "^5.6.3",
"unplugin-vue-components": "^0.27.4",
"vite": "5.4.10",
"vite-plugin-compression": "~0.5.1",
"vue-tsc": "~2.0.22"
"vue-tsc": "^2.1.8"
}
}

View File

@@ -1,7 +1,7 @@
// load the Wiregasm library
importScripts(
'/wiregasm/wiregasm_new.js', // self-compilation es5
'/wiregasm/wiregasm_load.js'
'wiregasm_new.js', // self-compilation es5
'wiregasm_load.js'
// 'https://cdn.jsdelivr.net/npm/@goodtools/wiregasm/dist/wiregasm.js'
);
@@ -16,11 +16,11 @@ const fetchPackages = async () => {
console.log('Fetching packages');
let [wasmBuffer, dataBuffer] = await Promise.all([
await inflateRemoteBuffer(
'/wiregasm/wiregasm.wasm'
'wiregasm.wasm'
// 'https://cdn.jsdelivr.net/npm/@goodtools/wiregasm/dist/wiregasm.wasm'
),
await inflateRemoteBuffer(
'/wiregasm/wiregasm.data'
'wiregasm.data'
// 'https://cdn.jsdelivr.net/npm/@goodtools/wiregasm/dist/wiregasm.data'
),
]);

View File

@@ -1,22 +1,48 @@
<script setup lang="ts">
import { ConfigProvider } from 'ant-design-vue/lib';
import { usePrimaryColor } from '@/hooks/useTheme';
import zhCN from 'ant-design-vue/lib/locale/zh_CN';
import enUS from 'ant-design-vue/lib/locale/en_US';
import { onBeforeMount, ref, watch } from 'vue';
import { message } from 'ant-design-vue/es';
import zhCN from 'ant-design-vue/es/locale/zh_CN';
import enUS from 'ant-design-vue/es/locale/en_US';
import { usePrefersColorScheme, viewTransitionTheme } from 'antdv-pro-layout';
import dayjs from 'dayjs';
import advancedFormat from 'dayjs/plugin/advancedFormat';
import 'dayjs/locale/zh-cn';
import { ref, watch } from 'vue';
import useLayoutStore from '@/store/modules/layout';
import useAppStore from '@/store/modules/app';
import useI18n from '@/hooks/useI18n';
const { t, currentLocale } = useI18n();
const appStore = useAppStore();
const { themeConfig, initPrimaryColor, changeConf } = useLayoutStore();
dayjs.extend(advancedFormat);
dayjs.locale('zh-cn'); // 默认中文
usePrimaryColor(); // 载入用户自定义主题色
// dayjs.locale('zh-cn'); // 默认中文
let locale = ref(enUS); // 国际化初始中文
let locale = ref(zhCN); // 国际化初始中文
// 偏好设置
const colorScheme = usePrefersColorScheme();
watch(
() => colorScheme.value,
themeMode => {
viewTransitionTheme(() => {
changeConf('theme', themeMode);
});
}
);
onBeforeMount(() => {
// 全局message提示
message.config({
top: '100px', // 距离顶部位置100px
duration: 3,
maxCount: 15,
});
initPrimaryColor();
// 输出应用版本号
const appStore = useAppStore();
console.info(
`%c ${t('common.desc')} %c ${appStore.appCode} - ${appStore.appVersion} `,
'color: #fadfa3; background: #030307; padding: 4px 0;',
'color: #030307; background: #fadfa3; padding: 4px 0;'
);
});
// 国际化切换语言
function fnChangeLocale(v: string) {
@@ -37,26 +63,18 @@ fnChangeLocale(currentLocale.value);
watch(currentLocale, val => {
fnChangeLocale(val);
});
// 输出应用版本号
console.info(
`%c ${t('common.title')} %c ${appStore.appCode} - ${appStore.appVersion} `,
'color: #fadfa3; background: #030307; padding: 4px 0;',
'color: #030307; background: #fadfa3; padding: 4px 0;'
);
</script>
<template>
<ConfigProvider :locale="locale">
<a-config-provider :theme="themeConfig" :locale="locale">
<RouterView />
</ConfigProvider>
</a-config-provider>
</template>
<style lang="css">
#app {
height: 100%;
}
body .ant-pro-basicLayout {
display: flex;
flex-direction: column;
@@ -86,56 +104,23 @@ body .ant-pro-basicLayout {
transform: translate(-2em, 0);
}
/**强制改表格边距 */
.ant-table.ant-table-small .ant-table-tbody > tr > td,
.ant-table.ant-table-small .ant-table-thead > tr > th {
padding: 6px !important;
::view-transition-old(root),
::view-transition-new(root) {
animation: none;
mix-blend-mode: normal;
}
/** ==== 表格头按钮区域 S === **/
/* 默认 */
.button-container {
display: flex;
flex-wrap: wrap;
justify-content: flex-start;
align-items: center;
[data-theme='dark']::view-transition-old(root) {
z-index: 1;
}
[data-theme='dark']::view-transition-new(root) {
z-index: 999;
}
.button-container > button,
.button-container > span {
margin-right: 12px;
margin-bottom: 12px;
::view-transition-old(root) {
z-index: 999;
}
.button-container > button:last-child,
.button-container > span:last-child {
margin-right: 0;
::view-transition-new(root) {
z-index: 1;
}
/* 平板端 */
@media (max-width: 992px) {
.button-container {
flex-direction: row;
align-items: flex-start;
align-items: left;
}
.button-container > button,
.button-container > span {
margin-right: 12px;
margin-bottom: 12px;
}
}
/* 手机端 */
@media (max-width: 576px) {
.button-container {
flex-direction: column;
align-items: flex-start;
align-items: left;
}
.button-container > button,
.button-container > span {
margin-right: 0px;
margin-bottom: 12px;
}
}
/** ==== 表格头按钮区域 E === **/
</style>

View File

@@ -23,6 +23,7 @@ export function listUDMAuth(query: Record<string, any>) {
url: '/neData/udm/auth/list',
method: 'get',
params: query,
timeout: 30_000,
});
}

View File

@@ -23,6 +23,7 @@ export function listUDMSub(query: Record<string, any>) {
url: '/neData/udm/sub/list',
method: 'get',
params: query,
timeout: 30_000,
});
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 226 KiB

View File

Before

Width:  |  Height:  |  Size: 70 KiB

After

Width:  |  Height:  |  Size: 70 KiB

1
src/assets/svg/dark.svg Normal file
View File

@@ -0,0 +1 @@
<svg width="1em" height="1em" class="icon-dark" viewBox="0 0 17 17" xmlns="http://www.w3.org/2000/svg" style="vertical-align: -0.125em;color: rgba(255, 255, 255, 0.65);"><g id="Dark-\u9875\u9762-1" stroke="none" stroke-width="1px" fill="none" fill-rule="evenodd"><g id="Dark-\u9ED8\u8BA4" transform="translate(-9.000000, -49.500000)" fill="currentColor" fill-rule="nonzero"><g id="Dark-\u7F16\u7EC4-17" transform="translate(0.000000, 42.500000)"><g id="Dark-moon" transform="translate(9.268811, 7.500000)"><rect id="Dark-\u77E9\u5F62" opacity="0" x="0" y="0" width="16" height="16"></rect><path d="M8,1.33333333 C8.14933333,1.33333333 8.29688889,1.33844444 8.44266667,1.34866666 C8.14755556,1.98422221 8,2.64577777 8,3.33333333 C8,3.96533333 8.12333333,4.56955555 8.37,5.146 C8.61666667,5.72244445 8.94822222,6.21888889 9.36466667,6.63533333 C9.78111112,7.05177777 10.2775556,7.38333332 10.854,7.63 C11.4304444,7.87666668 12.0346667,8.00000001 12.6666667,8 C13.3542222,8 14.0157778,7.85244444 14.6513333,7.55733333 C14.6615556,7.70311111 14.6666667,7.85066667 14.6666667,8 C14.6666667,8.604 14.5868889,9.19422222 14.4273333,9.77066667 C14.2677778,10.3471111 14.0446667,10.8793333 13.758,11.3673333 C13.4713333,11.8553333 13.1233333,12.3042222 12.714,12.714 C12.3046667,13.1237778 11.8557778,13.4717778 11.3673333,13.758 C10.8788889,14.0442222 10.3466667,14.2673333 9.77066667,14.4273333 C9.19466667,14.5873333 8.60444445,14.6671111 8,14.6666685 C7.39555555,14.6662222 6.80533333,14.5864444 6.22933333,14.4273333 C5.65333333,14.2682222 5.1211111,14.0451111 4.63266666,13.758 C4.14422221,13.4708889 3.69533332,13.1228889 3.28599998,12.714 C2.87666665,12.3051111 2.52866665,11.8562222 2.24199998,11.3673333 C1.95533332,10.8784444 1.73222221,10.3462222 1.57266666,9.77066667 C1.4131111,9.19511112 1.33333333,8.6048889 1.33333333,8 C1.33333333,7.3951111 1.4131111,6.80488888 1.57266666,6.22933333 C1.73222221,5.65377778 1.95533332,5.12155555 2.24199998,4.63266666 C2.52866665,4.14377776 2.87666665,3.69488887 3.28599998,3.28599998 C3.69533332,2.8771111 4.14422221,2.5291111 4.63266666,2.24199998 C5.1211111,1.95488887 5.65333333,1.73177776 6.22933333,1.57266666 C6.80533333,1.41355555 7.39555555,1.33377778 8,1.33333333 Z M6.68733333,2.828 C6.11444444,2.97377778 5.58066667,3.20977778 5.086,3.536 C4.59133333,3.86222222 4.166,4.24933333 3.81,4.69733333 C3.454,5.14533333 3.17444444,5.65488889 2.97133333,6.226 C2.76822221,6.79711111 2.66666666,7.38822222 2.66666666,7.99933333 C2.66666666,8.72155555 2.80733332,9.41155555 3.08866666,10.0693333 C3.36999999,10.7271111 3.74933332,11.2948889 4.22666666,11.7726667 C4.70399999,12.2504444 5.27177777,12.6297778 5.92999998,12.9106667 C6.5882222,13.1915556 7.2782222,13.3322222 7.99999998,13.3326667 C8.6111111,13.3326667 9.20222221,13.2311111 9.77333331,13.028 C10.3444444,12.8248889 10.854,12.5453333 11.302,12.1893333 C11.75,11.8333333 12.1371111,11.408 12.4633333,10.9133333 C12.7895555,10.4186666 13.0255555,9.88488887 13.1713333,9.31199998 C13.022,9.32577777 12.8535555,9.33266666 12.666,9.33266666 C11.8535555,9.33266666 11.0775555,9.17377777 10.338,8.85599998 C9.59844443,8.5382222 8.96044443,8.11111109 8.42399998,7.57466666 C7.88755554,7.03822222 7.46044443,6.40022222 7.14266666,5.66066666 C6.82488889,4.92111109 6.66599999,4.14511109 6.66599998,3.33266666 C6.66599998,3.1451111 6.67288888,2.97666666 6.68666666,2.82733333 L6.68733333,2.828 Z" id="Dark-\u5F62\u72B6"></path></g></g></g></g></svg>

After

Width:  |  Height:  |  Size: 3.4 KiB

1
src/assets/svg/light.svg Normal file
View File

@@ -0,0 +1 @@
<svg width="1em" height="1em" class="icon-light" viewBox="0 0 13 13" xmlns="http://www.w3.org/2000/svg" style="vertical-align: -0.125em;color: rgba(0, 0, 0, 0.88);"><g id="Light-\u9875\u9762-1" stroke="none" stroke-width="1px" fill="none" fill-rule="evenodd"><g id="Light-\u4E3B\u9898\u5305" transform="translate(-2943.000000, -292.000000)" fill="currentColor" fill-rule="nonzero"><g id="Light-\u7F16\u7EC4-12" transform="translate(2415.000000, 222.000000)"><g id="Light-\u89C6\u56FE\u5207\u6362-\u7F16\u8F91\u6001" transform="translate(518.000000, 60.000000)"><g id="Light-eye" transform="translate(8.000000, 8.000000)"><g id="Light-sun" transform="translate(2.000000, 2.000000)"><rect id="Light-\u77E9\u5F62" opacity="0" x="0" y="0" width="13" height="13"></rect><path d="M6.5,9.75 C4.7051875,9.75 3.25,8.2948125 3.25,6.5 C3.25,4.7051875 4.7051875,3.25 6.5,3.25 C8.2948125,3.25 9.75,4.7051875 9.75,6.5 C9.75,8.2948125 8.2948125,9.75 6.5,9.75 Z M6.5,8.66666667 C7.69661696,8.66666667 8.66666667,7.69661696 8.66666667,6.5 C8.66666667,5.30338304 7.69661696,4.33333333 6.5,4.33333333 C5.30338305,4.33333333 4.33333336,5.30338305 4.33333336,6.5 C4.33333336,7.69661695 5.30338305,8.66666667 6.5,8.66666667 Z M5.95833333,1.08333333 C5.95833333,0.784179087 6.20084576,0.541666658 6.5,0.541666658 C6.79915424,0.541666658 7.04166667,0.784179087 7.04166667,1.08333333 L7.04166667,2.16666667 C7.04166667,2.46582091 6.79915424,2.70833334 6.5,2.70833334 C6.20084576,2.70833334 5.95833333,2.46582091 5.95833333,2.16666667 L5.95833333,1.08333333 L5.95833333,1.08333333 Z M5.95833333,10.8333333 C5.95833333,10.5341791 6.20084576,10.2916667 6.5,10.2916667 C6.79915424,10.2916667 7.04166667,10.5341791 7.04166667,10.8333333 L7.04166667,11.9166667 C7.04166667,12.2158209 6.79915424,12.4583333 6.5,12.4583333 C6.20084576,12.4583333 5.95833333,12.2158209 5.95833333,11.9166667 L5.95833333,10.8333333 L5.95833333,10.8333333 Z M1.08333333,7.04166667 C0.784179087,7.04166667 0.541666658,6.79915424 0.541666658,6.5 C0.541666658,6.20084576 0.784179087,5.95833333 1.08333333,5.95833333 L2.16666667,5.95833333 C2.46582091,5.95833333 2.70833334,6.20084576 2.70833334,6.5 C2.70833334,6.79915424 2.46582091,7.04166667 2.16666667,7.04166667 L1.08333333,7.04166667 L1.08333333,7.04166667 Z M10.8333333,7.04166667 C10.5341791,7.04166667 10.2916667,6.79915424 10.2916667,6.5 C10.2916667,6.20084576 10.5341791,5.95833333 10.8333333,5.95833333 L11.9166667,5.95833333 C12.2158209,5.95833333 12.4583333,6.20084576 12.4583333,6.5 C12.4583333,6.79915424 12.2158209,7.04166667 11.9166667,7.04166667 L10.8333333,7.04166667 L10.8333333,7.04166667 Z M2.05454167,2.82045833 C1.84926545,2.60791971 1.85220137,2.27007933 2.06114035,2.06114035 C2.27007933,1.85220137 2.60791971,1.84926545 2.82045833,2.05454167 L3.63295833,2.86704167 C3.83823455,3.07958029 3.83529863,3.41742067 3.62635965,3.62635965 C3.41742067,3.83529863 3.07958029,3.83823455 2.86704167,3.63295833 L2.05454167,2.82045833 L2.05454167,2.82045833 Z M9.36704167,10.1329583 C9.16176545,9.92041971 9.16470137,9.58257933 9.37364035,9.37364035 C9.58257933,9.16470137 9.92041971,9.16176545 10.1329583,9.36704167 L10.9454583,10.1795417 C11.1507346,10.3920803 11.1477986,10.7299207 10.9388596,10.9388596 C10.7299207,11.1477986 10.3920803,11.1507346 10.1795417,10.9454583 L9.36704167,10.1329583 L9.36704167,10.1329583 Z M2.82045833,10.9454583 C2.60791971,11.1507346 2.27007933,11.1477986 2.06114035,10.9388596 C1.85220137,10.7299207 1.84926545,10.3920803 2.05454167,10.1795417 L2.86704167,9.36704167 C3.07958029,9.16176545 3.41742067,9.16470137 3.62635965,9.37364035 C3.83529863,9.58257933 3.83823455,9.92041971 3.63295833,10.1329583 L2.82045833,10.9454583 L2.82045833,10.9454583 Z M10.1329583,3.63295833 C9.92041971,3.83823455 9.58257933,3.83529863 9.37364035,3.62635965 C9.16470137,3.41742067 9.16176545,3.07958029 9.36704167,2.86704167 L10.1795417,2.05454167 C10.3920803,1.84926545 10.7299207,1.85220137 10.9388596,2.06114035 C11.1477986,2.27007933 11.1507346,2.60791971 10.9454583,2.82045833 L10.1329583,3.63295833 L10.1329583,3.63295833 Z" id="Light-\u5F62\u72B6"></path></g></g></g></g></g></g></svg>

After

Width:  |  Height:  |  Size: 4.0 KiB

View File

@@ -3,7 +3,7 @@
:drag="true"
:destroyOnClose="true"
:title="t('components.CronModal.title')"
:visible="props.visible"
:open="props.open"
:body-style="{ padding: '0 24px' }"
@cancel="fnCronModal(false)"
@ok="fnCronModal(true)"
@@ -35,6 +35,7 @@
</ProModal>
</template>
<script lang="ts" setup>
import { ProModal } from 'antdv-pro-modal';
import CronSecond from './components/Second.vue';
import CronMinute from './components/Minute.vue';
import CronHour from './components/Hour.vue';
@@ -44,9 +45,9 @@ import { reactive, computed, watch } from 'vue';
import useI18n from '@/hooks/useI18n';
const { t } = useI18n();
const emit = defineEmits(['cancel', 'ok', 'update:visible']);
const emit = defineEmits(['cancel', 'ok', 'update:open']);
const props = defineProps({
visible: {
open: {
type: Boolean,
required: true,
},
@@ -75,7 +76,7 @@ const cronStr = computed(() => {
/**监听是否显示初始cron属性 */
watch(
() => props.visible,
() => props.open,
val => {
if (!val) return;
const arr = props.cron.split(' ');
@@ -98,7 +99,7 @@ watch(
* @param val modal触发事件
*/
function fnCronModal(val: boolean) {
emit('update:visible', false);
emit('update:open', false);
if (val) {
emit('ok', cronStr.value);
} else {

View File

@@ -12,7 +12,7 @@ const router = useRouter();
const { t } = useI18n();
/**显示遮罩 */
const isVisible = computed(() => !['none', 'lock'].includes(maskStore.type));
const isOpen = computed(() => !['none', 'lock'].includes(maskStore.type));
// 用户无操作一段时间后进行锁屏
function idleTimeout(time: number, callback: Function) {
@@ -67,7 +67,7 @@ onUnmounted(() => {});
</script>
<template>
<a-modal
v-model:visible="isVisible"
v-model:open="isOpen"
get-container="#app"
:footer="null"
:zIndex="1008"

View File

@@ -2,7 +2,6 @@
import { reactive, watch, onMounted, PropType, nextTick } from 'vue';
import { Container, Draggable } from 'vue3-smooth-dnd';
import useI18n from '@/hooks/useI18n';
import { type ColumnsType } from 'ant-design-vue/lib/table';
import { dbGetJSON, dbSetJSON } from '@/utils/cache-db-utils';
import { CACHE_DB_TABLE_DND } from '@/constants/cache-keys-constants';
const { t, currentLocale } = useI18n();
@@ -37,7 +36,7 @@ const props = defineProps({
});
/**表格字段列 */
const tableColumns = reactive<ColumnsType>(props.columns);
const tableColumns = reactive(props.columns);
/**表格字段列勾选状态 */
const state = reactive<{
@@ -56,7 +55,9 @@ const state = reactive<{
function fnTableColumnsCheckAllChange(e: any) {
const checked = e.target.checked;
state.indeterminate = false;
state.columnsTitleList = checked ? tableColumns.map(s => `${s.title}`) : [];
state.columnsTitleList = checked
? tableColumns.map(s => `${s.title as string}`)
: [];
}
/**表格字段列拖拽操作 */

View File

@@ -0,0 +1,225 @@
<script lang="ts" setup>
import { ref, onMounted, onBeforeUnmount, nextTick } from 'vue';
import { FitAddon } from '@xterm/addon-fit';
import { Terminal } from '@xterm/xterm';
import '@xterm/xterm/css/xterm.css';
import { RESULT_CODE_ERROR } from '@/constants/result-constants';
import { OptionsType, WS } from '@/plugins/ws-websocket';
const ws = new WS();
const emit = defineEmits(['connect', 'close', 'message']);
const props = defineProps({
/**终端ID必传 */
id: {
type: String,
required: true,
},
/**连接主机ID必传 */
hostId: {
type: String,
required: true,
},
/**初始发送命令 */
initCmd: {
type: [String, Boolean],
default: false,
},
});
/**终端输入DOM节点实例对象 */
const terminalDom = ref<HTMLElement | undefined>(undefined);
/**终端输入实例对象 */
const terminal = ref<any>(null);
/**终端输入命令 */
const terminalCmd = ref<string>('');
/**终端输入渲染 */
function handleRanderXterm(container: HTMLElement | undefined) {
if (!container) return;
const xterm = new Terminal({
lineHeight: 1.2,
fontSize: 12,
fontFamily: "Monaco, Menlo, Consolas, 'Courier New', monospace",
theme: {
background: '#000000',
},
cursorBlink: true, // 光标闪烁
cursorStyle: 'block',
scrollback: 1000,
scrollSensitivity: 15,
tabStopWidth: 4,
disableStdin: false, // 禁止输入
});
// 挂载
xterm.open(container);
// 自适应尺寸
const fitAddon = new FitAddon();
xterm.loadAddon(fitAddon);
// 终端输入字符按键监听
xterm.onKey(({ key, domEvent }) => {
// console.log(key, domEvent);
// 单键输入
switch (domEvent.key) {
case 'Enter':
const cmdStr = terminalCmd.value.trim();
// 发送文本
terminal.value.scrollToBottom();
terminal.value.writeln('\r\n');
ws.send({
requestId: `redis_${props.hostId}`,
type: 'redis',
data: `${cmdStr}\r\n`,
});
terminalCmd.value = '';
// 退出登录
if ('quit' === cmdStr) {
setTimeout(() => {
ws.close();
}, 1000);
}
break;
case 'Backspace':
// 处理退格键,删除最后一个字符
xterm.write('\b \b');
break;
default:
xterm.write(key);
terminalCmd.value += key;
return;
}
});
// 创建 ResizeObserver 实例
var observer = new ResizeObserver(entries => {
fitAddon.fit();
});
// 监听元素大小变化
observer.observe(container);
terminal.value = xterm;
}
/**连接打开后回调 */
function wsOpen(ev: any) {
// console.info('wsOpen', ev);
nextTick(() => {
handleRanderXterm(terminalDom.value);
// 连接事件
emit('connect', {
timeStamp: ev.timeStamp,
cols: terminal.value.cols,
rows: terminal.value.rows,
hostId: props.hostId,
id: props.id,
});
// 初始发送命令
if (typeof props.initCmd === 'string') {
ws.send({
requestId: `redis_${props.hostId}`,
type: 'redis',
data: `${props.initCmd}\r\n`,
});
}
});
}
/**连接错误后回调 */
function wsError(ev: any) {
console.error('wsError', ev);
if (terminal.value != null) {
let message = 'disconnected';
terminal.value.write(`\x1b[31m${message}\x1b[m\r\n`);
} else if (terminalDom.value) {
terminalDom.value.style.background = '#000';
terminalDom.value.style.color = '#ff4d4f';
terminalDom.value.style.height = '60%';
terminalDom.value.innerText = 'disconnected';
}
}
/**连接关闭后回调 */
function wsClose(code: number) {
// console.warn('wsClose', code);
if (terminal.value != null) {
let message = 'disconnected';
terminal.value.write(`\x1b[31m${message}\x1b[m\r\n`);
}
// 关闭事件
emit('close', {
code: code,
hostId: props.hostId,
id: props.id,
});
}
/**接收消息后回调 */
function wsMessage(res: Record<string, any>) {
emit('message', res);
// console.log('wsMessage', res);
const { code, requestId, data } = res;
if (code === RESULT_CODE_ERROR) {
console.warn(res.msg);
return;
}
if (!requestId) return;
if (data.indexOf('is empty') > 0) return;
if (terminal.value != null) {
// terminal.value.write(data.trim().replace(/\n/g, "\r\n"));
// 是否n结尾
if (/[\r\n]$/.test(data)) {
terminal.value.writeln(data.trim().replace(/\n/g, '\r\n'));
} else {
terminal.value.write(data.replace(/\n/g, '\r\n'));
}
}
}
onMounted(() => {
if (props.hostId) {
// 建立链接
const options: OptionsType = {
url: '/ws/redis',
params: {
hostId: props.hostId,
},
onmessage: wsMessage,
onerror: wsError,
onopen: wsOpen,
onclose: wsClose,
};
ws.connect(options);
}
});
onBeforeUnmount(() => {
ws.close();
});
// 给组件设置属性 ref="xxxTerminal"
// setup内使用 const xxxTerminal = ref();
defineExpose({
/**发送方法 */
send: (data: string) => {
ws.send({
requestId: `redis_${props.hostId}`,
type: 'redis',
data: `${data}\r\n`,
});
},
});
</script>
<template>
<div class="terminal">
<div ref="terminalDom" :id="id" class="terminal"></div>
</div>
</template>
<style lang="css" scoped>
.terminal {
width: 100%;
height: 100%;
}
</style>

View File

@@ -126,7 +126,7 @@ function handleRanderXterm(container: HTMLElement | undefined) {
// console.log('尺寸', cols, rows);
ws.send({
requestId: `ssh_resize_${props.hostId}`,
type: 'ssh_resize',
type: 'resize',
data: { cols, rows },
});
});

View File

@@ -43,6 +43,11 @@ const props = defineProps({
type: String,
default: 'ssh',
},
/**消息处理函数 */
processMessages: {
type: Function,
default: undefined,
},
});
/**终端输入DOM节点实例对象 */
@@ -153,32 +158,49 @@ function wsMessage(res: Record<string, any>) {
}
if (!requestId) return;
if (terminal.value != null) {
// 查找的开始输出标记
const parts: string[] = data.split('\u001b[?2004l\r');
if (parts.length > 0) {
let text = parts[parts.length - 1];
// 找到最后输出标记
let lestIndex = text.lastIndexOf('\u001b[?2004h\u001b]0;');
if (lestIndex !== -1) {
text = text.substring(0, lestIndex);
}
if (text === '' || text === '\r\n' || text.startsWith('^C\r\n')) {
return;
}
// 是否还有最后输出标记
lestIndex = text.lastIndexOf('\u001b[?2004h');
if (lestIndex !== -1) {
text = text.substring(0, lestIndex);
}
// console.log({ parts, text });
terminal.value.write(text);
let text = '';
// 处理消息
if (props.processMessages) {
text = props.processMessages(data);
}else{
text = processMessage(data);
}
// 无消息是则不输出
if (text === '') {
return;
}
// 无标记
terminal.value.write(data);
terminal.value.write(text);
}
}
/**终端消息处理*/
function processMessage(data: string): string {
// 查找的开始输出标记
const parts: string[] = data.split('\u001b[?2004l\r');
if (parts.length > 0) {
if (parts[0].startsWith('^C') || parts[0].startsWith('\r')) {
return '';
}
let text = parts[parts.length - 1];
// 找到最后输出标记
let lestIndex = text.lastIndexOf('\u001b[?2004h\u001b]0;');
if (lestIndex !== -1) {
text = text.substring(0, lestIndex);
}
if (text === '' || text === '\r\n' || text.startsWith('^C\r\n')) {
return '';
}
// 是否还有最后输出标记
lestIndex = text.lastIndexOf('\u001b[?2004h');
if (lestIndex !== -1) {
text = text.substring(0, lestIndex);
}
// console.log({ parts, text });
return text;
}
return data;
}
onMounted(() => {
if (props.neType && props.neId) {
// 建立链接

View File

@@ -1,5 +1,5 @@
<script lang="ts" setup>
import { message } from 'ant-design-vue/lib';
import { message } from 'ant-design-vue/es';
import { ref, reactive, onMounted, onBeforeUnmount, nextTick } from 'vue';
import { FitAddon } from '@xterm/addon-fit';
import { Terminal } from '@xterm/xterm';
@@ -160,7 +160,7 @@ function handleRanderXterm(container: HTMLElement | undefined) {
// console.log('尺寸', cols, rows);
ws.send({
requestId: `telnet_resize_${props.hostId}`,
type: 'telnet_resize',
type: 'resize',
data: { cols, rows },
});
});

View File

@@ -1,97 +0,0 @@
<script lang="ts" setup>
import { ref, onMounted, onBeforeUnmount, nextTick } from 'vue';
import { FitAddon } from '@xterm/addon-fit';
import { Terminal } from '@xterm/xterm';
import '@xterm/xterm/css/xterm.css';
const emit = defineEmits(['update:value']);
const props = defineProps({
/**终端ID必传 */
id: {
type: String,
required: true,
},
/**窗口单行字符数 */
cols: {
type: Number,
default: 80,
},
/**窗口行数 */
rows: {
type: Number,
default: 40,
},
/**信息 */
value: {
type: String,
default: '',
},
});
/**终端输入DOM节点实例对象 */
const terminalDom = ref<HTMLElement | undefined>(undefined);
/**终端输入实例对象 */
const terminal = ref<any>(null);
/**终端输入渲染 */
function handleRanderXterm(container: HTMLElement | undefined) {
if (!container) return;
const xterm = new Terminal({
cols: props.cols,
rows: props.rows,
lineHeight: 1.2,
fontSize: 12,
fontFamily: "Monaco, Menlo, Consolas, 'Courier New', monospace",
theme: {
background: '#000000',
},
cursorBlink: false, // 光标闪烁
cursorStyle: 'block',
scrollback: 1000,
scrollSensitivity: 15,
tabStopWidth: 4,
disableStdin: true, // 禁止输入
});
// 挂载
xterm.open(container);
// 自适应尺寸
const fitAddon = new FitAddon();
xterm.loadAddon(fitAddon);
// 创建 ResizeObserver 实例
var observer = new ResizeObserver(entries => {
fitAddon.fit();
});
// 监听元素大小变化
observer.observe(container);
terminal.value = xterm;
}
onMounted(() => {
nextTick(() => {
handleRanderXterm(terminalDom.value);
// 初始发送命令
if (typeof props.value === 'string') {
terminal.value.write(props.value);
}
});
});
onBeforeUnmount(() => {
if (terminal.value != null) {
terminal.value.dispose();
}
});
</script>
<template>
<div ref="terminalDom" :id="id" class="terminal"></div>
</template>
<style lang="css" scoped>
.terminal {
width: 100%;
height: 100%;
}
</style>

View File

@@ -1,10 +1,11 @@
<script setup lang="ts">
import { message } from 'ant-design-vue/lib';
import { FileType } from 'ant-design-vue/lib/upload/interface';
import { UploadRequestOption } from 'ant-design-vue/lib/vc-upload/interface';
import { message } from 'ant-design-vue/es';
import { FileType } from 'ant-design-vue/es/upload/interface';
import { UploadRequestOption } from 'ant-design-vue/es/vc-upload/interface';
import { ProModal } from 'antdv-pro-modal';
import useI18n from '@/hooks/useI18n';
const { t } = useI18n();
const emit = defineEmits(['upload', 'close', 'update:visible']);
const emit = defineEmits(['upload', 'close', 'update:open']);
const props = defineProps({
/**窗口标题 */
title: {
@@ -17,7 +18,7 @@ const props = defineProps({
default: false,
},
/**是否弹出显示,必传 */
visible: {
open: {
type: Boolean,
required: true,
},
@@ -80,7 +81,7 @@ function fnUpload(up: UploadRequestOption) {
:drag="true"
:destroyOnClose="true"
:title="props.title"
:visible="props.visible"
:open="props.open"
:keyboard="false"
:mask-closable="false"
:confirm-loading="props.loading"

View File

@@ -1,5 +1,5 @@
import { onBeforeMount } from 'vue';
import { ConfigProvider, message } from 'ant-design-vue/lib';
import { ConfigProvider, message } from 'ant-design-vue/es';
import { CACHE_LOCAL_PRIMARY_COLOR } from '@/constants/cache-keys-constants';
import { localGet, localSet } from '@/utils/cache-local-utils';

View File

@@ -6,7 +6,7 @@ export default {
// 通用
common: {
title: 'Core Network Management Platform',
title: 'Login Platform',
desc: 'Core Network Management Platform',
loading: 'Please wait...',
inputPlease: 'Please input',
@@ -192,6 +192,7 @@ export default {
lockPasswd: "Unlock Password",
lockPasswdTip: "No password can be set",
fullscreen: "Full Screen",
theme: "Theme light/dark mode",
logout: "Logout",
profile: "Profile",
settings: "Settings",
@@ -317,6 +318,8 @@ export default {
color: "Style color scheme",
colorActions: "Overall style color scheme setting",
colorRandomly: "Randomization",
theme: "Theme dark and light modes",
themeActions: "Toggle light/dark mode",
navTheme: "Dark Menu",
navThemeActions: "Menus that can only change the navigation mode",
fixedHeader: "Fixed top navigation bar",
@@ -575,7 +578,7 @@ export default {
resultOk: "Success",
resultFail: "Fail",
delTip: "Confirm deletion of the data item numbered [{msg}]?",
tenantName: "Tenant Name",
tenantName: "Tenant Name",
exportTip: "Do you confirm to export the current query conditions of the CDR data? (Maximum 10,000 items can be exported.)",
smfChargingID: 'Charging ID',
smfSubscriptionIDData: 'Subscription ID Data',
@@ -868,7 +871,7 @@ export default {
import: 'Import',
loadDataConfirm: 'Are you sure you want to reload the data?',
loadData: 'Load Data',
loadDataTip: 'Successfully fetched load data: {num} entries, the system is internally updating the data. Please wait a moment!!!!',
loadDataTip: 'Successfully fetched loaded data: {num} items, the system is internally updating the data, it will take about {timer} seconds, please wait!!!!!.',
startIMSI: 'Start IMSI',
batchAddText: 'Batch Add',
batchDelText: 'Batch Delete',
@@ -896,7 +899,7 @@ export default {
import: 'Import',
loadDataConfirm: 'Are you sure you want to reload the data?',
loadData: 'Load Data',
loadDataTip: 'Successfully fetched load data: {num} entries, the system is internally updating the data. Please wait a moment!!!!',
loadDataTip: 'Successfully fetched loaded data: {num} items, the system is internally updating the data, it will take about {timer} seconds, please wait!!!!!.',
numAdd: 'Number of releases',
numDel: 'Number of deleted',
checkDel: 'Check Delete',
@@ -964,7 +967,7 @@ export default {
sarTip2:'(corresponding parameter setting -Service Area Restriction)',
rfsfTip:'RAT Frequency Selection Priority',
},
base5G: {
base5G: {
neType: 'Radio Type',
gnb:'5G Radios',
enb:'4G Radios',
@@ -1063,6 +1066,14 @@ export default {
realTimeData: "Real Time Data",
},
customTarget:{
TourTitle1:'Calculate element selection',
TourDes1:'Select the metric corresponding to the selected NE type for the calculation formula',
TourTitle2:'Calculate symbol selection',
TourDes2:'Select a calculation symbol',
TourTitle3:'Calculation formula',
TourDes3:'The calculation formula is automatically composed from the calculation elements and calculation symbols selected earlier',
TourTitle4:'Result unit',
TourDes4:'Units are optional. PS: Formula automatically × 100% when the % sign',
kpiId:' Custom Indicator',
kpiIdTip:'This Ne has no custom indicators',
period:' Granularity',
@@ -1072,8 +1083,8 @@ export default {
description:' Description',
kpiSet:' Statistical Settings',
sixHoursAgo:'Six hours ago',
threeHoursAgo:'Three hours ago.',
delCustomTip:'Confirm deletion of data item with record number {num}?',
threeHoursAgo:'Three hours ago',
delCustomTip:'Confirm deletion of data item with record Custom Indicator {num}?',
delCustom:' Successfully delete record number {num} custom indicator',
addCustom:' Add custom indicator',
editCustom:' Edit Custom indicator',
@@ -1085,8 +1096,14 @@ export default {
element:'Element',
granularity:'Granularity',
unit:'Unit',
expressionModal:'Expression Modal',
expressionErrorTip:'Please check the expression, the wrong indicator is {kpiId}',
expressionNoIdTip:'Please check the expression, no valid indicator is found',
},
kpiKeyTarget:{
"time":"Time",
"rawData":"Table Data",
"statistics":"NE metrics",
"fullWidthLayout":"Full Width",
"twoColumnLayout":"Two Column",
"saveLayout": "Save Layout",
@@ -1099,6 +1116,11 @@ export default {
"layout3": "Layout 3"
},
kpiOverView:{
"kpiName":"NE Metrics Name",
"maxValue":"Max Value",
"minValue":"Min Value",
"avgValue":"Average Value",
"totalValue":"Worth Value",
"kpiChartTitle":"Overview of NE metrics",
"changeLine":"Change to Line Charts",
"changeBar":"Change to Bar Charts",
@@ -1698,7 +1720,7 @@ export default {
userName: 'Nick Name',
permission: 'Role',
className: 'Department',
tenntName:'Tenant Name',
tenntName:'Tenant Name',
loginIp: 'Login Address',
loginTime: 'Login Time',
status: 'Status',

View File

@@ -6,7 +6,7 @@ export default {
// 通用
common: {
title: '核心网管理平台',
title: '登录平台',
desc: '核心网管理平台',
loading: '请稍等...',
inputPlease: '请输入',
@@ -192,6 +192,7 @@ export default {
lockPasswd: "解锁密码",
lockPasswdTip: "可不设置密码",
fullscreen: "全屏显示",
theme: "主题明/暗模式",
logout: "退出登录",
profile: "个人中心",
settings: "个人设置",
@@ -317,6 +318,8 @@ export default {
color: "风格配色",
colorActions: "整体风格配色设置",
colorRandomly: "随机",
theme: "主题明暗模式",
themeActions: "切换浅色/暗黑模式",
navTheme: "深色菜单",
navThemeActions: "只能改变导航模式的菜单",
fixedHeader: "固定顶部导航栏",
@@ -575,7 +578,7 @@ export default {
resultOk: "成功",
resultFail: "失败",
delTip: "确认删除编号为【{msg}】的数据项?",
tenantName: "租户名称",
tenantName: "租户名称",
exportTip: "确认导出当前查询条件的话单数据吗?(导出最大支持一万条)",
smfChargingID: '计费ID',
smfSubscriptionIDData: '订阅 ID 数据',
@@ -868,7 +871,7 @@ export default {
import: '导入',
loadDataConfirm: '确认要重新加载数据吗?',
loadData: '加载数据',
loadDataTip: '成功获取加载数据:{num}条,系统内部正在进行数据更新,请稍候!!!',
loadDataTip: '成功获取加载数据:{num}条,系统内部正在进行数据更新,大约需要{timer}秒,请稍候!!!',
startIMSI: '起始IMSI',
batchAddText: '批量新增',
batchDelText: '批量删除',
@@ -896,7 +899,7 @@ export default {
import: '导入',
loadDataConfirm: '确认要重新加载数据吗?',
loadData: '加载数据',
loadDataTip: '成功获取加载数据:{num}条,系统内部正在进行数据更新,请稍候!!!',
loadDataTip: '成功获取加载数据:{num}条,系统内部正在进行数据更新,大约需要{timer}秒,请稍候!!!',
numAdd: '放号个数',
numDel: '删除个数',
checkDel:'勾选删除',
@@ -1063,6 +1066,14 @@ export default {
realTimeData: "实时数据",
},
customTarget:{
TourTitle1:'计算元素选择',
TourDes1:'选择已经勾选网元类型对应的指标用于计算公式',
TourTitle2:'计算符号选择',
TourDes2:'选择计算符号',
TourTitle3:'计算公式',
TourDes3:'由前面选择的计算元素和计算符号自动组成计算公式',
TourTitle4:'结果单位',
TourDes4:'单位可选可填。PS%符号时公式自动×100%',
kpiId:'自定义指标项',
kpiIdTip:'该网元没有自定义指标',
period:'颗粒度',
@@ -1073,7 +1084,7 @@ export default {
kpiSet:'统计设置',
sixHoursAgo:'6小时前',
threeHoursAgo:'3小时前',
delCustomTip:'确认删除记录编号为 {num} 的数据项?',
delCustomTip:'确认删除自定义指标项为 {num} 的数据项?',
delCustom:'成功删除记录编号为 {num} 自定义指标',
addCustom:'添加自定义指标',
editCustom:'编辑自定义指标',
@@ -1085,8 +1096,14 @@ export default {
element:'元素',
granularity:'颗粒度',
unit:'单位',
},
expressionModal:'表达式模块',
expressionErrorTip:'请检查表达式,错误的指标为{kpiId}',
expressionNoIdTip:'请检查表达式,没有找到任何有效的指标',
},
kpiKeyTarget:{
"time":"时间",
"rawData":"表格数据",
"statistics":"指标",
"fullWidthLayout":"全宽布局",
"twoColumnLayout":"两列布局",
"saveLayout": "保存布局",
@@ -1099,12 +1116,16 @@ export default {
"layout3": "布局3"
},
kpiOverView:{
"kpiName":"指标名",
"maxValue":"最大值",
"minValue":"最小值",
"avgValue":"平均值",
"totalValue":"总值",
"kpiChartTitle":"网元指标概览",
"changeLine":"切换为折线图",
"changeBar":"切换为柱状图",
"chooseShowMetrics":"选择需要显示的指标",
"chooseMetrics":"选择指标",
},
},
traceManage: {

View File

@@ -1,10 +1,9 @@
<script setup lang="ts">
import {
ProLayout,
WaterMark,
getMenuData,
clearMenuItem,
type MenuDataItem,
MenuDataItem,
} from 'antdv-pro-layout';
import RightContent from './components/RightContent.vue';
import Tabs from './components/Tabs.vue';
@@ -12,26 +11,25 @@ import GlobalMask from '@/components/GlobalMask/index.vue';
import { scriptUrl } from '@/assets/js/icon_font_8d5l8fzk5b87iudi';
import {
computed,
reactive,
watch,
nextTick,
onMounted,
onUnmounted,
nextTick,
reactive,
watch,
} from 'vue';
import { useRouter } from 'vue-router';
import useLayoutStore from '@/store/modules/layout';
import useAppStore from '@/store/modules/app';
import useRouterStore from '@/store/modules/router';
import useTabsStore from '@/store/modules/tabs';
import useAlarmStore from '@/store/modules/alarm';
import useAppStore from '@/store/modules/app';
import { useRouter } from 'vue-router';
import { MENU_PATH_INLINE } from '@/constants/menu-constants';
const { proConfig, waterMarkContent } = useLayoutStore();
import useI18n from '@/hooks/useI18n';
import useAlarmStore from '@/store/modules/alarm';
import { getServerTime } from '@/api';
import { MENU_PATH_INLINE } from '@/constants/menu-constants';
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
import { parseDateToStr } from '@/utils/date-utils';
import { parseUrlPath } from '@/plugins/file-static-url';
const { proConfig, waterMarkContent } = useLayoutStore();
const { t, currentLocale } = useI18n();
const routerStore = useRouterStore();
const tabsStore = useTabsStore();
@@ -39,7 +37,7 @@ const appStore = useAppStore();
const router = useRouter();
/**菜单面板 */
let layoutState = reactive({
const layoutState = reactive({
collapsed: false, // 是否展开菜单面板
openKeys: ['/'], // 打开菜单key
selectedKeys: ['/index'], // 选中高亮菜单key
@@ -247,7 +245,7 @@ onUnmounted(() => {
</script>
<template>
<WaterMark :content="waterMarkContent" :z-index="100">
<a-watermark :content="waterMarkContent" :z-index="100">
<ProLayout
v-model:collapsed="layoutState.collapsed"
v-model:selectedKeys="layoutState.selectedKeys"
@@ -290,10 +288,10 @@ onUnmounted(() => {
</RouterLink>
</template>
<!--插槽-顶部左侧,只对side布局有效-->
<!--插槽-渲染顶部内容区域,仅布局side有效-->
<template #headerContentRender></template>
<!--插槽-顶部右侧-->
<!--插槽-渲染顶部内容右端区域-->
<template #headerContentRightRender>
<RightContent />
</template>
@@ -364,7 +362,7 @@ onUnmounted(() => {
<!-- 全局遮罩 -->
<GlobalMask />
</WaterMark>
</a-watermark>
</template>
<style lang="less" scoped>
@@ -413,6 +411,19 @@ onUnmounted(() => {
}
}
.theme-light.theme-menu-light .app-name {
color: #141414 !important;
}
.theme-light.theme-menu-dark .app-name {
color: #fff !important;
}
.theme-dark.theme-menu-light .app-name {
color: #fff !important;
}
.theme-dark.theme-menu-dark .app-name {
color: #fff !important;
}
.footer {
z-index: 16;
margin: 0px;
@@ -427,6 +438,7 @@ onUnmounted(() => {
flex-direction: row;
flex-wrap: nowrap;
justify-content: space-between;
align-items: center;
padding: 4px 16px;
background: #fff;
box-shadow: 0 1px 4px #0015291f;
@@ -434,6 +446,10 @@ onUnmounted(() => {
height: 32px;
}
[data-theme='dark'] &-fixed {
background: #141414;
}
& #serverTimeDom {
color: inherit;
opacity: 0.85;

View File

@@ -1,20 +1,25 @@
<script setup lang="ts">
import { MenuInfo } from 'ant-design-vue/lib/menu/src/interface';
import svgLight from '@/assets/svg/light.svg';
import svgDark from '@/assets/svg/dark.svg';
import { MenuInfo } from 'ant-design-vue/es/menu/src/interface';
import { viewTransitionTheme } from 'antdv-pro-layout';
import { ProModal } from 'antdv-pro-modal';
import { ref } from 'vue';
import { useRoute, useRouter } from 'vue-router';
import { useFullscreen } from '@vueuse/core';
import { hasPermissions } from '@/plugins/auth-user';
import useI18n from '@/hooks/useI18n';
import useLayoutStore from '@/store/modules/layout';
import useAppStore from '@/store/modules/app';
import useUserStore from '@/store/modules/user';
import useAlarmStore from '@/store/modules/alarm';
import useMaskStore from '@/store/modules/mask';
import { hasPermissions } from '@/plugins/auth-user';
import { dbClear } from '@/utils/cache-db-utils';
import { CACHE_DB_TABLE_DND } from '@/constants/cache-keys-constants';
import { TENANTADMIN_ROLE_KEY } from '@/constants/admin-constants';
import { ref } from 'vue';
const { isFullscreen, toggle } = useFullscreen();
const { t, changeLocale, optionsLocale } = useI18n();
const layoutStore = useLayoutStore();
const maskStore = useMaskStore();
const userStore = useUserStore();
const appStore = useAppStore();
@@ -64,6 +69,13 @@ function fnClickAlarm() {
router.push({ name: 'ActiveAlarm_2088' });
}
/**改变主题色 */
function fnClickTheme(e: any) {
viewTransitionTheme(isDarkMode => {
layoutStore.changeConf('theme', isDarkMode ? 'light' : 'dark');
}, e);
}
/**改变多语言 */
function fnChangeLocale(e: any) {
changeLocale(e.key);
@@ -92,7 +104,7 @@ function fnChangeLocale(e: any) {
<!-- 锁屏操作 -->
<span v-perms:has="['system:setting:lock']">
<a-tooltip placement="bottom">
<a-tooltip placement="bottomRight">
<template #title>{{ t('loayouts.rightContent.lock') }}</template>
<a-button type="text" style="color: inherit" @click="fnClickLock()">
<template #icon>
@@ -101,10 +113,11 @@ function fnChangeLocale(e: any) {
</a-button>
<ProModal
:drag="true"
:center-y="true"
:width="400"
:minHeight="200"
:mask-closable="false"
v-model:visible="lockConfirm"
v-model:open="lockConfirm"
:title="t('loayouts.rightContent.lockTip')"
@ok="fnClickLockToPage()"
>
@@ -128,7 +141,7 @@ function fnChangeLocale(e: any) {
</a-tooltip>
</span>
<a-tooltip placement="bottom">
<a-tooltip placement="bottomRight">
<template #title>{{ t('loayouts.rightContent.fullscreen') }}</template>
<a-button type="text" style="color: inherit" @click="toggle">
<template #icon>
@@ -138,14 +151,27 @@ function fnChangeLocale(e: any) {
</a-button>
</a-tooltip>
<a-tooltip placement="bottomRight">
<template #title>{{ t('loayouts.rightContent.theme') }}</template>
<a-button type="text" @click="fnClickTheme">
<template #icon>
<img
v-if="layoutStore.proConfig.theme === 'dark'"
:src="svgDark"
class="theme-icon"
/>
<img v-else :src="svgLight" class="theme-icon" />
</template>
</a-button>
</a-tooltip>
<a-dropdown
placement="bottom"
placement="bottomRight"
trigger="click"
v-if="appStore.i18nOpen && hasPermissions(['system:setting:i18n'])"
>
<a-button size="small" type="default">
{{ t('i18n') }}
<DownOutlined />
<a-button type="text" style="color: inherit">
<template #icon> <TranslationOutlined /> </template>
</a-button>
<template #overlay>
<a-menu @click="fnChangeLocale">
@@ -213,4 +239,11 @@ function fnChangeLocale(e: any) {
overflow: hidden;
}
}
.theme-icon {
width: 18px;
height: 18px;
margin-bottom: 4px;
color: inherit;
}
</style>

View File

@@ -4,9 +4,9 @@ import { computed, watch } from 'vue';
import { useRouter } from 'vue-router';
import useTabsStore from '@/store/modules/tabs';
import useI18n from '@/hooks/useI18n';
const { t } = useI18n();
const tabsStore = useTabsStore();
const router = useRouter();
const { t } = useI18n();
defineProps({
/**标签栏宽度 */
@@ -112,7 +112,7 @@ watch(router.currentRoute, v => tabsStore.tabOpen(v), { immediate: true });
<a-tabs
class="tabs"
:class="{ 'tabs-fixed': fixedHeader }"
:style="{ width: width, top: headerRender === false ? 0 : undefined }"
:style="{ width: fixedHeader ? width : '100%', top: headerRender === false ? 0 : undefined }"
hide-add
tab-position="top"
type="editable-card"
@@ -150,7 +150,7 @@ watch(router.currentRoute, v => tabsStore.tabOpen(v), { immediate: true });
</a-tooltip>
<a-tooltip placement="topRight">
<template #title>{{ t('loayouts.tabs.more') }}</template>
<a-dropdown trigger="click" placement="bottomRight">
<a-dropdown placement="bottomRight" trigger="click">
<a-button type="ghost" shape="circle" size="small">
<template #icon><DownOutlined /></template>
</a-button>
@@ -199,7 +199,18 @@ watch(router.currentRoute, v => tabsStore.tabOpen(v), { immediate: true });
}
}
[data-theme='dark'] .tabs {
background: #141414;
}
.tabs :deep(.ant-tabs-nav:before) {
border-bottom: none;
}
.tabs :deep(.ant-tabs-nav-list .ant-tabs-tab) {
border-radius: 8px;
}
.tabs :deep(.ant-tabs-nav-list .ant-tabs-tab.ant-tabs-tab-active) {
border-bottom-right-radius: unset;
border-bottom-left-radius: unset;
}
</style>

View File

@@ -4,16 +4,15 @@ import App from './App.vue';
import router from './router';
import directive from './directive';
import i18n from './i18n';
import ProModal from "antdv-pro-modal";
import 'antdv-pro-layout/dist/style.css';
import 'antdv-pro-modal/dist/style.css';
import 'ant-design-vue/dist/antd.variable.min.css';
import 'antdv-pro-layout/dist/style.css';
import 'ant-design-vue/dist/reset.css';
const app = createApp(App);
app.use(store);
app.use(router);
app.use(directive);
app.use(i18n);
app.use(ProModal);
app.mount('#app');

View File

@@ -19,3 +19,26 @@ export function parseUrlPath(path: string) {
: import.meta.env.VITE_API_BASE_URL;
return `${baseUrl}${path}?r=${Math.random().toFixed(2)}`;
}
/**
* 解析静态文件相对路径
* @param path 静态资源文件
* @returns
*/
export function parseBasePath(path: string) {
if (!path || path === '#') {
return '#';
}
if (validHttp(path)) {
return path;
}
// 兼容旧前端可改配置文件
const baseUrl = import.meta.env.VITE_HISTORY_BASE_URL;
let scriptUrl =
baseUrl.length === 1 && baseUrl.indexOf('/') === 0
? ''
: baseUrl.indexOf('/') === -1
? '/' + baseUrl
: baseUrl;
return `${scriptUrl}${path}?r=${Math.random().toFixed(2)}`;
}

View File

@@ -198,7 +198,7 @@ function beforeRequest(options: OptionsType): OptionsType | Promise<any> {
if (options.method === 'get') return options;
// 非get参数提交
let body = options.data
let body = options.data;
if (body instanceof FormData) {
options.body = body;
} else if (body) {

View File

@@ -182,7 +182,12 @@ router.beforeEach(async (to, from, next) => {
next({ name: 'Index' });
}
const token = getToken();
let token = getToken();
// 免用户登录认证
// if (!appStore.loginAuth) {
// token = '== Not Login Auth ==';
// }
// 没有token
if (!token) {

View File

@@ -20,6 +20,8 @@ type AppStore = {
buildTime: string;
/**系统引导使用 */
bootloader: boolean;
// 用户登录认证
loginAuth: boolean;
// 序列号
serialNum: string;
/**应用版权声明 */
@@ -52,6 +54,7 @@ const useAppStore = defineStore('app', {
version: `-`,
buildTime: `-`,
bootloader: false,
loginAuth: false,
serialNum: `-`,
copyright: `Copyright ©2023 For ${import.meta.env.VITE_APP_NAME}`,
logoType: 'icon',
@@ -85,6 +88,7 @@ const useAppStore = defineStore('app', {
if (this.bootloader) {
removeToken();
}
this.loginAuth = res.data.loginAuth === 'true';
this.serialNum = res.data.serialNum;
this.appName = res.data.title;
this.copyright = res.data.copyright;

View File

@@ -1,16 +1,23 @@
import { CACHE_LOCAL_PROCONFIG } from '@/constants/cache-keys-constants';
import { localGetJSON, localSetJSON } from '@/utils/cache-local-utils';
import { theme } from 'ant-design-vue/es';
import type { ThemeConfig } from 'ant-design-vue/es/config-provider/context';
import { defineStore } from 'pinia';
import {
CACHE_LOCAL_PRIMARY_COLOR,
CACHE_LOCAL_PROCONFIG,
} from '@/constants/cache-keys-constants';
import {
localGet,
localGetJSON,
localSetJSON,
} from '@/utils/cache-local-utils';
/**布局参数类型 */
type LayoutStore = {
/**布局设置抽屉显示 */
visible: boolean;
/**布局配置 */
proConfig: {
/**导航布局 */
layout: 'side' | 'top' | 'mix';
/**全局主题色,需要导入样式文件 */
/**全局主题色*/
theme: 'dark' | 'light';
/**菜单导航主题色 */
menuTheme: 'dark' | 'light';
@@ -29,10 +36,33 @@ type LayoutStore = {
/**内容区域-导航标签项 */
tabRender: any | boolean | undefined;
};
/**主题配置 */
themeConfig: ThemeConfig;
/**水印内容 */
waterMarkContent: string;
};
/**
* 获取随机颜色范围
* @returns 颜色
*/
function getRandomColor(): string {
const colors: string[] = [
'#f5222d',
'#fa541c',
'#fa8c16',
'#a0d911',
'#13c2c2',
'#1890ff',
'#722ed1',
'#eb2f96',
'#faad14',
'#52c41a',
];
const i = Math.floor(Math.random() * 10);
return colors[i];
}
/**判断是否关闭内容区域 */
const proRender = (render: any) => (render === false ? false : undefined);
@@ -50,7 +80,6 @@ const proConfigLocal: LayoutStore['proConfig'] = localGetJSON(
const useLayoutStore = defineStore('layout', {
state: (): LayoutStore => ({
visible: false,
proConfig: {
layout: proConfigLocal.layout,
theme: proConfigLocal.theme,
@@ -63,13 +92,27 @@ const useLayoutStore = defineStore('layout', {
menuHeaderRender: proRender(proConfigLocal.menuHeaderRender),
tabRender: proRender(proConfigLocal.tabRender),
},
themeConfig: {
algorithm: [theme.darkAlgorithm],
// algorithm: themeColor["dark"],
token: {
// colorBgContainer: "#fff",
colorPrimary: localGet(CACHE_LOCAL_PRIMARY_COLOR) || '#1890ff',
// borderRadius: 6,
},
},
waterMarkContent: import.meta.env.VITE_APP_NAME,
}),
actions: {
/**改变显示状态 */
changeVisibleLayoutSetting() {
this.visible = !this.visible;
getters: {
getColorPrimary(): string {
let color = '#1890ff';
if (this.themeConfig.token) {
color = this.themeConfig.token.colorPrimary || color;
}
return color;
},
},
actions: {
/**修改水印文字 */
changeWaterMark(text: string) {
this.waterMarkContent = text;
@@ -77,10 +120,48 @@ const useLayoutStore = defineStore('layout', {
/**修改布局设置 */
changeConf(key: string, value: boolean | string | number | undefined) {
if (Reflect.has(this.proConfig, key)) {
// console.log(key, value);
if (key === 'theme') {
// const themeColor = {
// light: theme.defaultAlgorithm,
// compact: theme.compactAlgorithm,
// dark: theme.darkAlgorithm,
// };
if (value === 'dark') {
document.documentElement.setAttribute('data-theme', 'dark');
this.themeConfig.algorithm = [theme.darkAlgorithm];
} else {
document.documentElement.setAttribute('data-theme', 'light');
this.themeConfig.algorithm = [theme.defaultAlgorithm];
}
}
Reflect.set(this.proConfig, key, value);
localSetJSON(CACHE_LOCAL_PROCONFIG, this.proConfig);
}
},
/**主题色初始化 */
initPrimaryColor() {
// 主题色初始化
this.changePrimaryColor(this.getColorPrimary);
// 明暗模式初始化
const themeMode = this.proConfig.theme;
document.documentElement.setAttribute('data-theme', themeMode);
this.changeConf('theme', themeMode);
},
/**
* 主题色变更
* @param color 颜色
*/
changePrimaryColor(color?: string) {
if (!color) {
color = getRandomColor();
}
if (this.themeConfig && this.themeConfig.token) {
this.themeConfig.token.colorPrimary = color;
localStorage.setItem(CACHE_LOCAL_PRIMARY_COLOR, color);
}
},
},
});

View File

@@ -1,7 +1,7 @@
import defaultAvatar from '@/assets/images/default_avatar.png';
import useLayoutStore from './layout';
import { login, logout, getInfo } from '@/api/login';
import { getToken, setToken, removeToken } from '@/plugins/auth-token';
import { setToken, removeToken } from '@/plugins/auth-token';
import { defineStore } from 'pinia';
import { TOKEN_RESPONSE_FIELD } from '@/constants/token-constants';
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
@@ -133,10 +133,10 @@ const useUserStore = defineStore('user', {
}
// 水印文字信息=用户昵称 手机号
let waterMarkContent = this.userName;
if (this.phonenumber) {
waterMarkContent = `${this.userName} ${this.phonenumber}`;
}
// let waterMarkContent = this.userName;
// if (this.phonenumber) {
// waterMarkContent = `${this.userName} ${this.phonenumber}`;
// }
// useLayoutStore().changeWaterMark(waterMarkContent);
useLayoutStore().changeWaterMark('');
}

View File

@@ -13,13 +13,41 @@ export function generateColorHEX(): string {
* @returns rgb(24 144 255) / rgba(0,0,0,.85)
*/
export function generateColorRGBA(hasAlpha: boolean = false) {
const red = Math.floor(Math.random() * 256);
const green = Math.floor(Math.random() * 256);
const blue = Math.floor(Math.random() * 256);
const isDark = document.documentElement.getAttribute('data-theme') === 'dark';
let red: number;
let green: number;
let blue: number;
if (isDark) {
// 暗色模式下生成较亮的颜色
red = Math.floor(Math.random() * 156) + 100; // 100-255
green = Math.floor(Math.random() * 156) + 100; // 100-255
blue = Math.floor(Math.random() * 156) + 100; // 100-255
// 确保至少有一个通道的值较高,使颜色更明亮
const brightChannel = Math.floor(Math.random() * 3);
switch (brightChannel) {
case 0:
red = Math.min(255, red + 50);
break;
case 1:
green = Math.min(255, green + 50);
break;
case 2:
blue = Math.min(255, blue + 50);
break;
}
} else {
// 亮色模式下生成正常的颜色
red = Math.floor(Math.random() * 256); // 0-255
green = Math.floor(Math.random() * 256); // 0-255
blue = Math.floor(Math.random() * 256); // 0-255
}
if (hasAlpha) {
const alpha = Math.floor(Math.random() * 100);
return `rgb(${red}, ${green}, ${blue}, 0.${alpha})`;
return `rgba(${red}, ${green}, ${blue}, 0.${alpha})`;
}
return `rgb(${red}, ${green}, ${blue})`;

View File

@@ -1,7 +1,7 @@
<script lang="ts" setup>
import { Modal, message } from 'ant-design-vue/lib';
import { FileType } from 'ant-design-vue/lib/upload/interface';
import { UploadRequestOption } from 'ant-design-vue/lib/vc-upload/interface';
import { Modal, message } from 'ant-design-vue/es';
import { FileType } from 'ant-design-vue/es/upload/interface';
import { UploadRequestOption } from 'ant-design-vue/es/vc-upload/interface';
import { onMounted, reactive, ref, toRaw } from 'vue';
import { updateUserProfile, uploadAvatar } from '@/api/profile';
import { regExpEmail, regExpMobile, regExpNick } from '@/utils/regular-utils';
@@ -27,7 +27,7 @@ let stateForm = reactive({
nickName: '',
email: '',
phonenumber: '',
sex: undefined,
sex: '0',
},
/**表单提交点击状态 */
formClick: false,

View File

@@ -1,5 +1,5 @@
<script lang="ts" setup>
import { Modal, message } from 'ant-design-vue/lib';
import { Modal, message } from 'ant-design-vue/es';
import { reactive } from 'vue';
import { updateUserPwd } from '@/api/profile';
import { regExpPasswd } from '@/utils/regular-utils';
@@ -147,7 +147,7 @@ function fnFinish() {
</a-input-password>
</a-form-item>
<a-form-item :wrapper-col="{ span: 3 }">
<a-form-item :wrapper-col="{ span: 4 }">
<a-button
block
type="primary"

View File

@@ -1,22 +1,32 @@
<script lang="ts" setup>
import { ref } from 'vue';
import { getLocalColor, changePrimaryColor } from '@/hooks/useTheme';
import { viewTransitionTheme } from 'antdv-pro-layout';
import useLayoutStore from '@/store/modules/layout';
import useI18n from '@/hooks/useI18n';
const { t } = useI18n();
const { proConfig, changeConf } = useLayoutStore();
const { proConfig, changeConf, themeConfig, changePrimaryColor } =
useLayoutStore();
let color = ref<string>(getLocalColor());
let timerId: any = null;
/**改变主题色 */
function fnColorChange(e: Event) {
const target = e.target as HTMLInputElement;
if (target.nodeName === 'INPUT') {
changePrimaryColor(target.value ?? '#1890ff');
} else {
changePrimaryColor();
}
color.value = getLocalColor();
// 需要防抖函数处理
clearTimeout(timerId);
timerId = setTimeout(() => {
if (target.nodeName === 'INPUT') {
changePrimaryColor(target.value ?? '#1890ff');
} else {
changePrimaryColor();
}
}, 300);
}
/**手动变更主题-过渡动画 */
function changeTheme(e: any) {
viewTransitionTheme(isDarkMode => {
changeConf('theme', isDarkMode ? 'light' : 'dark');
}, e);
}
</script>
@@ -56,13 +66,31 @@ function fnColorChange(e: Event) {
<template #extra>
<a-space :size="16" align="end" direction="horizontal">
<a-button type="primary" size="small" @click="fnColorChange">
<BgColorsOutlined />
{{ t('views.account.settings.colorRandomly') }}
</a-button>
<input type="color" :value="color" @input="fnColorChange" />
<input
type="color"
:value="themeConfig?.token?.colorPrimary"
@input="fnColorChange"
/>
</a-space>
</template>
</a-list-item>
<a-list-item>
{{ t('views.account.settings.theme') }}
<template #actions>
{{ t('views.account.settings.themeActions') }}
</template>
<template #extra>
<a-button
:type="proConfig.theme === 'dark' ? 'primary' : 'default'"
size="small"
@click="changeTheme"
>
{{ proConfig.theme }}
</a-button>
</template>
</a-list-item>
<a-list-item>
{{ t('views.account.settings.navTheme') }}
<template #actions>

View File

@@ -1,6 +1,6 @@
<script lang="ts" setup>
import { PageContainer } from 'antdv-pro-layout';
import { message } from 'ant-design-vue/lib';
import { message } from 'ant-design-vue/es';
import { getUserProfile } from '@/api/profile';
import { reactive, ref, onMounted } from 'vue';
import { parseDateToStr } from '@/utils/date-utils';
@@ -205,6 +205,7 @@ onMounted(() => {
display: flex;
flex-direction: column;
align-items: center;
padding: 16px 0;
&-no {
align-self: flex-start;
font-size: 14px;

View File

@@ -1,518 +0,0 @@
<script setup lang="ts">
import { reactive, ref, onMounted, toRaw } from 'vue';
import { PageContainer } from 'antdv-pro-layout';
import { Form, message, Modal } from 'ant-design-vue/lib';
import { SizeType } from 'ant-design-vue/lib/config-provider';
import { MenuInfo } from 'ant-design-vue/lib/menu/src/interface';
import { ColumnsType } from 'ant-design-vue/lib/table';
import { parseDateToStr } from '@/utils/date-utils';
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
import {
listNeBackup,
delNeBackup,
downloadNeBackup,
} from '@/api/configManage/backupManage';
import { saveAs } from 'file-saver';
import useI18n from '@/hooks/useI18n';
import { updateBackInfo } from '@/api/configManage/backupManage';
import useNeInfoStore from '@/store/modules/neinfo';
const { t } = useI18n();
/**查询参数 */
let queryParams = reactive({
/**网元类型 */
neType: '',
/**当前页数 */
pageNum: 1,
/**每页条数 */
pageSize: 20,
});
/**查询参数重置 */
function fnQueryReset() {
queryParams = Object.assign(queryParams, {
neType: '',
pageNum: 1,
pageSize: 20,
});
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: ColumnsType = [
{
title: t('common.rowId'),
dataIndex: 'id',
align: 'center',
width: 1,
},
{
title: t('views.configManage.backupManage.neType'),
dataIndex: 'neType',
align: 'center',
width: 2,
},
{
title: t('views.configManage.backupManage.neID'),
dataIndex: 'neId',
align: 'center',
width: 2,
},
{
title: t('views.configManage.backupManage.fileName'),
dataIndex: 'fileName',
align: 'center',
width: 3,
},
{
title: t('views.configManage.backupManage.remark'),
dataIndex: 'comment',
align: 'center',
width: 3,
},
{
title: t('views.configManage.backupManage.createAt'),
dataIndex: 'createTime',
align: 'center',
customRender(opt) {
if (!opt.value) return '';
return parseDateToStr(opt.value);
},
width: 3,
},
{
title: t('common.operate'),
key: 'id',
align: 'center',
fixed: 'right',
width: 2,
},
];
/**表格分页器参数 */
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 }),
onChange: (page: number, pageSize: number) => {
tablePagination.current = page;
tablePagination.pageSize = pageSize;
queryParams.pageNum = page;
queryParams.pageSize = pageSize;
fnGetList();
},
});
/**表格紧凑型变更操作 */
function fnTableSize({ key }: MenuInfo) {
tableState.size = key as SizeType;
}
/**信息文件下载 */
function fnDownloadFile(row: Record<string, any>) {
Modal.confirm({
title: t('common.tipTitle'),
content: t('views.configManage.backupManage.totalSure', {
oper: t('common.downloadText'),
id: row.id,
}),
onOk() {
const key = 'downloadNeBackup';
message.loading({ content: t('common.loading'), key });
downloadNeBackup(toRaw(row)).then(res => {
if (res.code === RESULT_CODE_SUCCESS) {
message.success({
content: t('common.msgSuccess', { msg: t('common.downloadText') }),
key,
duration: 2,
});
saveAs(res.data, `${row.fileName}`);
} else {
message.error({
content: `${res.msg}`,
key,
duration: 2,
});
}
});
},
});
}
/**
* 备份信息删除
* @param row 记录编号ID
*/
function fnRecordDelete(row: Record<string, any>) {
Modal.confirm({
title: t('common.tipTitle'),
content: t('views.configManage.backupManage.totalSure', {
oper: t('common.deleteText'),
id: row.id,
}),
onOk() {
const key = 'delNeBackup';
message.loading({ content: t('common.loading'), key });
delNeBackup(toRaw(row)).then(res => {
if (res.code === RESULT_CODE_SUCCESS) {
message.success({
content: t('common.msgSuccess', { msg: t('common.deleteText') }),
key,
duration: 2,
});
fnGetList();
} else {
message.error({
content: `${res.msg}`,
key: key,
duration: 2,
});
}
});
},
});
}
/**查询备份信息列表, pageNum初始页数 */
function fnGetList(pageNum?: number) {
if (tableState.loading) return;
tableState.loading = true;
if (pageNum) {
queryParams.pageNum = pageNum;
}
listNeBackup(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;
});
}
/**对话框对象信息状态类型 */
type ModalStateType = {
/**新增框或修改框是否显示 */
visibleByEdit: boolean;
/**标题 */
title: string;
/**表单数据 */
from: Record<string, any>;
/**确定按钮 loading */
confirmLoading: boolean;
};
/**对话框对象信息状态 */
let modalState: ModalStateType = reactive({
visibleByEdit: false,
title: '任务设置',
from: {
id: 0,
backupInfo: '',
},
confirmLoading: false,
});
/**
* 对话框弹出显示为 新增或者修改
* @param noticeId 网元id, 不传为新增
*/
function fnModalVisibleByEdit(row: Record<string, any>) {
if (modalState.confirmLoading) return;
modalState.from.backupInfo = row.comment;
modalState.from.id = row.id;
modalState.title = t('views.configManage.backupManage.edit');
modalState.visibleByEdit = true;
}
/**对话框内表单属性和校验规则 */
const modalStateFrom = Form.useForm(
modalState.from,
reactive({
backupInfo: [
{
required: true,
message:
t('views.configManage.backupManage.remark') + t('common.unableNull'),
},
],
})
);
/**
* 对话框弹出确认执行函数
* 进行表达规则校验
*/
function fnModalOk() {
modalStateFrom
.validate()
.then(e => {
modalState.confirmLoading = true;
const from = toRaw(modalState.from);
const hide = message.loading(t('common.loading'), 0);
updateBackInfo(from)
.then(res => {
if (res.code === RESULT_CODE_SUCCESS) {
message.success({
content: t('common.msgSuccess', { msg: modalState.title }),
duration: 3,
});
modalState.visibleByEdit = false;
modalStateFrom.resetFields();
fnGetList();
} else {
message.error({
content: `${res.msg}`,
duration: 3,
});
fnGetList();
}
})
.finally(() => {
hide();
modalState.confirmLoading = false;
});
})
.catch(e => {
message.error(t('common.errorFields', { num: e.errorFields.length }), 3);
});
}
/**
* 对话框弹出关闭执行函数
* 进行表达规则校验
*/
function fnModalCancel() {
modalState.visibleByEdit = false;
modalStateFrom.resetFields();
}
onMounted(() => {
// 获取列表数据
fnGetList();
});
</script>
<template>
<PageContainer>
<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.configManage.backupManage.neType')"
name="neType "
>
<a-auto-complete
v-model:value="queryParams.neType"
:options="useNeInfoStore().getNeSelectOtions"
allow-clear
:placeholder="t('views.configManage.backupManage.neTypePlease')"
/>
</a-form-item>
</a-col>
<a-col :lg="6" :md="12" :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-space>
</a-form-item>
</a-col>
</a-row>
</a-form>
</a-card>
<a-card :bordered="false" :body-style="{ padding: '0px' }">
<!-- 插槽-卡片左侧侧 -->
<template #title>
<a-space :size="8" align="center">
<!-- <a-button type="primary" @click.prevent="fnModalVisibleByEdit()">
<template #icon><FieldTimeOutlined /></template>
{{ t('views.configManage.backupManage.setBackupTask') }}
</a-button> -->
</a-space>
</template>
<!-- 插槽-卡片右侧 -->
<template #extra>
<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-tooltip>
<a-tooltip>
<template #title>{{ t('common.reloadText') }}</template>
<a-button type="text" @click.prevent="fnGetList(1)">
<template #icon><ReloadOutlined /></template>
</a-button>
</a-tooltip>
<a-tooltip>
<template #title>{{ t('common.sizeText') }}</template>
<a-dropdown trigger="click">
<a-button type="text">
<template #icon><ColumnHeightOutlined /></template>
</a-button>
<template #overlay>
<a-menu
:selected-keys="[tableState.size as string]"
@click="fnTableSize"
>
<a-menu-item key="default">
{{ t('common.size.default') }}
</a-menu-item>
<a-menu-item key="middle">
{{ t('common.size.middle') }}
</a-menu-item>
<a-menu-item key="small">
{{ t('common.size.small') }}
</a-menu-item>
</a-menu>
</template>
</a-dropdown>
</a-tooltip>
</a-space>
</template>
<!-- 表格列表 -->
<a-table
class="table"
row-key="id"
:columns="tableColumns"
:loading="tableState.loading"
:data-source="tableState.data"
:size="tableState.size"
:pagination="tablePagination"
:scroll="{ x: 1200, y: 400 }"
>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'id'">
<a-space :size="8" align="center">
<a-tooltip>
<template #title>{{ t('common.downloadText') }}</template>
<a-button type="link" @click.prevent="fnDownloadFile(record)">
<template #icon><DownloadOutlined /></template>
</a-button>
</a-tooltip>
<a-tooltip>
<template #title>{{ t('common.deleteText') }}</template>
<a-button type="link" @click.prevent="fnRecordDelete(record)">
<template #icon><DeleteOutlined /></template>
</a-button>
</a-tooltip>
<a-tooltip>
<template #title>{{ t('common.editText') }}</template>
<a-button
type="link"
@click.prevent="fnModalVisibleByEdit(record)"
>
<template #icon><FormOutlined /></template>
</a-button>
</a-tooltip>
</a-space>
</template>
</template>
</a-table>
</a-card>
<!-- 新增框或修改框 -->
<ProModal
:drag="true"
:width="800"
:destroyOnClose="true"
:keyboard="false"
:mask-closable="false"
:visible="modalState.visibleByEdit"
:title="modalState.title"
:confirm-loading="modalState.confirmLoading"
@ok="fnModalOk"
@cancel="fnModalCancel"
>
<a-form name="modalStateFrom" layout="horizontal">
<a-form-item
:label="t('views.configManage.backupManage.remark')"
name="backupInfo"
v-bind="modalStateFrom.validateInfos.backupInfo"
>
<a-textarea
v-model:value="modalState.from.backupInfo"
:auto-size="{ minRows: 2, maxRows: 6 }"
:maxlength="250"
:show-count="true"
/>
</a-form-item>
</a-form>
</ProModal>
</PageContainer>
</template>
<style lang="less" scoped>
.table :deep(.ant-pagination) {
padding: 0 24px;
}
</style>

View File

@@ -1,10 +1,11 @@
<script setup lang="ts">
import { reactive, onMounted, toRaw, ref } from 'vue';
import { PageContainer } from 'antdv-pro-layout';
import { message, Modal, Form } from 'ant-design-vue/lib';
import { SizeType } from 'ant-design-vue/lib/config-provider';
import { MenuInfo } from 'ant-design-vue/lib/menu/src/interface';
import { ColumnsType } from 'ant-design-vue/lib/table';
import { ProModal } from 'antdv-pro-modal';
import { message, Modal, Form } from 'ant-design-vue/es';
import { SizeType } from 'ant-design-vue/es/config-provider';
import { MenuInfo } from 'ant-design-vue/es/menu/src/interface';
import { ColumnsType } from 'ant-design-vue/es/table';
import {
listNeInfo,
getNeInfo,
@@ -20,8 +21,8 @@ import {
} from '@/api/configManage/neManage';
import { updateNeConfigReload } from '@/api/configManage/configParam';
import useI18n from '@/hooks/useI18n';
import { FileType } from 'ant-design-vue/lib/upload/interface';
import { UploadRequestOption } from 'ant-design-vue/lib/vc-upload/interface';
import { FileType } from 'ant-design-vue/es/upload/interface';
import { UploadRequestOption } from 'ant-design-vue/es/vc-upload/interface';
import TableColumnsDnd from '@/components/TableColumnsDnd/index.vue';
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
import { NE_TYPE_LIST } from '@/constants/ne-constants';
@@ -194,11 +195,11 @@ function fnTableSize({ key }: MenuInfo) {
/**对话框对象信息状态类型 */
type ModalStateType = {
/**详情框是否显示 */
visibleByView: boolean;
openByView: boolean;
/**新增框或修改框是否显示 */
visibleByEdit: boolean;
openByEdit: boolean;
/**导入是否显示 */
visibleByImport: boolean;
openByImport: boolean;
/**标题 */
title: string;
/**表单数据 */
@@ -211,9 +212,9 @@ type ModalStateType = {
/**对话框对象信息状态 */
let modalState: ModalStateType = reactive({
visibleByView: false,
visibleByEdit: false,
visibleByImport: false,
openByView: false,
openByEdit: false,
openByImport: false,
title: '网元',
from: {
id: undefined,
@@ -326,7 +327,7 @@ function fnModalVisibleByEdit(row?: Record<string, any>) {
if (!row) {
modalStateFrom.resetFields();
modalState.title = t('views.configManage.neManage.addNe');
modalState.visibleByEdit = true;
modalState.openByEdit = true;
} else {
if (modalState.confirmLoading) return;
const hide = message.loading(t('common.loading'), 0);
@@ -337,7 +338,7 @@ function fnModalVisibleByEdit(row?: Record<string, any>) {
if (res.code === RESULT_CODE_SUCCESS) {
modalState.from = Object.assign(modalState.from, res.data);
modalState.title = t('views.configManage.neManage.editNe');
modalState.visibleByEdit = true;
modalState.openByEdit = true;
} else {
message.error(t('views.configManage.neManage.getInfo'), 2);
}
@@ -370,7 +371,7 @@ function fnModalOk() {
content: t('common.msgSuccess', { msg: modalState.title }),
duration: 3,
});
modalState.visibleByEdit = false;
modalState.openByEdit = false;
modalStateFrom.resetFields();
fnGetList(1);
}
@@ -418,7 +419,7 @@ function fnImportModalOk() {
content: t('common.msgSuccess', { msg: modalState.title }),
duration: 3,
});
modalState.visibleByEdit = false;
modalState.openByEdit = false;
modalStateFrom.resetFields();
} else {
message.error({
@@ -444,8 +445,8 @@ function fnImportModalOk() {
* 进行表达规则校验
*/
function fnImportModalCancel() {
modalState.visibleByView = false;
modalState.visibleByImport = false;
modalState.openByView = false;
modalState.openByImport = false;
importStateFrom.resetFields();
}
@@ -454,8 +455,8 @@ function fnImportModalCancel() {
* 进行表达规则校验
*/
function fnModalCancel() {
modalState.visibleByEdit = false;
modalState.visibleByView = false;
modalState.openByEdit = false;
modalState.openByView = false;
modalStateFrom.resetFields();
}
@@ -707,7 +708,7 @@ function fnRecordMore(type: string | number, row: Record<string, any>) {
if (type === 'import') {
modalState.importFrom = Object.assign(modalState.importFrom, row);
modalState.title = t('views.configManage.neManage.import');
modalState.visibleByImport = true;
modalState.openByImport = true;
}
}
@@ -978,7 +979,7 @@ onMounted(() => {
:destroyOnClose="true"
:keyboard="false"
:mask-closable="false"
:visible="modalState.visibleByEdit"
:open="modalState.openByEdit"
:title="modalState.title"
:confirm-loading="modalState.confirmLoading"
@ok="fnModalOk"
@@ -990,7 +991,7 @@ onMounted(() => {
:label-col="{ span: 6 }"
:labelWrap="true"
>
<a-row :gutter="16">
<a-row>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
:label="t('views.configManage.neManage.neType')"
@@ -1007,7 +1008,7 @@ onMounted(() => {
<template #title>{{
t('views.configManage.neManage.neTypeTip')
}}</template>
<InfoCircleOutlined style="color: rgba(0, 0, 0, 0.45)" />
<InfoCircleOutlined style="opacity: 0.45; color: inherit;" />
</a-tooltip>
</template>
</a-input>
@@ -1028,7 +1029,7 @@ onMounted(() => {
</a-col>
</a-row>
<a-row :gutter="16">
<a-row>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
:label="t('views.configManage.neManage.uid')"
@@ -1068,7 +1069,7 @@ onMounted(() => {
</a-col>
</a-row>
<a-row :gutter="16">
<a-row>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
:label="t('views.configManage.neManage.ip')"
@@ -1090,7 +1091,7 @@ onMounted(() => {
<template #title>
<div>{{ t('views.configManage.neManage.portTip') }}</div>
</template>
<InfoCircleOutlined style="color: rgba(0, 0, 0, 0.45)" />
<InfoCircleOutlined style="opacity: 0.45; color: inherit;" />
</a-tooltip>
</template>
</a-input>
@@ -1098,7 +1099,7 @@ onMounted(() => {
</a-col>
</a-row>
<a-row :gutter="16">
<a-row>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
:label="t('views.configManage.neManage.neName')"
@@ -1120,14 +1121,14 @@ onMounted(() => {
<template #title>
<div>{{ t('views.configManage.neManage.macTip') }}</div>
</template>
<InfoCircleOutlined style="color: rgba(0, 0, 0, 0.45)" />
<InfoCircleOutlined style="opacity: 0.45; color: inherit;" />
</a-tooltip> </template
></a-input>
</a-form-item>
</a-col>
</a-row>
<a-row :gutter="16">
<a-row>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
:label="t('views.configManage.neManage.vendorName')"
@@ -1144,7 +1145,7 @@ onMounted(() => {
</a-col>
</a-row>
<a-row :gutter="16">
<a-row>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
:label="t('views.configManage.neManage.province')"
@@ -1179,14 +1180,14 @@ onMounted(() => {
:destroyOnClose="true"
:keyboard="false"
:mask-closable="false"
:visible="modalState.visibleByImport"
:open="modalState.openByImport"
:title="modalState.title"
:confirm-loading="modalState.confirmLoading"
@ok="fnImportModalOk"
@cancel="fnImportModalCancel"
>
<a-form name="importStateFrom" layout="horizontal">
<a-row :gutter="16">
<a-row>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
:label="t('views.configManage.neManage.neType')"

View File

@@ -1,7 +1,7 @@
<script setup lang="ts">
import { PageContainer } from 'antdv-pro-layout';
import { ColumnsType } from 'ant-design-vue/lib/table';
import { message } from 'ant-design-vue/lib';
import { ColumnsType } from 'ant-design-vue/es/table';
import { message } from 'ant-design-vue/es';
import { reactive, ref, onMounted, onBeforeUnmount, markRaw } from 'vue';
import useI18n from '@/hooks/useI18n';
import { TooltipComponent } from 'echarts/components';
@@ -108,10 +108,6 @@ let tableColumns: ColumnsType = [
type TabeStateType = {
/**加载等待 */
loading: boolean;
/**紧凑型 */
size: string;
/**搜索栏 */
seached: boolean;
/**记录数据 */
data: object[];
/**勾选记录 */
@@ -121,8 +117,6 @@ type TabeStateType = {
/**表格状态 */
let tableState: TabeStateType = reactive({
loading: false,
size: 'middle',
seached: false,
data: [],
selectedRowKeys: [],
});
@@ -247,9 +241,9 @@ function fnDesign(container: HTMLElement | undefined, option: any) {
}
/**抽屉 网元详细信息 */
const visible = ref(false);
const open = ref(false);
const closeDrawer = () => {
visible.value = false;
open.value = false;
};
/**抽屉 网元详细信息 */
@@ -301,7 +295,7 @@ function rowClick(record: any, index: any) {
expiryDate: pronData.expire,
};
}
visible.value = true;
open.value = true;
},
};
}
@@ -342,7 +336,7 @@ onBeforeUnmount(() => {
<template>
<PageContainer :breadcrumb="{}">
<div>
<a-drawer :visible="visible" @close="closeDrawer" :width="700">
<a-drawer :open="open" @close="closeDrawer" :width="700">
<a-descriptions bordered :column="1" :label-style="{ width: '160px' }">
<a-descriptions-item :label="t('views.index.hostName')">{{
pronInfo.hostName
@@ -356,6 +350,9 @@ onBeforeUnmount(() => {
<a-descriptions-item :label="t('views.index.version')">{{
pronInfo.version
}}</a-descriptions-item>
<a-descriptions-item :label="t('views.index.capability')">{{
pronInfo.capability
}}</a-descriptions-item>
<a-descriptions-item :label="t('views.index.cpuUse')">{{
pronInfo.cpuUse
}}</a-descriptions-item>
@@ -378,6 +375,7 @@ onBeforeUnmount(() => {
<a-table
class="table"
row-key="id"
size="small"
:columns="tableColumns"
:loading="tableState.loading"
:data-source="tableState.data"
@@ -398,10 +396,18 @@ onBeforeUnmount(() => {
</a-table>
</a-col>
<a-col :lg="10" :md="8" :xs="24">
<a-card :title="t('views.index.runStatus')" style="margin-bottom: 16px">
<a-card
:title="t('views.index.runStatus')"
style="margin-bottom: 16px"
size="small"
>
<div style="width: 100%; min-height: 200px" ref="statusBar"></div>
</a-card>
<a-card :title="t('views.index.mark')" style="margin-top: 16px">
<a-card
:title="t('views.index.mark')"
style="margin-top: 16px"
size="small"
>
<a-descriptions
bordered
:column="1"

View File

@@ -1,280 +0,0 @@
<script setup lang="ts">
import { reactive, toRaw, watch, ref } from 'vue';
import { SizeType } from 'ant-design-vue/lib/config-provider';
import { ColumnsType } from 'ant-design-vue/lib/table';
import { listNeVersion } from '@/api/configManage/softwareManage';
import { parseDateToStr } from '@/utils/date-utils';
import useNeInfoStore from '@/store/modules/neinfo';
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
import useI18n from '@/hooks/useI18n';
const { t } = useI18n();
const emit = defineEmits(['ok', 'cancel', 'update:visible']);
const props = defineProps({
title: {
type: String,
default: '标题',
},
visible: {
type: Boolean,
default: false,
},
});
/**开始结束时间 */
let queryRangePicker = ref<[string, string]>(['', '']);
/**查询参数 */
let queryParams = reactive({
/**网元类型 */
neType: '',
/**记录开始时间 */
beginTime: '',
/**记录结束时间 */
endTime: '',
/**状态 */
status: undefined,
/**当前页数 */
pageNum: 1,
/**每页条数 */
pageSize: 20,
});
/**查询参数重置 */
function fnQueryReset() {
queryRangePicker.value = ['', ''];
queryParams = Object.assign(queryParams, {
neType: '',
status: undefined,
beginTime: '',
endTime: '',
pageNum: 1,
pageSize: 20,
});
tablePagination.current = 1;
tablePagination.pageSize = 20;
fnGetList();
}
/**表格状态类型 */
type TabeStateType = {
/**加载等待 */
loading: boolean;
/**紧凑型 */
size: SizeType;
/**记录数据 */
data: object[];
/**勾选记录 */
selectedRowKeys: (string | number)[];
};
/**表格状态 */
let tableState: TabeStateType = reactive({
loading: false,
size: 'small',
data: [],
selectedRowKeys: [],
});
/**表格字段列 */
let tableColumns: ColumnsType = [
{
title: t('views.configManage.softwareManage.neType'),
dataIndex: 'neType',
align: 'center',
width: 100,
},
{
title: t('views.configManage.neManage.neId'),
dataIndex: 'neId',
align: 'center',
width: 200,
},
{
title: t('views.configManage.softwareManage.versions'),
dataIndex: 'version',
align: 'center',
},
{
title: t('views.configManage.softwareManage.upVersions'),
dataIndex: 'preVersion',
align: 'center',
},
{
title: t('views.configManage.softwareManage.backVersions'),
dataIndex: 'newVersion',
align: 'center',
},
{
title: t('views.configManage.softwareManage.status'),
dataIndex: 'status',
key: 'status',
align: 'center',
width: 100,
},
{
title: t('views.configManage.softwareManage.letUpTime'),
dataIndex: 'updateTime',
align: 'center',
customRender(opt) {
if (!opt.value) return '';
return parseDateToStr(opt.value);
},
width: 200,
},
];
/**表格分页器参数 */
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 }),
onChange: (page: number, pageSize: number) => {
tablePagination.current = page;
tablePagination.pageSize = pageSize;
queryParams.pageNum = page;
queryParams.pageSize = pageSize;
fnGetList();
},
});
/**查询角色未授权用户列表, pageNum初始页数 */
function fnGetList(pageNum?: number) {
if (tableState.loading) return;
tableState.loading = true;
if (pageNum) {
queryParams.pageNum = pageNum;
}
if (!queryRangePicker.value) {
queryRangePicker.value = ['', ''];
}
queryParams.beginTime = queryRangePicker.value[0];
queryParams.endTime = queryRangePicker.value[1];
listNeVersion(toRaw(queryParams)).then(res => {
if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.rows)) {
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('cancel');
}
/**显示弹框时初始数据 */
function init() {
// 查询参数重置
fnQueryReset();
}
/**监听是否显示,初始数据 */
watch(
() => props.visible,
val => {
if (val) init();
}
);
</script>
<template>
<ProModal
:drag="true"
:forceFullscreen="true"
:destroyOnClose="true"
:title="props.title"
:visible="props.visible"
:keyboard="false"
:mask-closable="false"
@cancel="fnModalCancel"
:footer="false"
>
<!-- 表格搜索栏 -->
<a-form :model="queryParams" name="queryParams" layout="horizontal">
<a-row :gutter="16">
<a-col :lg="6" :md="6" :xs="24">
<a-form-item
:label="t('views.configManage.softwareManage.neType')"
name="neType"
>
<a-auto-complete
v-model:value="queryParams.neType"
:options="useNeInfoStore().getNeSelectOtions"
allow-clear
:placeholder="t('views.configManage.softwareManage.neTypePlease')"
/>
</a-form-item>
</a-col>
<a-col :lg="6" :md="6" :xs="24">
<a-form-item
:label="t('views.configManage.softwareManage.createTime')"
name="queryRangePicker"
>
<a-range-picker
v-model:value="queryRangePicker"
allow-clear
bordered
value-format="YYYY-MM-DD"
style="width: 100%"
></a-range-picker>
</a-form-item>
</a-col>
<a-col :lg="6" :md="6" :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-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"
:scroll="{ x: true }"
:pagination="tablePagination"
>
</a-table>
</ProModal>
</template>
<style lang="less" scoped>
.table :deep(.ant-pagination) {
padding: 0 24px;
}
</style>

File diff suppressed because it is too large Load Diff

View File

@@ -1,10 +1,10 @@
<script setup lang="ts">
import { reactive, onMounted, toRaw, ref, onBeforeUnmount } from 'vue';
import { PageContainer } from 'antdv-pro-layout';
import { message, Modal } from 'ant-design-vue/lib';
import { SizeType } from 'ant-design-vue/lib/config-provider';
import { MenuInfo } from 'ant-design-vue/lib/menu/src/interface';
import { ColumnsType } from 'ant-design-vue/lib/table';
import { message, Modal } from 'ant-design-vue/es';
import { SizeType } from 'ant-design-vue/es/config-provider';
import { MenuInfo } from 'ant-design-vue/es/menu/src/interface';
import { ColumnsType } from 'ant-design-vue/es/table';
import TableColumnsDnd from '@/components/TableColumnsDnd/index.vue';
import useI18n from '@/hooks/useI18n';
import {

View File

@@ -1,10 +1,10 @@
<script setup lang="ts">
import { reactive, onMounted, toRaw, ref, onBeforeUnmount } from 'vue';
import { PageContainer } from 'antdv-pro-layout';
import { message, Modal } from 'ant-design-vue/lib';
import { SizeType } from 'ant-design-vue/lib/config-provider';
import { MenuInfo } from 'ant-design-vue/lib/menu/src/interface';
import { ColumnsType } from 'ant-design-vue/lib/table';
import { message, Modal } from 'ant-design-vue/es';
import { SizeType } from 'ant-design-vue/es/config-provider';
import { MenuInfo } from 'ant-design-vue/es/menu/src/interface';
import { ColumnsType } from 'ant-design-vue/es/table';
import TableColumnsDnd from '@/components/TableColumnsDnd/index.vue';
import useI18n from '@/hooks/useI18n';
import {

View File

@@ -1,10 +1,10 @@
<script setup lang="ts">
import { reactive, onMounted, toRaw, ref, onBeforeUnmount } from 'vue';
import { PageContainer } from 'antdv-pro-layout';
import { message, Modal } from 'ant-design-vue/lib';
import { SizeType } from 'ant-design-vue/lib/config-provider';
import { MenuInfo } from 'ant-design-vue/lib/menu/src/interface';
import { ColumnsType } from 'ant-design-vue/lib/table';
import { message, Modal } from 'ant-design-vue/es';
import { SizeType } from 'ant-design-vue/es/config-provider';
import { MenuInfo } from 'ant-design-vue/es/menu/src/interface';
import { ColumnsType } from 'ant-design-vue/es/table';
import useI18n from '@/hooks/useI18n';
import {
RESULT_CODE_ERROR,
@@ -27,9 +27,6 @@ const queue = new PQueue({ concurrency: 1, autoStart: true });
/**网元可选 */
let neOtions = ref<Record<string, any>[]>([]);
/**event Type */
let mmeEventType = ref<DictType[]>([]);
/**字典数据 */
let dict: {
/**UE 事件认证代码类型 */
@@ -432,13 +429,12 @@ onMounted(() => {
dict.ueAauthCode = resArr[0].value;
}
if (resArr[1].status === 'fulfilled') {
resArr[1].value.map(item => {
const realJson = JSON.parse(JSON.stringify(item));
if (realJson.value === 'cm-state') {
realJson.label = realJson.label.replace('CM', 'ECM');
const ueEventType: any[] = JSON.parse(JSON.stringify(resArr[1].value));
dict.ueEventType = ueEventType.map(item => {
if (item.value === 'cm-state') {
item.label = item.label.replace('CM', 'ECM');
}
mmeEventType.value.push(realJson);
return item;
});
}
if (resArr[2].status === 'fulfilled') {
@@ -525,7 +521,7 @@ onBeforeUnmount(() => {
<a-select
v-model:value="eventTypes"
mode="multiple"
:options="mmeEventType"
:options="dict.ueEventType"
:placeholder="t('common.selectPlease')"
@change="fnQueryEventTypeChange"
></a-select>
@@ -693,7 +689,7 @@ onBeforeUnmount(() => {
>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'eventType'">
<DictTag :options="mmeEventType" :value="record.eventType" />
<DictTag :options="dict.ueEventType" :value="record.eventType" />
</template>
<template v-if="column.key === 'result'">
<span v-if="record.eventType === 'auth-result'">
@@ -750,7 +746,7 @@ onBeforeUnmount(() => {
</div>
<div>
<span>{{ t('views.dashboard.ue.eventType') }}: </span>
<DictTag :options="mmeEventType" :value="record.eventType" />
<DictTag :options="dict.ueEventType" :value="record.eventType" />
</div>
<div>
<span>{{ t('views.dashboard.ue.result') }}: </span>

View File

@@ -1,13 +1,14 @@
<script setup lang="ts">
import { reactive, toRaw, watch } from 'vue';
import { ProModal } from 'antdv-pro-modal';
import { dbGetJSON, dbSetJSON } from '@/utils/cache-db-utils';
const emit = defineEmits(['ok', 'cancel', 'update:visible']);
const emit = defineEmits(['ok', 'cancel', 'update:open']);
const props = defineProps({
title: {
type: String,
default: '标题',
},
visible: {
open: {
type: Boolean,
default: false,
},
@@ -27,13 +28,13 @@ let dataState = reactive({
function fnModalOk() {
dbSetJSON('tbl_mocn', `tmp`, toRaw(dataState));
emit('ok');
emit('update:visible', false);
emit('update:open', false);
}
/**弹框取消按钮事件 */
function fnModalCancel() {
emit('cancel');
emit('update:visible', false);
emit('update:open', false);
}
/**显示弹框时初始数据 */
@@ -48,7 +49,7 @@ function init() {
/**监听是否显示,初始数据 */
watch(
() => props.visible,
() => props.open,
val => {
if (val) init();
}
@@ -60,7 +61,7 @@ watch(
:drag="true"
:width="800"
:title="props.title"
:visible="props.visible"
:open="props.open"
:keyboard="false"
:mask-closable="false"
@cancel="fnModalCancel"

View File

@@ -8,7 +8,7 @@ import Topology from '../overview/components/Topology/index.vue';
import NeResources from '../overview/components/NeResources/index.vue';
import UserActivity from '../overview/components/UserActivity/index.vue';
import AlarnTypeBar from './components/AlarnTypeBar/index.vue';
import setting from './components/setting.vue';
import Setting from './components/setting.vue';
import UPFFlow from '../overview/components/UPFFlow/index.vue';
import { listUDMSub } from '@/api/neData/udm_sub';
import { listUENumBySMF } from '@/api/neUser/smf';
@@ -208,7 +208,7 @@ onBeforeUnmount(() => {
/**MOCN状态 */
const mocnState = reactive({
title: 'Set MOCN Data',
visible: false,
open: false,
data: {
/**基站数 */
baseNum: 0,
@@ -220,7 +220,7 @@ const mocnState = reactive({
});
/**MOCN 右击设置 */
function fnRightClick() {
mocnState.visible = true;
mocnState.open = true;
}
</script>
@@ -543,9 +543,9 @@ function fnRightClick() {
</div>
</div>
</div>
<setting
<Setting
:title="mocnState.title"
v-model:visible="mocnState.visible"
v-model:open="mocnState.open"
></setting>
</div>
</template>

View File

@@ -2,9 +2,10 @@
import { onMounted, ref } from 'vue';
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
import { listAllNeInfo } from '@/api/ne/neInfo';
import { message } from 'ant-design-vue/lib';
import { message } from 'ant-design-vue/es';
import { getGraphData } from '@/api/monitor/topology';
import { Graph, GraphData, Tooltip } from '@antv/g6';
import { parseBasePath } from '@/plugins/file-static-url';
import { edgeLineAnimateState } from '@/views/monitor/topologyBuild/hooks/registerEdge';
import { nodeImageAnimateState } from '@/views/monitor/topologyBuild/hooks/registerNode';
import {
@@ -186,6 +187,12 @@ function fnGraphDataLoad(reload: boolean = false) {
const nf: Record<string, any>[] = nodes.filter(
(node: Record<string, any>) => {
Reflect.set(node, 'neState', { online: false });
// 图片路径处理
if (node.img) node.img = parseBasePath(node.img);
if (node.icon.show && node.icon?.img) {
node.icon.img = parseBasePath(node.icon.img);
}
// 遍历是否有网元数据
const nodeID: string = node.id;
const hasNe = res.neList.some(ne => {
Reflect.set(node, 'neInfo', ne.neType === nodeID ? ne : {});

View File

@@ -176,6 +176,7 @@ function loadData() {
clearInterval(interval10s.value);
interval10s.value = setInterval(() => {
if (!interval10s.value) return
if (upfTFActive.value === '0') {
upfTFSend('7');
upfTFActive.value = '7';
@@ -190,6 +191,7 @@ function loadData() {
clearInterval(interval5s.value);
interval5s.value = setInterval(() => {
if (!interval5s.value) return
fnGetSkim(); // 获取概览信息
fnGetNeState(); // 获取网元状态
}, 5_000);

View File

@@ -1,10 +1,10 @@
<script setup lang="ts">
import { reactive, onMounted, toRaw, onBeforeUnmount, ref } from 'vue';
import { PageContainer } from 'antdv-pro-layout';
import { Modal, message } from 'ant-design-vue/lib';
import { SizeType } from 'ant-design-vue/lib/config-provider';
import { MenuInfo } from 'ant-design-vue/lib/menu/src/interface';
import { ColumnsType } from 'ant-design-vue/lib/table';
import { Modal, message } from 'ant-design-vue/es';
import { SizeType } from 'ant-design-vue/es/config-provider';
import { MenuInfo } from 'ant-design-vue/es/menu/src/interface';
import { ColumnsType } from 'ant-design-vue/es/table';
import useNeInfoStore from '@/store/modules/neinfo';
import useI18n from '@/hooks/useI18n';
import {
@@ -16,7 +16,6 @@ import {
exportSMFDataCDR,
listSMFDataCDR,
} from '@/api/neData/smf';
import { parseDateToStr } from '@/utils/date-utils';
import { OptionsType, WS } from '@/plugins/ws-websocket';
import PQueue from 'p-queue';
import saveAs from 'file-saver';

View File

@@ -1,10 +1,10 @@
<script setup lang="ts">
import { reactive, onMounted, toRaw, ref, onBeforeUnmount } from 'vue';
import { PageContainer } from 'antdv-pro-layout';
import { message, Modal } from 'ant-design-vue/lib';
import { SizeType } from 'ant-design-vue/lib/config-provider';
import { MenuInfo } from 'ant-design-vue/lib/menu/src/interface';
import { ColumnsType } from 'ant-design-vue/lib/table';
import { message, Modal } from 'ant-design-vue/es';
import { SizeType } from 'ant-design-vue/es/config-provider';
import { MenuInfo } from 'ant-design-vue/es/menu/src/interface';
import { ColumnsType } from 'ant-design-vue/es/table';
import useDictStore from '@/store/modules/dict';
import useI18n from '@/hooks/useI18n';
import {

View File

@@ -1,10 +1,11 @@
<script setup lang="ts">
import { reactive, ref, onMounted, toRaw } from 'vue';
import { PageContainer } from 'antdv-pro-layout';
import { message, Modal } from 'ant-design-vue/lib';
import { SizeType } from 'ant-design-vue/lib/config-provider';
import { MenuInfo } from 'ant-design-vue/lib/menu/src/interface';
import { ColumnsType } from 'ant-design-vue/lib/table';
import { ProModal } from 'antdv-pro-modal';
import { message, Modal } from 'ant-design-vue/es';
import { SizeType } from 'ant-design-vue/es/config-provider';
import { MenuInfo } from 'ant-design-vue/es/menu/src/interface';
import { ColumnsType } from 'ant-design-vue/es/table';
import {
listAct,
updateConfirm,
@@ -328,15 +329,15 @@ function fnTableSize({ key }: MenuInfo) {
/**对话框对象信息状态类型 */
type ModalStateType = {
/**详情框是否显示 */
visibleByView: boolean;
openByView: boolean;
/**新增框或修改框是否显示 */
visibleByEdit: boolean;
openByEdit: boolean;
/**显示过滤设置是否显示 */
visibleByShowSet: boolean;
openByShowSet: boolean;
/**告警帮助文档是否显示 */
helpShowView: boolean;
/**个性化设置置是否显示 */
visibleByMyselfSet: boolean;
openByMyselfSet: boolean;
/**标题 */
title: string;
/**表单数据 */
@@ -349,11 +350,11 @@ type ModalStateType = {
/**对话框对象信息状态 */
let modalState: ModalStateType = reactive({
visibleByView: false,
visibleByEdit: false,
visibleByShowSet: false,
openByView: false,
openByEdit: false,
openByShowSet: false,
helpShowView: false,
visibleByMyselfSet: false,
openByMyselfSet: false,
title: '全部信息',
from: {
alarmId: '',
@@ -405,7 +406,7 @@ function fnModalVisibleByVive(row: Record<string, any>) {
modalState.title = t('views.faultManage.activeAlarm.viewIdInfo', {
alarmId: row.alarmId,
});
modalState.visibleByView = true;
modalState.openByView = true;
}
/** 告警帮助文档详细信息 */
@@ -434,7 +435,7 @@ function fnModalOk() {
duration: 3,
});
modalState.confirmLoading = false;
modalState.visibleByView = false;
modalState.openByView = false;
return false;
}
const result = updateConfirm(from);
@@ -446,7 +447,7 @@ function fnModalOk() {
content: t('common.msgSuccess', { msg: modalState.title }),
duration: 3,
});
modalState.visibleByView = false;
modalState.openByView = false;
fnGetList();
} else {
message.error({
@@ -476,7 +477,7 @@ function fnShowModalOk() {
content: t('common.msgSuccess', { msg: modalState.title }),
duration: 3,
});
modalState.visibleByShowSet = false;
modalState.openByShowSet = false;
fnGetList();
} else {
message.error({
@@ -604,7 +605,7 @@ function fnShowSet() {
: {};
modalState.showSetFrom = Object.assign(modalState.showSetFrom, realJson);
modalState.title = t('views.faultManage.activeAlarm.showSet');
modalState.visibleByShowSet = true;
modalState.openByShowSet = true;
} else {
message.error(t('common.getInfoFail'), 2);
}
@@ -617,11 +618,14 @@ function mapKeysWithReduce(data: any[], titleMapping: Record<string, string>) {
if (typeof item !== 'object' || item === null) {
return item; // 如果不是对象,直接返回原值
}
return Object.keys(item).reduce((newItem: Record<string, any>, key: string) => {
const title = titleMapping[key] || key;
newItem[title] = item[key];
return newItem;
}, {}); // 确保初始值是一个空对象
return Object.keys(item).reduce(
(newItem: Record<string, any>, key: string) => {
const title = titleMapping[key] || key;
newItem[title] = item[key];
return newItem;
},
{}
); // 确保初始值是一个空对象
});
}
@@ -704,9 +708,9 @@ function fnExportAll() {
* 进行表达规则校验
*/
function fnModalCancel() {
modalState.visibleByEdit = false;
modalState.visibleByView = false;
modalState.visibleByShowSet = false;
modalState.openByEdit = false;
modalState.openByView = false;
modalState.openByShowSet = false;
modalState.helpShowView = false;
}
@@ -837,7 +841,7 @@ onMounted(() => {
</a-form-item>
</a-col>
</a-row>
<a-row :gutter="16">
<a-row>
<a-col :lg="6" :md="12" :xs="24">
<a-form-item
:label="t('views.faultManage.activeAlarm.alarmCode')"
@@ -877,7 +881,7 @@ onMounted(() => {
</a-form-item>
</a-col>
</a-row>
<a-row :gutter="16">
<a-row>
<a-col :lg="6" :md="12" :xs="24">
<a-form-item
:label="t('views.faultManage.activeAlarm.pvFlag')"
@@ -912,7 +916,7 @@ onMounted(() => {
<a-card :bordered="false" :body-style="{ padding: '0px' }">
<!-- 插槽-卡片左侧侧 -->
<template #title>
<div class="button-container">
<a-space :size="8" align="center">
<a-button
type="primary"
@click.prevent="fnCancelConfirm()"
@@ -956,12 +960,12 @@ onMounted(() => {
<template #icon> <export-outlined /> </template>
{{ t('views.faultManage.activeAlarm.exportAll') }}
</a-button>
</div>
</a-space>
</template>
<!-- 插槽-卡片右侧 -->
<template #extra>
<div class="button-container">
<a-space :size="8" align="center">
<a-tooltip>
<template #title>{{ t('common.searchBarText') }}</template>
<a-switch
@@ -1006,7 +1010,7 @@ onMounted(() => {
:columns="tableColumns"
v-model:columns-dnd="tableColumnsDnd"
></TableColumnsDnd>
</div>
</a-space>
</template>
<!-- 表格列表 -->
@@ -1084,7 +1088,7 @@ onMounted(() => {
:destroyOnClose="true"
:keyboard="false"
:mask-closable="false"
:visible="modalState.helpShowView"
:open="modalState.helpShowView"
:title="modalState.title"
:confirm-loading="modalState.confirmLoading"
:body-style="{ padding: '0px' }"
@@ -1111,7 +1115,7 @@ onMounted(() => {
:body-style="{ height: '520px', overflowY: 'scroll' }"
:keyboard="false"
:mask-closable="false"
:visible="modalState.visibleByView"
:open="modalState.openByView"
:title="modalState.title"
:confirm-loading="modalState.confirmLoading"
@ok="fnModalOk"
@@ -1124,7 +1128,7 @@ onMounted(() => {
:label-col="{ span: 8 }"
:label-wrap="true"
>
<a-row :gutter="16">
<a-row>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
:label="t('views.faultManage.activeAlarm.alarmId')"
@@ -1143,7 +1147,7 @@ onMounted(() => {
</a-col>
</a-row>
<a-row :gutter="16">
<a-row>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
:label="t('views.faultManage.activeAlarm.neId')"
@@ -1162,7 +1166,7 @@ onMounted(() => {
</a-col>
</a-row>
<a-row :gutter="16">
<a-row>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
:label="t('views.faultManage.activeAlarm.neType')"
@@ -1181,7 +1185,7 @@ onMounted(() => {
</a-col>
</a-row>
<a-row :gutter="16">
<a-row>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
:label="t('views.faultManage.activeAlarm.alarmTitle')"
@@ -1200,7 +1204,7 @@ onMounted(() => {
</a-col>
</a-row>
<a-row :gutter="16">
<a-row>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
:label="t('views.faultManage.activeAlarm.alarmType')"
@@ -1227,9 +1231,9 @@ onMounted(() => {
{{ modalState.from.locationInfo }}
</a-form-item>
<a-row :gutter="16"> </a-row>
<a-row> </a-row>
<a-row :gutter="16">
<a-row>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
:label="t('views.faultManage.activeAlarm.province')"
@@ -1272,7 +1276,7 @@ onMounted(() => {
{{ modalState.from.specificProblem }}
</a-form-item>
<a-row :gutter="16">
<a-row>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
:label="t('views.faultManage.activeAlarm.ackUser')"
@@ -1291,7 +1295,7 @@ onMounted(() => {
</a-col>
</a-row>
<a-row :gutter="16">
<a-row>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
:label="t('views.faultManage.activeAlarm.ackTime')"
@@ -1318,7 +1322,7 @@ onMounted(() => {
:width="800"
:keyboard="false"
:mask-closable="false"
:visible="modalState.visibleByShowSet"
:open="modalState.openByShowSet"
:title="modalState.title"
:confirm-loading="modalState.confirmLoading"
@ok="fnShowModalOk"
@@ -1326,7 +1330,7 @@ onMounted(() => {
@cancel="fnModalCancel"
>
<a-form name="modalStateShowFrom" layout="horizontal">
<a-row :gutter="16">
<a-row>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
:label="t('views.faultManage.activeAlarm.neType')"
@@ -1351,7 +1355,7 @@ onMounted(() => {
</a-col>
</a-row>
<a-row :gutter="16">
<a-row>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
:label="t('views.faultManage.activeAlarm.pvFlag')"
@@ -1382,7 +1386,7 @@ onMounted(() => {
</a-form-item>
</a-col>
</a-row>
<a-row :gutter="16">
<a-row>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
:label="t('views.faultManage.activeAlarm.origLevel')"
@@ -1418,7 +1422,7 @@ onMounted(() => {
:width="800"
:keyboard="false"
:mask-closable="false"
:visible="modalState.visibleByMyselfSet"
:open="modalState.openByMyselfSet"
:title="modalState.title"
:confirm-loading="modalState.confirmLoading"
@ok="fnShowModalOk"
@@ -1426,7 +1430,7 @@ onMounted(() => {
@cancel="fnModalCancel"
>
<a-form name="modalStateShowFrom" layout="horizontal">
<a-row :gutter="16">
<a-row>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
:label="t('views.faultManage.activeAlarm.neType')"
@@ -1450,7 +1454,7 @@ onMounted(() => {
</a-col>
</a-row>
<a-row :gutter="16">
<a-row>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
:label="t('views.faultManage.activeAlarm.pvFlag')"
@@ -1481,7 +1485,7 @@ onMounted(() => {
</a-form-item>
</a-col>
</a-row>
<a-row :gutter="16">
<a-row>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
:label="t('views.faultManage.activeAlarm.origLevel')"

View File

@@ -1,10 +1,11 @@
<script setup lang="ts">
import { reactive, ref, onMounted, toRaw } from 'vue';
import { PageContainer } from 'antdv-pro-layout';
import { message, Modal } from 'ant-design-vue/lib';
import { SizeType } from 'ant-design-vue/lib/config-provider';
import { MenuInfo } from 'ant-design-vue/lib/menu/src/interface';
import { ColumnsType } from 'ant-design-vue/lib/table';
import { ProModal } from 'antdv-pro-modal';
import { message, Modal } from 'ant-design-vue/es';
import { SizeType } from 'ant-design-vue/es/config-provider';
import { MenuInfo } from 'ant-design-vue/es/menu/src/interface';
import { ColumnsType } from 'ant-design-vue/es/table';
import { listAct, exportAll } from '@/api/faultManage/eventAlarm';
import useI18n from '@/hooks/useI18n';
import useDictStore from '@/store/modules/dict';
@@ -211,13 +212,13 @@ function fnTableSize({ key }: MenuInfo) {
/**对话框对象信息状态类型 */
type ModalStateType = {
/**详情框是否显示 */
visibleByView: boolean;
openByView: boolean;
/**新增框或修改框是否显示 */
visibleByEdit: boolean;
openByEdit: boolean;
/**显示过滤设置是否显示 */
visibleByShowSet: boolean;
openByShowSet: boolean;
/**个性化设置置是否显示 */
visibleByMyselfSet: boolean;
openByMyselfSet: boolean;
/**标题 */
title: string;
/**表单数据 */
@@ -230,10 +231,10 @@ type ModalStateType = {
/**对话框对象信息状态 */
let modalState: ModalStateType = reactive({
visibleByView: false,
visibleByEdit: false,
visibleByShowSet: false,
visibleByMyselfSet: false,
openByView: false,
openByEdit: false,
openByShowSet: false,
openByMyselfSet: false,
title: '全部信息',
from: {
alarmId: '',
@@ -285,7 +286,7 @@ function fnModalVisibleByVive(row: Record<string, any>) {
modalState.title = t('views.faultManage.activeAlarm.viewIdInfo', {
alarmId: row.alarmId,
});
modalState.visibleByView = true;
modalState.openByView = true;
}
/**表格状态 */
@@ -310,8 +311,8 @@ const onSelectChange = (
// key替换中文title
function mapKeysWithReduce(data: any, titleMapping: any) {
return data.map((item:any) => {
return Object.keys(item).reduce((newItem:any, key:any) => {
return data.map((item: any) => {
return Object.keys(item).reduce((newItem: any, key: any) => {
const title = titleMapping[key] || key;
newItem[title] = item[key];
return newItem;
@@ -360,7 +361,7 @@ function fnExportAll() {
writeSheet(res.data, 'alarm', sortData).then(fileBlob => {
saveAs(fileBlob, `evnet_${Date.now()}.xlsx`);
message.success({
content: t('common.msgSuccess', { msg: t('common.export') }),
key,
@@ -384,8 +385,8 @@ function fnExportAll() {
* 进行表达规则校验
*/
function fnModalCancel() {
modalState.visibleByEdit = false;
modalState.visibleByView = false;
modalState.openByEdit = false;
modalState.openByView = false;
}
/**查询列表, pageNum初始页数 */
@@ -508,7 +509,7 @@ onMounted(() => {
</a-form-item>
</a-col>
</a-row>
<a-row :gutter="16">
<a-row>
<a-col :lg="6" :md="12" :xs="24">
<a-form-item
:label="t('views.faultManage.activeAlarm.alarmCode')"
@@ -550,7 +551,7 @@ onMounted(() => {
</a-form-item>
</a-col>
</a-row>
<a-row :gutter="16">
<a-row>
<a-col :lg="6" :md="12" :xs="24">
<a-form-item
:label="t('views.faultManage.activeAlarm.alarmType')"
@@ -570,7 +571,7 @@ onMounted(() => {
<a-card :bordered="false" :body-style="{ padding: '0px' }">
<!-- 插槽-卡片左侧侧 -->
<template #title>
<div class="button-container">
<a-space :size="8" align="center">
<a-button
type="primary"
@click.prevent="fnExportAll()"
@@ -579,12 +580,12 @@ onMounted(() => {
<template #icon> <export-outlined /> </template>
{{ t('views.faultManage.activeAlarm.exportAll') }}
</a-button>
</div>
</a-space>
</template>
<!-- 插槽-卡片右侧 -->
<template #extra>
<div class="button-container">
<a-space :size="8" align="center">
<a-tooltip>
<template #title>{{ t('common.searchBarText') }}</template>
<a-switch
@@ -629,7 +630,7 @@ onMounted(() => {
:columns="tableColumns"
v-model:columns-dnd="tableColumnsDnd"
></TableColumnsDnd>
</div>
</a-space>
</template>
<!-- 表格列表 -->
@@ -641,7 +642,7 @@ onMounted(() => {
:data-source="tableState.data"
:size="tableState.size"
:pagination="tablePagination"
:scroll="{ x: 2500, y: 400 }"
:scroll="{ x: tableColumns.length * 120, y: 400 }"
>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'origSeverity'">
@@ -689,7 +690,7 @@ onMounted(() => {
:body-style="{ height: '520px', overflowY: 'scroll' }"
:keyboard="false"
:mask-closable="false"
:visible="modalState.visibleByView"
:open="modalState.openByView"
:title="modalState.title"
:confirm-loading="modalState.confirmLoading"
@cancel="fnModalCancel"
@@ -706,7 +707,7 @@ onMounted(() => {
:label-col="{ span: 8 }"
:label-wrap="true"
>
<a-row :gutter="16">
<a-row>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
:label="t('views.faultManage.activeAlarm.alarmId')"
@@ -725,7 +726,7 @@ onMounted(() => {
</a-col>
</a-row>
<a-row :gutter="16">
<a-row>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
:label="t('views.faultManage.activeAlarm.neId')"
@@ -744,7 +745,7 @@ onMounted(() => {
</a-col>
</a-row>
<a-row :gutter="16">
<a-row>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
:label="t('views.faultManage.activeAlarm.neType')"
@@ -763,7 +764,7 @@ onMounted(() => {
</a-col>
</a-row>
<a-row :gutter="16">
<a-row>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
:label="t('views.faultManage.activeAlarm.alarmTitle')"
@@ -790,9 +791,7 @@ onMounted(() => {
{{ modalState.from.locationInfo }}
</a-form-item>
<a-row :gutter="16"> </a-row>
<a-row :gutter="16">
<a-row>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
:label="t('views.faultManage.activeAlarm.province')"
@@ -819,7 +818,7 @@ onMounted(() => {
{{ modalState.from.addInfo }}
</a-form-item>
<a-row :gutter="16">
<a-row>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
:label="t('views.faultManage.activeAlarm.specificProblemId')"

View File

@@ -1,7 +1,7 @@
<script setup lang="ts">
import { reactive, onMounted, toRaw } from 'vue';
import { PageContainer } from 'antdv-pro-layout';
import { Form, message } from 'ant-design-vue/lib';
import { Form, message } from 'ant-design-vue/es';
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
import {
getForwardSet,
@@ -177,7 +177,7 @@ onMounted(() => {
<template>
<PageContainer>
<a-row :gutter="16">
<a-row>
<a-col :span="8" v-if="false">
<!-- 日志设置 -->
<a-card :title="alarmState.title" :loading="alarmState.fromLoading">

View File

@@ -1,10 +1,11 @@
<script setup lang="ts">
import { reactive, ref, onMounted, toRaw } from 'vue';
import { PageContainer } from 'antdv-pro-layout';
import { message, Modal } from 'ant-design-vue/lib';
import { SizeType } from 'ant-design-vue/lib/config-provider';
import { MenuInfo } from 'ant-design-vue/lib/menu/src/interface';
import { ColumnsType } from 'ant-design-vue/lib/table';
import { ProModal } from 'antdv-pro-modal';
import { message, Modal } from 'ant-design-vue/es';
import { SizeType } from 'ant-design-vue/es/config-provider';
import { MenuInfo } from 'ant-design-vue/es/menu/src/interface';
import { ColumnsType } from 'ant-design-vue/es/table';
import {
listAct,
updateConfirm,
@@ -262,13 +263,13 @@ function fnTableSize({ key }: MenuInfo) {
/**对话框对象信息状态类型 */
type ModalStateType = {
/**详情框是否显示 */
visibleByView: boolean;
openByView: boolean;
/**新增框或修改框是否显示 */
visibleByEdit: boolean;
openByEdit: boolean;
/**显示过滤设置是否显示 */
visibleByShowSet: boolean;
openByShowSet: boolean;
/**个性化设置置是否显示 */
visibleByMyselfSet: boolean;
openByMyselfSet: boolean;
/**标题 */
title: string;
/**表单数据 */
@@ -281,10 +282,10 @@ type ModalStateType = {
/**对话框对象信息状态 */
let modalState: ModalStateType = reactive({
visibleByView: false,
visibleByEdit: false,
visibleByShowSet: false,
visibleByMyselfSet: false,
openByView: false,
openByEdit: false,
openByShowSet: false,
openByMyselfSet: false,
title: '全部信息',
from: {
alarmId: '',
@@ -336,7 +337,7 @@ function fnModalVisibleByVive(row: Record<string, any>) {
modalState.title = t('views.faultManage.activeAlarm.viewIdInfo', {
alarmId: row.alarmId,
});
modalState.visibleByView = true;
modalState.openByView = true;
}
/**
@@ -351,7 +352,7 @@ function fnModalOk() {
duration: 3,
});
modalState.confirmLoading = false;
modalState.visibleByView = false;
modalState.openByView = false;
return false;
}
const result = updateConfirm(from);
@@ -363,7 +364,7 @@ function fnModalOk() {
content: t('common.msgSuccess', { msg: modalState.title }),
duration: 3,
});
modalState.visibleByView = false;
modalState.openByView = false;
fnGetList();
} else {
message.error({
@@ -430,13 +431,16 @@ function fnCancelConfirm() {
function mapKeysWithReduce(data: any[], titleMapping: Record<string, string>) {
return data.map((item: any) => {
if (typeof item !== 'object' || item === null) {
return item;
return item;
}
return Object.keys(item).reduce((newItem: Record<string, any>, key: string) => {
const title = titleMapping[key] || key;
newItem[title] = item[key];
return newItem;
}, {});
return Object.keys(item).reduce(
(newItem: Record<string, any>, key: string) => {
const title = titleMapping[key] || key;
newItem[title] = item[key];
return newItem;
},
{}
);
});
}
@@ -518,9 +522,9 @@ function fnExportAll() {
* 进行表达规则校验
*/
function fnModalCancel() {
modalState.visibleByEdit = false;
modalState.visibleByView = false;
modalState.visibleByShowSet = false;
modalState.openByEdit = false;
modalState.openByView = false;
modalState.openByShowSet = false;
}
/**查询列表, pageNum初始页数 */
@@ -644,7 +648,7 @@ onMounted(() => {
</a-form-item>
</a-col>
</a-row>
<a-row :gutter="16">
<a-row>
<a-col :lg="6" :md="12" :xs="24">
<a-form-item
:label="t('views.faultManage.activeAlarm.alarmCode')"
@@ -684,7 +688,7 @@ onMounted(() => {
</a-form-item>
</a-col>
</a-row>
<a-row :gutter="16">
<a-row>
<a-col :lg="6" :md="12" :xs="24">
<a-form-item
:label="t('views.faultManage.activeAlarm.pvFlag')"
@@ -805,7 +809,7 @@ onMounted(() => {
onChange: onSelectChange,
}"
:pagination="tablePagination"
:scroll="{ x: 2500, y: 400 }"
:scroll="{ x: tableColumns.length * 120, y: 400 }"
>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'origSeverity'">
@@ -853,7 +857,7 @@ onMounted(() => {
:body-style="{ height: '520px', overflowY: 'scroll' }"
:keyboard="false"
:mask-closable="false"
:visible="modalState.visibleByView"
:open="modalState.openByView"
:title="modalState.title"
:confirm-loading="modalState.confirmLoading"
@ok="fnModalOk"
@@ -865,7 +869,7 @@ onMounted(() => {
layout="horizontal"
:label-col="{ span: 8 }"
>
<a-row :gutter="16">
<a-row>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
:label="t('views.faultManage.activeAlarm.alarmId')"
@@ -884,7 +888,7 @@ onMounted(() => {
</a-col>
</a-row>
<a-row :gutter="16">
<a-row>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
:label="t('views.faultManage.activeAlarm.neId')"
@@ -903,7 +907,7 @@ onMounted(() => {
</a-col>
</a-row>
<a-row :gutter="16">
<a-row>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
:label="t('views.faultManage.activeAlarm.neType')"
@@ -922,7 +926,7 @@ onMounted(() => {
</a-col>
</a-row>
<a-row :gutter="16">
<a-row>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
:label="t('views.faultManage.activeAlarm.alarmTitle')"
@@ -941,7 +945,7 @@ onMounted(() => {
</a-col>
</a-row>
<a-row :gutter="16">
<a-row>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
:label="t('views.faultManage.activeAlarm.pvFlag')"
@@ -968,7 +972,7 @@ onMounted(() => {
>
{{ modalState.from.locationInfo }}
</a-form-item>
<a-row :gutter="16">
<a-row>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
:label="t('views.faultManage.activeAlarm.province')"
@@ -1009,7 +1013,7 @@ onMounted(() => {
>
{{ modalState.from.specificProblem }}
</a-form-item>
<a-row :gutter="16">
<a-row>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
:label="t('views.faultManage.activeAlarm.clearType')"
@@ -1028,7 +1032,7 @@ onMounted(() => {
</a-col>
</a-row>
<a-row :gutter="16">
<a-row>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
:label="t('views.faultManage.activeAlarm.ackUser')"
@@ -1047,7 +1051,7 @@ onMounted(() => {
</a-col>
</a-row>
<a-row :gutter="16">
<a-row>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
:label="t('views.faultManage.activeAlarm.ackTime')"

View File

@@ -1,9 +1,9 @@
<script setup lang="ts">
import { reactive, ref, onMounted, toRaw } from 'vue';
import { PageContainer } from 'antdv-pro-layout';
import { SizeType } from 'ant-design-vue/lib/config-provider';
import { MenuInfo } from 'ant-design-vue/lib/menu/src/interface';
import { ColumnsType } from 'ant-design-vue/lib/table';
import { SizeType } from 'ant-design-vue/es/config-provider';
import { MenuInfo } from 'ant-design-vue/es/menu/src/interface';
import { ColumnsType } from 'ant-design-vue/es/table';
import { parseDateToStr } from '@/utils/date-utils';
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
import { listAlarm } from '@/api/logManage/alarm';

View File

@@ -1,9 +1,9 @@
<script setup lang="ts">
import { reactive, ref, onMounted, toRaw } from 'vue';
import { PageContainer } from 'antdv-pro-layout';
import { SizeType } from 'ant-design-vue/lib/config-provider';
import { ColumnsType } from 'ant-design-vue/lib/table';
import { Modal, message } from 'ant-design-vue/lib';
import { SizeType } from 'ant-design-vue/es/config-provider';
import { ColumnsType } from 'ant-design-vue/es/table';
import { Modal, message } from 'ant-design-vue/es';
import { parseDateToStr } from '@/utils/date-utils';
import {
getBakFile,
@@ -277,34 +277,27 @@ onMounted(() => {
<!-- 插槽-卡片左侧侧 -->
<template #title>
<a-form :model="queryParams" name="queryParams" layout="horizontal">
<a-row :gutter="16">
<a-col :lg="8" :md="12" :xs="24">
<a-form-item
:label="t('views.logManage.exportFile.fileName')"
name="fileName"
style="margin-bottom: 0"
>
<a-select
v-model:value="logSelect"
:options="fileList"
@change="fnNeChange"
:allow-clear="false"
/>
</a-form-item>
<a-row :gutter="16" align="middle">
<a-col>
<span>{{ t('views.logManage.exportFile.fileName') }}:</span>&nbsp;
<a-select
v-model:value="logSelect"
:options="fileList"
@change="fnNeChange"
:allow-clear="false"
style="width: 200px"
/>
</a-col>
<a-col :lg="16" :md="18" :xs="24" v-if="queryParams.path">
<a-form-item
:label="t('views.logManage.neFile.nePath')"
name="configName"
style="margin-bottom: 0"
>
<template v-if="queryParams.path">
<span>{{ t('views.logManage.neFile.nePath') }}:</span>&nbsp;
<a-col>
<a-breadcrumb>
<a-breadcrumb-item>
{{ queryParams.path }}
</a-breadcrumb-item>
</a-breadcrumb>
</a-form-item>
</a-col>
</a-col>
</template>
</a-row>
</a-form>
</template>

View File

@@ -1,9 +1,9 @@
<script setup lang="ts">
import { reactive, ref, onMounted, toRaw } from 'vue';
import { PageContainer } from 'antdv-pro-layout';
import { SizeType } from 'ant-design-vue/lib/config-provider';
import { MenuInfo } from 'ant-design-vue/lib/menu/src/interface';
import { ColumnsType } from 'ant-design-vue/lib/table';
import { SizeType } from 'ant-design-vue/es/config-provider';
import { MenuInfo } from 'ant-design-vue/es/menu/src/interface';
import { ColumnsType } from 'ant-design-vue/es/table';
import { parseDateToStr } from '@/utils/date-utils';
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
import { listForwarding } from '@/api/logManage/forwarding';

View File

@@ -1,7 +1,7 @@
<script setup lang="ts">
import { reactive, ref, onMounted, toRaw } from 'vue';
import { PageContainer } from 'antdv-pro-layout';
import { Form, Modal, message } from 'ant-design-vue/lib';
import { Form, Modal, message } from 'ant-design-vue/es';
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
import {
backupDownload,
@@ -411,7 +411,7 @@ onMounted(() => {
<template>
<PageContainer>
<a-row :gutter="16">
<a-row>
<a-col :span="8">
<!-- 日志设置 -->
<a-card :title="logSetState.title" :loading="logSetState.fromLoading">

View File

@@ -1,9 +1,9 @@
<script setup lang="ts">
import { reactive, ref, onMounted, toRaw } from 'vue';
import { PageContainer } from 'antdv-pro-layout';
import { SizeType } from 'ant-design-vue/lib/config-provider';
import { MenuInfo } from 'ant-design-vue/lib/menu/src/interface';
import { ColumnsType } from 'ant-design-vue/lib/table';
import { SizeType } from 'ant-design-vue/es/config-provider';
import { MenuInfo } from 'ant-design-vue/es/menu/src/interface';
import { ColumnsType } from 'ant-design-vue/es/table';
import { parseDateToStr } from '@/utils/date-utils';
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
import { listMML } from '@/api/logManage/mml';
@@ -62,12 +62,12 @@ let tableState: TabeStateType = reactive({
});
/**表格字段列 */
let tableColumns: ColumnsType = [
let tableColumns: ColumnsType = reactive([
{
title: t('common.rowId'),
dataIndex: 'id',
align: 'left',
width: 100,
width: 80,
},
{
title: t('views.logManage.mml.account'),
@@ -108,9 +108,9 @@ let tableColumns: ColumnsType = [
dataIndex: 'mml',
key: 'mml',
align: 'left',
width: 200,
ellipsis: true,
},
];
]);
/**表格分页器参数 */
let tablePagination = reactive({
@@ -161,7 +161,11 @@ function fnGetList(pageNum?: number) {
if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.rows)) {
tablePagination.total = res.total;
tableState.data = res.rows;
if (tablePagination.total <=(queryParams.pageNum - 1) * tablePagination.pageSize &&queryParams.pageNum !== 1) {
if (
tablePagination.total <=
(queryParams.pageNum - 1) * tablePagination.pageSize &&
queryParams.pageNum !== 1
) {
tableState.loading = false;
fnGetList(queryParams.pageNum - 1);
}
@@ -289,16 +293,15 @@ onMounted(() => {
:loading="tableState.loading"
:data-source="tableState.data"
:size="tableState.size"
:pagination="tablePagination"
:scroll="{ x: tableColumns.length * 100 }"
:pagination="tablePagination"
>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'mml'">
<!-- <template v-if="column.key === 'mml'">
<a-tooltip placement="topLeft">
<template #title>{{ record.result }}</template>
<div class="mmlText">{{ record.mml }}</div>
</a-tooltip>
</template>
</template> -->
</template>
</a-table>
</a-card>

View File

@@ -4,9 +4,9 @@ import { ProModal } from 'antdv-pro-modal';
import TerminalSSHView from '@/components/TerminalSSHView/index.vue';
import useI18n from '@/hooks/useI18n';
const { t } = useI18n();
const emit = defineEmits(['ok', 'cancel', 'update:visible']);
const emit = defineEmits(['ok', 'cancel', 'update:open']);
const props = defineProps({
visible: {
open: {
type: Boolean,
default: false,
required: true,
@@ -34,7 +34,7 @@ const props = defineProps({
/**对话框对象信息状态类型 */
type StateType = {
/**框是否显示 */
visible: boolean;
open: boolean;
/**标题 */
title: string;
/**查看命令 */
@@ -43,7 +43,7 @@ type StateType = {
/**对话框对象信息状态 */
let state: StateType = reactive({
visible: false,
open: false,
title: '文件查看',
form: {
follow: true,
@@ -54,21 +54,21 @@ let state: StateType = reactive({
});
function onClose() {
state.visible = false;
state.open = false;
emit('cancel');
emit('update:visible', false);
emit('update:open', false);
}
/**监听是否显示,初始数据 */
watch(
() => props.visible,
() => props.open,
val => {
if (val) {
if (props.neType && props.neId) {
const filePath = props.filePath;
const fileName = filePath.substring(filePath.lastIndexOf('/') + 1);
state.title = fileName;
state.visible = true;
state.open = true;
}
}
}
@@ -114,9 +114,9 @@ function fnReload() {
:destroyOnClose="true"
:keyboard="false"
:mask-closable="false"
:visible="state.visible"
:open="state.open"
:title="state.title"
:body-style="{ padding: '12px', overflow: 'hidden' }"
:body-style="{ overflow: 'hidden' }"
:footer="null"
@cancel="onClose"
>
@@ -132,7 +132,7 @@ function fnReload() {
></TerminalSSHView>
<!-- 命令控制属性 -->
<a-form name="form" layout="horizontal">
<a-row :gutter="16">
<a-row>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item :label="t('views.logManage.neFile.viewAs')">
<a-input-group compact>

View File

@@ -1,9 +1,9 @@
<script setup lang="ts">
import { reactive, ref, onMounted, toRaw } from 'vue';
import { PageContainer } from 'antdv-pro-layout';
import { SizeType } from 'ant-design-vue/lib/config-provider';
import { ColumnsType } from 'ant-design-vue/lib/table';
import { Modal, message } from 'ant-design-vue/lib';
import { SizeType } from 'ant-design-vue/es/config-provider';
import { ColumnsType } from 'ant-design-vue/es/table';
import { Modal, message } from 'ant-design-vue/es';
import { parseDateToStr } from '@/utils/date-utils';
import { getNeFile, listNeFiles } from '@/api/tool/neFile';
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
@@ -260,7 +260,7 @@ function fnGetList(pageNum?: number) {
/**抽屉状态 */
const viewDrawerState = reactive({
visible: false,
open: false,
/**文件路径 /var/log/amf.log */
filePath: '',
/**网元类型 */
@@ -274,7 +274,7 @@ function fnDrawerOpen(row: Record<string, any>) {
viewDrawerState.filePath = [...nePathArr.value, row.fileName].join('/');
viewDrawerState.neType = neTypeSelect.value[0];
viewDrawerState.neId = neTypeSelect.value[1];
viewDrawerState.visible = !viewDrawerState.visible;
viewDrawerState.open = !viewDrawerState.open;
}
onMounted(() => {
@@ -300,43 +300,33 @@ onMounted(() => {
<a-card :bordered="false" :body-style="{ padding: '0px' }">
<!-- 插槽-卡片左侧侧 -->
<template #title>
<a-form :model="queryParams" name="queryParams" layout="horizontal">
<a-row :gutter="16">
<a-col :lg="8" :md="12" :xs="24">
<a-form-item
:label="t('views.logManage.neFile.neType')"
name="neType"
style="margin-bottom: 0"
>
<a-cascader
v-model:value="neTypeSelect"
:options="neInfoStore.getNeCascaderOptions"
@change="fnNeChange"
:allow-clear="false"
:placeholder="t('views.logManage.neFile.neTypePlease')"
:disabled="downLoading || tableState.loading"
/>
</a-form-item>
<a-row :gutter="16" align="middle">
<a-col>
<span>{{ t('views.logManage.neFile.neType') }}:</span>&nbsp;
<a-cascader
v-model:value="neTypeSelect"
:options="neInfoStore.getNeCascaderOptions"
@change="fnNeChange"
:allow-clear="false"
:placeholder="t('views.logManage.neFile.neTypePlease')"
:disabled="downLoading || tableState.loading"
/>
</a-col>
<template v-if="nePathArr.length > 0">
<span>{{ t('views.logManage.neFile.nePath') }}:</span>&nbsp;
<a-col>
<a-breadcrumb>
<a-breadcrumb-item
v-for="(path, index) in nePathArr"
:key="path"
@click="fnDirCD(path, index)"
>
{{ path }}
</a-breadcrumb-item>
</a-breadcrumb>
</a-col>
<a-col :lg="16" :md="18" :xs="24" v-if="nePathArr.length > 0">
<a-form-item
:label="t('views.logManage.neFile.nePath')"
name="configName"
style="margin-bottom: 0"
>
<a-breadcrumb>
<a-breadcrumb-item
v-for="(path, index) in nePathArr"
:key="path"
@click="fnDirCD(path, index)"
>
{{ path }}
</a-breadcrumb-item>
</a-breadcrumb>
</a-form-item>
</a-col>
</a-row>
</a-form>
</template>
</a-row>
</template>
<!-- 插槽-卡片右侧 -->
@@ -397,7 +387,7 @@ onMounted(() => {
<!-- 文件内容查看抽屉 -->
<ViewDrawer
v-model:visible="viewDrawerState.visible"
v-model:open="viewDrawerState.open"
:file-path="viewDrawerState.filePath"
:ne-type="viewDrawerState.neType"
:ne-id="viewDrawerState.neId"

View File

@@ -1,15 +1,19 @@
<script lang="ts" setup>
import { message } from 'ant-design-vue/lib';
import { reactive, onMounted, computed } from 'vue';
import svgLight from '@/assets/svg/light.svg';
import svgDark from '@/assets/svg/dark.svg';
import { message } from 'ant-design-vue/es';
import { reactive, onMounted, computed, toRaw } from 'vue';
import useUserStore from '@/store/modules/user';
import useAppStore from '@/store/modules/app';
import { getCaptchaImage } from '@/api/login';
import { useRouter, useRoute } from 'vue-router';
import useI18n from '@/hooks/useI18n';
import { toRaw } from 'vue';
import useLayoutStore from '@/store/modules/layout';
import { viewTransitionTheme } from 'antdv-pro-layout';
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
import { parseUrlPath } from '@/plugins/file-static-url';
const { t, changeLocale, optionsLocale, currentLocale } = useI18n();
const { t, changeLocale, optionsLocale } = useI18n();
const layoutStore = useLayoutStore();
const appStore = useAppStore();
const router = useRouter();
const route = useRoute();
@@ -85,28 +89,12 @@ function fnGetCaptcha() {
});
}
// LOGO地址
const logoUrl = computed(() => {
let url =
appStore.logoType === 'brand'
? parseUrlPath(appStore.filePathBrand)
: parseUrlPath(appStore.filePathIcon);
if (url.indexOf('{language}') === -1) {
return url;
}
// 语言参数替换
const local = currentLocale.value;
const lang = local.split('_')[0];
return url.replace('{language}', lang);
});
// 判断是否有背景地址
const calcBG = computed(() => {
const bgURL = parseUrlPath(appStore.loginBackground);
if (bgURL && bgURL !== '#') {
return {
backgroundImage: `url(${bgURL})`,
backgroundImage: `url('${bgURL}')`,
backgroundPosition: 'center',
backgroundSize: 'cover',
};
@@ -125,6 +113,13 @@ function fnLocale() {
appStore.setTitle(title);
}
/**改变主题色 */
function fnClickTheme(e: any) {
viewTransitionTheme(isDarkMode => {
layoutStore.changeConf('theme', isDarkMode ? 'light' : 'dark');
}, e);
}
onMounted(() => {
fnLocale();
fnGetCaptcha();
@@ -146,21 +141,9 @@ function fnChangeLocale(e: any) {
<div class="animation animation5"></div>
</section>
<header class="header">
<div class="header-left">
<template v-if="appStore.logoType === 'icon'">
<img :src="logoUrl" class="logo-icon" :alt="appStore.appName" />
<span class="title">{{ appStore.appName }}</span>
</template>
<template v-if="appStore.logoType === 'brand'">
<img :src="logoUrl" class="logo-brand" :alt="appStore.appName" />
</template>
</div>
</header>
<a-card :bordered="false" class="login-card">
<div class="desc">
{{ t('common.desc') }}
<div class="title">
{{ t('common.title') }}
</div>
<a-form :model="state.from" name="stateFrom" @finish="fnFinish">
<a-form-item
@@ -209,7 +192,7 @@ function fnChangeLocale(e: any) {
</a-input-password>
</a-form-item>
<a-row :gutter="8" v-if="state.captcha.enabled">
<a-row v-if="state.captcha.enabled">
<a-col :span="16">
<a-form-item
name="code"
@@ -247,7 +230,6 @@ function fnChangeLocale(e: any) {
</a-row>
<a-row
:gutter="8"
justify="space-between"
align="middle"
style="margin-bottom: 16px"
@@ -274,18 +256,26 @@ function fnChangeLocale(e: any) {
{{ t('views.login.loginBtn') }}
</a-button>
<a-row
:gutter="8"
justify="space-between"
align="middle"
style="margin-top: 18px"
v-if="appStore.i18nOpen"
>
<a-col :offset="18" :span="6">
<a-dropdown trigger="click">
<a-button size="small" type="default">
{{ t('i18n') }}
<DownOutlined />
<a-row justify="end" align="middle" style="margin-top: 18px">
<a-col :span="3">
<a-tooltip placement="bottomRight">
<template #title>{{ t('loayouts.rightContent.theme') }}</template>
<a-button type="text" @click="fnClickTheme">
<template #icon>
<img
v-if="layoutStore.proConfig.theme === 'dark'"
:src="svgDark"
class="theme-icon"
/>
<img v-else :src="svgLight" class="theme-icon" />
</template>
</a-button>
</a-tooltip>
</a-col>
<a-col :span="3" v-if="appStore.i18nOpen">
<a-dropdown trigger="click" placement="bottomRight">
<a-button type="text">
<template #icon> <TranslationOutlined /> </template>
</a-button>
<template #overlay>
<a-menu @click="fnChangeLocale">
@@ -299,10 +289,6 @@ function fnChangeLocale(e: any) {
</a-row>
</a-form>
</a-card>
<footer class="footer">
<div class="footer-copyright">{{ appStore.copyright }}</div>
</footer>
</div>
</template>
@@ -315,7 +301,7 @@ function fnChangeLocale(e: any) {
// background: url('./../assets/black_dot.png') 0% 0% / 14px 14px repeat;
background-image: url(@/assets/background.jpg);
background-image: url(@/assets/background_light.jpg);
background-repeat: no-repeat;
background-size: cover;
background-position: center center;
@@ -363,43 +349,9 @@ function fnChangeLocale(e: any) {
}
}
.header {
position: fixed;
left: 0;
top: 0;
width: 100%;
z-index: 1000;
background-color: rgb(255 255 255 / 85%);
padding: 0 16px;
display: flex;
justify-content: space-between;
align-items: center;
.logo-icon {
height: 40px;
width: 40px;
margin-right: 14px;
vertical-align: top;
border-style: none;
border-radius: 6.66px;
margin-top: 4px;
margin-bottom: 4px;
}
.logo-brand {
height: 48px;
width: 174px;
vertical-align: top;
border-style: none;
border-radius: 2px;
}
.title {
position: relative;
top: 6px;
color: rgba(0, 0, 0, 0.85);
font-weight: 600;
font-size: 24px;
font-family: Avenir, Helvetica Neue, Arial, Helvetica, sans-serif;
}
[data-theme='dark'] .container {
background-image: url(@/assets/background_dark.jpg);
background-color: #141414;
}
.login-card {
@@ -409,10 +361,10 @@ function fnChangeLocale(e: any) {
margin-left: 60%;
border-radius: 6px;
& .desc {
text-align: center;
& .title {
text-align: left;
margin-bottom: 18px;
color: #666;
color: #141414;
font-weight: 600;
font-size: 18px;
}
@@ -422,25 +374,15 @@ function fnChangeLocale(e: any) {
}
}
[data-theme='dark'] .login-card {
& .title {
color: #999;
}
}
@media (max-width: 992px) {
.login-card {
margin: 0 auto;
}
}
.footer {
position: absolute;
bottom: 0;
height: 36px;
padding: 8px 16px 0;
text-align: left;
background-color: rgb(255 255 255 / 85%);
width: 100%;
&-copyright {
font-size: 14px;
color: rgba(0, 0, 0, 0.75);
font-family: Avenir, Helvetica Neue, Arial, Helvetica, sans-serif;
}
}
</style>

View File

@@ -1,7 +1,7 @@
<script setup lang="ts">
import { reactive, onMounted, toRaw } from 'vue';
import { PageContainer } from 'antdv-pro-layout';
import { Form, message } from 'ant-design-vue/lib';
import { Form, message } from 'ant-design-vue/es';
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
import { getOperationSet, updateOperationSet } from '@/api/mmlManage/mmlSet';
import { regExpIPv4 } from '@/utils/regular-utils';
@@ -90,7 +90,7 @@ onMounted(() => {
<template>
<PageContainer>
<a-row :gutter="16">
<a-row>
<a-col :span="8">
<!-- 接口设置 -->
<a-card

View File

@@ -1,7 +1,7 @@
<script setup lang="ts">
import { reactive, ref, onMounted, toRaw } from 'vue';
import { PageContainer } from 'antdv-pro-layout';
import { Modal, message } from 'ant-design-vue/lib';
import { Modal, message } from 'ant-design-vue/es';
import CodemirrorEdite from '@/components/CodemirrorEdite/index.vue';
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
import useNeInfoStore from '@/store/modules/neinfo';
@@ -9,7 +9,7 @@ import { regExpIPv4, regExpIPv6 } from '@/utils/regular-utils';
import useI18n from '@/hooks/useI18n';
import { getMMLByNE, sendMMlByNE } from '@/api/mmlManage/neOperate';
import { uploadFileToNE } from '@/api/tool/file';
import { UploadRequestOption } from 'ant-design-vue/lib/vc-upload/interface';
import { UploadRequestOption } from 'ant-design-vue/es/vc-upload/interface';
const neInfoStore = useNeInfoStore();
const { t } = useI18n();

View File

@@ -1,7 +1,7 @@
<script setup lang="ts">
import { reactive, ref, onMounted, toRaw } from 'vue';
import { PageContainer } from 'antdv-pro-layout';
import { Modal, message } from 'ant-design-vue/lib';
import { Modal, message } from 'ant-design-vue/es';
import CodemirrorEdite from '@/components/CodemirrorEdite/index.vue';
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
import useNeInfoStore from '@/store/modules/neinfo';
@@ -9,7 +9,7 @@ import { regExpIPv4, regExpIPv6 } from '@/utils/regular-utils';
import useI18n from '@/hooks/useI18n';
import { getMMLByOMC, sendMMlByOMC } from '@/api/mmlManage/omcOperate';
import { uploadFileToNE } from '@/api/tool/file';
import { UploadRequestOption } from 'ant-design-vue/lib/vc-upload/interface';
import { UploadRequestOption } from 'ant-design-vue/es/vc-upload/interface';
const { t } = useI18n();
/**网元参数 */

View File

@@ -1,14 +1,14 @@
<script setup lang="ts">
import { reactive, ref, onMounted, toRaw } from 'vue';
import { PageContainer } from 'antdv-pro-layout';
import { Modal, message } from 'ant-design-vue/lib';
import { Modal, message } from 'ant-design-vue/es';
import CodemirrorEdite from '@/components/CodemirrorEdite/index.vue';
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
import useNeInfoStore from '@/store/modules/neinfo';
import { regExpIPv4, regExpIPv6 } from '@/utils/regular-utils';
import useI18n from '@/hooks/useI18n';
import { getMMLByUDM, sendMMlByUDM } from '@/api/mmlManage/udmOperate';
import { UploadRequestOption } from 'ant-design-vue/lib/vc-upload/interface';
import { UploadRequestOption } from 'ant-design-vue/es/vc-upload/interface';
import { uploadFileToNE } from '@/api/tool/file';
const { t } = useI18n();

View File

@@ -9,8 +9,8 @@ import {
clearCacheSafe,
} from '@/api/monitor/cache';
import { PageContainer } from 'antdv-pro-layout';
import { ColumnsType } from 'ant-design-vue/lib/table/Table';
import { message } from 'ant-design-vue/lib';
import { ColumnsType } from 'ant-design-vue/es/table/Table';
import { message } from 'ant-design-vue/es';
import { hasPermissions } from '@/plugins/auth-user';
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
import useI18n from '@/hooks/useI18n';
@@ -268,7 +268,7 @@ onMounted(() => {
<template>
<PageContainer>
<a-row :gutter="20">
<a-row :gutter="16">
<a-col :lg="8" :md="8" :xs="24">
<a-card
:title="t('views.monitor.cache.cacheList')"

View File

@@ -2,10 +2,11 @@
import { useRouter, useRoute } from 'vue-router';
import { reactive, onMounted, toRaw } from 'vue';
import { PageContainer } from 'antdv-pro-layout';
import { message, Modal, Form } from 'ant-design-vue/lib';
import { SizeType } from 'ant-design-vue/lib/config-provider';
import { MenuInfo } from 'ant-design-vue/lib/menu/src/interface';
import { ColumnsType } from 'ant-design-vue/lib/table';
import { ProModal } from 'antdv-pro-modal';
import { message, Modal, Form } from 'ant-design-vue/es';
import { SizeType } from 'ant-design-vue/es/config-provider';
import { MenuInfo } from 'ant-design-vue/es/menu/src/interface';
import { ColumnsType } from 'ant-design-vue/es/table';
import {
exportJob,
listJob,
@@ -190,9 +191,9 @@ function fnTableSelectedRowKeys(keys: (string | number)[]) {
/**对话框对象信息状态类型 */
type ModalStateType = {
/**详情框是否显示 */
visibleByView: boolean;
openByView: boolean;
/**新增框或修改框是否显示 */
visibleByEdit: boolean;
openByEdit: boolean;
/**标题 */
title: string;
/**表单数据 */
@@ -200,13 +201,13 @@ type ModalStateType = {
/**确定按钮 loading */
confirmLoading: boolean;
/**cron生成框是否显示 */
visibleByCron: boolean;
openByCron: boolean;
};
/**对话框对象信息状态 */
let modalState: ModalStateType = reactive({
visibleByView: false,
visibleByEdit: false,
openByView: false,
openByEdit: false,
title: '任务',
from: {
jobId: undefined,
@@ -222,7 +223,7 @@ let modalState: ModalStateType = reactive({
remark: '',
},
confirmLoading: false,
visibleByCron: false,
openByCron: false,
});
/**对话框内表单属性和校验规则 */
@@ -273,7 +274,7 @@ function fnModalVisibleByVive(jobId: string | number) {
if (res.code === RESULT_CODE_SUCCESS && res.data) {
modalState.from = Object.assign(modalState.from, res.data);
modalState.title = t('views.monitor.job.viewJob');
modalState.visibleByView = true;
modalState.openByView = true;
} else {
message.error(t('views.monitor.job.viewInfoErr'), 2);
}
@@ -288,7 +289,7 @@ function fnModalVisibleByEdit(jobId?: string | number) {
if (!jobId) {
modalStateFrom.resetFields();
modalState.title = t('views.monitor.job.addJob');
modalState.visibleByEdit = true;
modalState.openByEdit = true;
} else {
if (modalState.confirmLoading) return;
const hide = message.loading(t('common.loading'), 0);
@@ -299,7 +300,7 @@ function fnModalVisibleByEdit(jobId?: string | number) {
if (res.code === RESULT_CODE_SUCCESS && res.data) {
modalState.from = Object.assign(modalState.from, res.data);
modalState.title = t('views.monitor.job.editJob');
modalState.visibleByEdit = true;
modalState.openByEdit = true;
} else {
message.error(t('views.monitor.job.viewInfoErr'), 2);
}
@@ -328,7 +329,7 @@ function fnModalOk() {
key,
duration: 2,
});
modalState.visibleByEdit = false;
modalState.openByEdit = false;
modalStateFrom.resetFields();
fnGetList(1);
} else {
@@ -353,8 +354,8 @@ function fnModalOk() {
* 进行表达规则校验
*/
function fnModalCancel() {
modalState.visibleByEdit = false;
modalState.visibleByView = false;
modalState.openByEdit = false;
modalState.openByView = false;
modalStateFrom.resetFields();
}
@@ -362,7 +363,7 @@ function fnModalCancel() {
* 对话框弹出cron生成回调
*/
function fnModalCron(opt: boolean, cronStr?: string) {
modalState.visibleByCron = opt;
modalState.openByCron = opt;
if (cronStr) {
modalState.from.cronExpression = cronStr;
}
@@ -651,7 +652,7 @@ onMounted(() => {
<a-card :bordered="false" :body-style="{ padding: '0px' }">
<!-- 插槽-卡片左侧侧 -->
<template #title>
<div class="button-container">
<a-space :size="8" align="center">
<a-button
type="primary"
@click.prevent="fnModalVisibleByEdit()"
@@ -695,12 +696,12 @@ onMounted(() => {
<template #icon><SyncOutlined /></template>
{{ t('views.monitor.job.resetQueue') }}
</a-button>
</div>
</a-space>
</template>
<!-- 插槽-卡片右侧 -->
<template #extra>
<div class="button-container">
<a-space :size="8" align="center">
<a-tooltip>
<template #title>{{ t('common.searchBarText') }}</template>
<a-switch
@@ -740,7 +741,7 @@ onMounted(() => {
</template>
</a-dropdown>
</a-tooltip>
</div>
</a-space>
</template>
<!-- 表格列表 -->
@@ -848,12 +849,12 @@ onMounted(() => {
<ProModal
:drag="true"
:width="800"
:visible="modalState.visibleByView"
:open="modalState.openByView"
:title="modalState.title"
@cancel="fnModalCancel"
>
<a-form layout="horizontal" :label-col="{ span: 6 }" :label-wrap="true">
<a-row :gutter="16">
<a-row>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item :label="t('views.monitor.job.jobName')" name="jobName">
{{ modalState.from.jobName }}
@@ -869,7 +870,7 @@ onMounted(() => {
</a-col>
</a-row>
<a-row :gutter="16">
<a-row>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
:label="t('views.monitor.job.invokeTarget')"
@@ -891,7 +892,7 @@ onMounted(() => {
</a-col>
</a-row>
<a-row :gutter="16">
<a-row>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
:label="t('views.monitor.job.cronExpression')"
@@ -963,7 +964,7 @@ onMounted(() => {
:destroyOnClose="true"
:keyboard="false"
:mask-closable="false"
:visible="modalState.visibleByEdit"
:open="modalState.openByEdit"
:title="modalState.title"
:confirm-loading="modalState.confirmLoading"
@ok="fnModalOk"
@@ -975,7 +976,7 @@ onMounted(() => {
:label-col="{ span: 6 }"
:label-wrap="true"
>
<a-row :gutter="16">
<a-row>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
:label="t('views.monitor.job.jobName')"
@@ -1002,7 +1003,7 @@ onMounted(() => {
</a-col>
</a-row>
<a-row :gutter="16">
<a-row>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
:label="t('views.monitor.job.jobGroup')"
@@ -1047,7 +1048,7 @@ onMounted(() => {
<template #title>
<div>{{ t('views.monitor.job.invokeTargetTip') }}</div>
</template>
<InfoCircleOutlined style="color: rgba(0, 0, 0, 0.45)" />
<InfoCircleOutlined style="opacity: 0.45; color: inherit" />
</a-tooltip>
</template>
</a-input>
@@ -1073,7 +1074,7 @@ onMounted(() => {
{{ t('views.monitor.job.cronExpressionTip1') }}
</div>
</template>
<InfoCircleOutlined style="color: rgba(0, 0, 0, 0.45)" />
<InfoCircleOutlined style="opacity: 0.45; color: inherit" />
</a-tooltip>
</template>
<template #addonAfter>
@@ -1121,7 +1122,7 @@ onMounted(() => {
<!-- 生成cron表达式 -->
<CronModal
v-model:visible="modalState.visibleByCron"
v-model:open="modalState.openByCron"
:cron="modalState.from.cronExpression"
@ok="fnModalCron(false, $event)"
></CronModal>

View File

@@ -2,10 +2,11 @@
import { useRoute, useRouter } from 'vue-router';
import { reactive, ref, onMounted, toRaw } from 'vue';
import { PageContainer } from 'antdv-pro-layout';
import { message, Modal } from 'ant-design-vue/lib';
import { SizeType } from 'ant-design-vue/lib/config-provider';
import { MenuInfo } from 'ant-design-vue/lib/menu/src/interface';
import { ColumnsType } from 'ant-design-vue/lib/table';
import { ProModal } from 'antdv-pro-modal';
import { message, Modal } from 'ant-design-vue/es';
import { SizeType } from 'ant-design-vue/es/config-provider';
import { MenuInfo } from 'ant-design-vue/es/menu/src/interface';
import { ColumnsType } from 'ant-design-vue/es/table';
import {
exportJobLog,
listJobLog,
@@ -216,7 +217,7 @@ function fnTableSelectedRowKeys(keys: (string | number)[]) {
/**对话框对象信息状态类型 */
type ModalStateType = {
/**详情框是否显示 */
visibleByView: boolean;
open: boolean;
/**标题 */
title: string;
/**表单数据 */
@@ -225,7 +226,7 @@ type ModalStateType = {
/**对话框对象信息状态 */
let modalState: ModalStateType = reactive({
visibleByView: false,
open: false,
title: '任务日志',
from: {
jobLogId: undefined,
@@ -246,14 +247,14 @@ let modalState: ModalStateType = reactive({
function fnModalVisibleByVive(row: Record<string, string>) {
modalState.from = Object.assign(modalState.from, row);
modalState.title = t('views.monitor.jobLog.viewLog');
modalState.visibleByView = true;
modalState.open = true;
}
/**
* 对话框弹出关闭执行函数
*/
function fnModalCancel() {
modalState.visibleByView = false;
modalState.open = false;
}
/**
@@ -503,7 +504,7 @@ onMounted(() => {
<a-card :bordered="false" :body-style="{ padding: '0px' }">
<!-- 插槽-卡片左侧侧 -->
<template #title>
<div class="button-container">
<a-space :size="8" align="center">
<a-button type="default" @click.prevent="fnClose()">
<template #icon><CloseOutlined /></template>
{{ t('common.close') }}
@@ -535,12 +536,12 @@ onMounted(() => {
<template #icon><ExportOutlined /></template>
{{ t('common.export') }}
</a-button>
</div>
</a-space>
</template>
<!-- 插槽-卡片右侧 -->
<template #extra>
<div class="button-container">
<a-space :size="8" align="center">
<a-tooltip>
<template #title>{{ t('common.searchBarText') }}</template>
<a-switch
@@ -580,7 +581,7 @@ onMounted(() => {
</template>
</a-dropdown>
</a-tooltip>
</div>
</a-space>
</template>
<!-- 表格列表 -->
@@ -635,12 +636,12 @@ onMounted(() => {
<ProModal
:drag="true"
:width="800"
:visible="modalState.visibleByView"
:open="modalState.open"
:title="modalState.title"
@cancel="fnModalCancel"
>
<a-form layout="horizontal" :label-col="{ span: 6 }" :label-wrap="true">
<a-row :gutter="16">
<a-row>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item :label="t('common.rowId')" name="jobLogId">
{{ modalState.from.jobLogId }}
@@ -662,7 +663,7 @@ onMounted(() => {
</a-form-item>
</a-col>
</a-row>
<a-row :gutter="16">
<a-row>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
:label="t('views.monitor.jobLog.jobName')"
@@ -683,7 +684,7 @@ onMounted(() => {
</a-form-item>
</a-col>
</a-row>
<a-row :gutter="16">
<a-row>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
:label="t('views.monitor.jobLog.invokeTarget')"

View File

@@ -466,7 +466,7 @@ onMounted(() => {
</a-form>
</a-card>
<a-row :gutter="16">
<a-row>
<a-col :lg="24" :md="24" :xs="24">
<a-card :bordered="false" :body-style="{ marginBottom: '24px' }">
<!-- 插槽-卡片左侧侧 -->

View File

@@ -1,12 +1,12 @@
<script setup lang="ts">
import { reactive, onMounted } from 'vue';
import { PageContainer } from 'antdv-pro-layout';
import { message, Modal } from 'ant-design-vue/lib';
import { message, Modal } from 'ant-design-vue/es';
import { forceLogout, listOnline } from '@/api/monitor/online';
import { parseDateToStr } from '@/utils/date-utils';
import { SizeType } from 'ant-design-vue/lib/config-provider';
import { MenuInfo } from 'ant-design-vue/lib/menu/src/interface';
import { ColumnsType } from 'ant-design-vue/lib/table';
import { SizeType } from 'ant-design-vue/es/config-provider';
import { MenuInfo } from 'ant-design-vue/es/menu/src/interface';
import { ColumnsType } from 'ant-design-vue/es/table';
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
import useI18n from '@/hooks/useI18n';
const { t } = useI18n();

View File

@@ -1,7 +1,7 @@
<script setup lang="ts">
import { reactive, ref, onMounted } from 'vue';
import { PageContainer } from 'antdv-pro-layout';
import { ColumnsType } from 'ant-design-vue/lib/table';
import { ColumnsType } from 'ant-design-vue/es/table';
import { getSystemInfo } from '@/api/monitor/system';
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
import useI18n from '@/hooks/useI18n';

View File

@@ -4,9 +4,10 @@ import { PageContainer } from 'antdv-pro-layout';
import useI18n from '@/hooks/useI18n';
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
import { listAllNeInfo, stateNeInfo } from '@/api/ne/neInfo';
import { message } from 'ant-design-vue/lib';
import { message } from 'ant-design-vue/es';
import { randerGroph, switchLayout } from './graph';
import { parseDateToStr } from '@/utils/date-utils';
import { parseBasePath } from '@/plugins/file-static-url';
const { t } = useI18n();
/**图DOM节点实例对象 */
@@ -23,16 +24,18 @@ const graphG6Data = reactive<Record<string, any>>({
/**查询全部网元数据列表 */
function fnRanderData() {
if (!graphG6Dom.value) return;
if (!graphG6Dom.value) return false;
graphG6.value = randerGroph(t, graphG6Dom.value, graphG6Data);
return true;
}
/**网元状态调度器 */
const interval10s = ref<any>(null);
const interval = ref<boolean>(true);
/**查询网元状态 */
async function fnGetState() {
for (const node of graphG6Data.nodes) {
if (!interval.value) return;
const ne = node.info;
// if (ne.neType === 'OMC') continue;
const result = await stateNeInfo(ne.neType, ne.neId);
@@ -61,7 +64,7 @@ function fnGetList(refresh: boolean = false) {
res.data.length > 0
) {
// 根网管
let rootNodeInfo = { neName: "OMC_001" };
let rootNodeInfo = { neName: 'OMC_001' };
const nodes = [];
const edges = [];
for (const item of res.data) {
@@ -87,7 +90,7 @@ function fnGetList(refresh: boolean = false) {
x: -30,
y: -30,
// 可更换为其他图片地址
img: '/svg/service_db.svg',
img: parseBasePath('/svg/service_db.svg'),
width: 60,
height: 60,
},
@@ -102,7 +105,7 @@ function fnGetList(refresh: boolean = false) {
icon: {
x: -24,
y: -24,
img: '/svg/service.svg',
img: parseBasePath('/svg/service.svg'),
width: 48,
height: 48,
},
@@ -139,17 +142,31 @@ function fnGetList(refresh: boolean = false) {
}
})
.then(hasNeList => {
if (!hasNeList) return;
if (!hasNeList) return false;
if (refresh) {
// graphG6.value.get('canvas').set('localRefresh', true);
graphG6.value.destroy();
// graphG6.value.clear();
}
fnRanderData();
fnGetState();
interval10s.value = setInterval(() => {
fnGetState(); // 获取网元状态
}, 10_000);
return fnRanderData();
})
.then(randerGroph => {
if (!randerGroph) return;
repeatFn();
});
}
/**递归刷新网元状态 */
function repeatFn() {
if (!interval.value) {
return;
}
fnGetState()
.finally(() => {
repeatFn(); // 递归调用自己
})
.catch(error => {
console.error(error);
});
}
@@ -159,7 +176,7 @@ onMounted(() => {
});
onBeforeUnmount(() => {
clearInterval(interval10s.value);
interval.value = false;
});
</script>

View File

@@ -6,7 +6,7 @@ import {
RESULT_CODE_SUCCESS,
} from '@/constants/result-constants';
import { listAllNeInfo } from '@/api/ne/neInfo';
import { message } from 'ant-design-vue/lib';
import { message } from 'ant-design-vue/es';
import { getGraphData } from '@/api/monitor/topology';
import { parseDateToStr } from '@/utils/date-utils';
import { Graph, GraphData, Menu, Tooltip } from '@antv/g6';
@@ -24,6 +24,7 @@ import {
import useNeOptions from '@/views/ne/neInfo/hooks/useNeOptions';
import useI18n from '@/hooks/useI18n';
import { OptionsType, WS } from '@/plugins/ws-websocket';
import { parseBasePath } from '@/plugins/file-static-url';
const { t } = useI18n();
const { fnNeRestart, fnNeStop, fnNeLogFile } = useNeOptions();
const ws = new WS();
@@ -165,7 +166,7 @@ const graphNodeTooltip = new Tooltip({
</span></div>
<div><strong>${t('views.monitor.topology.expiryDate')}</strong><span>
${neState.expire ?? '--'}
</span></div>
</span></div>
</div>
`;
},
@@ -291,6 +292,11 @@ function fnGraphDataLoad(reload: boolean = false) {
const nf: Record<string, any>[] = nodes.filter(
(node: Record<string, any>) => {
Reflect.set(node, 'neState', { online: false });
// 图片路径处理
if (node.img) node.img = parseBasePath(node.img);
if (node.icon.show && node.icon?.img)
node.icon.img = parseBasePath(node.icon.img);
// 遍历是否有网元数据
const nodeID: string = node.id;
const hasNe = res.neList.some(ne => {
Reflect.set(node, 'neInfo', ne.neType === nodeID ? ne : {});
@@ -347,11 +353,11 @@ function fnGraphDataLoad(reload: boolean = false) {
}
clearInterval(interval10s.value);
interval10s.value = null;
fnGetState().finally(() => {
interval10s.value = setInterval(() => {
fnGetState(); // 获取网元状态
}, 10_000);
});
fnGetState();
interval10s.value = setInterval(async () => {
if (!interval10s.value) return;
fnGetState(); // 获取网元状态
}, 20_000);
});
}
@@ -359,7 +365,7 @@ function fnGraphDataLoad(reload: boolean = false) {
const interval10s = ref<any>(null);
/**查询网元状态 */
async function fnGetState() {
function fnGetState() {
// 获取节点状态
for (const node of graphState.data.nodes) {
if (notNeNodes.includes(node.id)) continue;
@@ -506,16 +512,20 @@ onBeforeUnmount(() => {
>
<!-- 插槽-卡片左侧侧 -->
<template #title>
<div class="button-container" style="margin-bottom: -12px">
<a-space :size="8" align="center">
<span>
{{ t('views.monitor.topologyBuild.graphGroup') }}
{{ graphState.group }}
</span>
</div>
</a-space>
</template>
<!-- 插槽-卡片右侧 -->
<template #extra>
<a-button type="default" @click.prevent="fnGraphDataLoad(true)">
<a-button
type="default"
size="small"
@click.prevent="fnGraphDataLoad(true)"
>
<template #icon><ReloadOutlined /></template>
{{ t('common.reloadText') }}
</a-button>

View File

@@ -1,5 +1,6 @@
<script setup lang="ts">
import { reactive, watch } from 'vue';
import { ProModal } from 'antdv-pro-modal';
import useI18n from '@/hooks/useI18n';
import {
graphEvent,
@@ -53,21 +54,21 @@ watch(graphEvent, v => {
edgeState.form.id = '#';
modalState.title = t('views.monitor.topologyBuild.edgeTitleAdd');
modalState.formType = 'edge';
modalState.visible = true;
modalState.open = true;
}
if (type === 'canvas-create-node') {
nodeState.origin = {};
nodeState.form.id = '';
modalState.title = t('views.monitor.topologyBuild.nodeTitleAdd');
modalState.formType = 'node';
modalState.visible = true;
modalState.open = true;
}
if (type === 'canvas-create-combo') {
comboState.origin = {};
comboState.form.id = '';
modalState.title = t('views.monitor.topologyBuild.comboTitleAdd');
modalState.formType = 'combo';
modalState.visible = true;
modalState.open = true;
}
// 边
if (type === 'edge-edit' && item) {
@@ -76,7 +77,7 @@ watch(graphEvent, v => {
edgeState.form = Object.assign(edgeState.form, edge);
modalState.title = t('views.monitor.topologyBuild.edgeTitleEdit');
modalState.formType = 'edge';
modalState.visible = true;
modalState.open = true;
}
// 节点
if (type === 'node-edit' && item) {
@@ -85,7 +86,7 @@ watch(graphEvent, v => {
nodeState.form = Object.assign(nodeState.form, node);
modalState.title = t('views.monitor.topologyBuild.nodeTitleEdit');
modalState.formType = 'node';
modalState.visible = true;
modalState.open = true;
}
// 分组
if (type === 'combo-edit' && item) {
@@ -98,14 +99,14 @@ watch(graphEvent, v => {
}
modalState.title = t('views.monitor.topologyBuild.comboTitleEdit');
modalState.formType = 'combo';
modalState.visible = true;
modalState.open = true;
}
});
/**对话框对象信息状态类型 */
type ModalStateType = {
/**对话框是否显示 */
visible: boolean;
open: boolean;
/**标题 */
title: string;
/**图元素表单类型 */
@@ -116,7 +117,7 @@ type ModalStateType = {
/**对话框对象信息状态 */
let modalState: ModalStateType = reactive({
visible: false,
open: false,
title: '图信息',
formType: 'edge',
confirmLoading: false,
@@ -132,21 +133,21 @@ function fnModalOk() {
// 边编辑确认
if (type === 'edge') {
handleOkEdge().then(result => {
modalState.visible = !result;
modalState.open = !result;
modalState.confirmLoading = false;
});
}
// 节点编辑确认
if (type === 'node') {
handleOkNode().then(result => {
modalState.visible = !result;
modalState.open = !result;
modalState.confirmLoading = false;
});
}
// 分租编辑确认
if (type === 'combo') {
handleOkcombo().then(result => {
modalState.visible = !result;
modalState.open = !result;
modalState.confirmLoading = false;
});
}
@@ -157,7 +158,7 @@ function fnModalOk() {
* 进行表达规则校验
*/
function fnModalCancel() {
modalState.visible = false;
modalState.open = false;
const type = modalState.formType;
// 边编辑还原
if (type === 'edge') {
@@ -179,10 +180,10 @@ function fnModalCancel() {
:drag="true"
:width="800"
:destroyOnClose="true"
:body-style="{ maxHeight: '650px', 'overflow-y': 'auto' }"
:body-style="{ maxHeight: '600px', 'overflow-y': 'auto' }"
:keyboard="false"
:mask-closable="false"
:visible="modalState.visible"
:open="modalState.open"
:title="modalState.title"
:confirm-loading="modalState.confirmLoading"
@ok="fnModalOk"
@@ -240,7 +241,7 @@ function fnModalCancel() {
</a-form-item>
<!-- 圆形尺寸 -->
<a-row :gutter="16" v-if="comboState.form.type.startsWith('circle')">
<a-row v-if="comboState.form.type.startsWith('circle')">
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
:label="t('views.monitor.topologyBuild.comboFormSize')"
@@ -269,7 +270,7 @@ function fnModalCancel() {
</a-row>
<!-- 矩形尺寸 -->
<a-row :gutter="16" v-if="comboState.form.type.startsWith('rect')">
<a-row v-if="comboState.form.type.startsWith('rect')">
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
:label="t('views.monitor.topologyBuild.comboFormSize')"
@@ -308,7 +309,7 @@ function fnModalCancel() {
</a-col>
</a-row>
<a-row :gutter="16">
<a-row>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
:label="t('views.monitor.topologyBuild.formStyleFill')"
@@ -396,7 +397,7 @@ function fnModalCancel() {
</a-input>
</a-form-item>
<a-row :gutter="16">
<a-row>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
:label="t('views.monitor.topologyBuild.formLabelStyleFill')"
@@ -424,7 +425,7 @@ function fnModalCancel() {
</a-col>
</a-row>
<a-row :gutter="16">
<a-row>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
:label="t('views.monitor.topologyBuild.formLabelRefX')"
@@ -457,7 +458,7 @@ function fnModalCancel() {
</a-col>
</a-row>
<a-row :gutter="16">
<a-row>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
:label="t('views.monitor.topologyBuild.formLabelPosition')"
@@ -525,7 +526,7 @@ function fnModalCancel() {
</a-select>
</a-form-item>
<a-row :gutter="16">
<a-row>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
:label="t('views.monitor.topologyBuild.nodeFormX')"
@@ -552,7 +553,7 @@ function fnModalCancel() {
</a-col>
</a-row>
<a-row :gutter="16">
<a-row>
<a-col
:lg="12"
:md="12"
@@ -653,7 +654,7 @@ function fnModalCancel() {
</a-row>
<template v-if="!nodeState.form.type.startsWith('image')">
<a-row :gutter="16">
<a-row>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
:label="t('views.monitor.topologyBuild.formStyleStroke')"
@@ -728,7 +729,7 @@ function fnModalCancel() {
</a-input>
</a-form-item>
<a-row :gutter="16">
<a-row>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
:label="t('views.monitor.topologyBuild.formLabelStyleFill')"
@@ -756,7 +757,7 @@ function fnModalCancel() {
</a-col>
</a-row>
<a-row :gutter="16">
<a-row>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
:label="t('views.monitor.topologyBuild.formLabelPosition')"
@@ -791,7 +792,7 @@ function fnModalCancel() {
{{ t('views.monitor.topologyBuild.nodeFormTypeImage') }}
</a-divider>
<a-row :gutter="16">
<a-row>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
:label="t('views.monitor.topologyBuild.nodeFormClipShow')"
@@ -835,7 +836,7 @@ function fnModalCancel() {
<!-- 裁剪功能 -->
<template v-if="nodeState.form.clipCfg.show">
<a-row :gutter="16">
<a-row>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
:label="t('views.monitor.topologyBuild.nodeFormClipType')"
@@ -851,10 +852,7 @@ function fnModalCancel() {
</a-row>
<!-- 剪裁圆形 -->
<a-row
:gutter="16"
v-if="nodeState.form.clipCfg.type.startsWith('circle')"
>
<a-row v-if="nodeState.form.clipCfg.type.startsWith('circle')">
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
:label="t('views.monitor.topologyBuild.nodeFormClipTypeCircle')"
@@ -872,10 +870,7 @@ function fnModalCancel() {
</a-row>
<!-- 剪裁矩形 -->
<a-row
:gutter="16"
v-if="nodeState.form.clipCfg.type.startsWith('rect')"
>
<a-row v-if="nodeState.form.clipCfg.type.startsWith('rect')">
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
:label="
@@ -911,7 +906,7 @@ function fnModalCancel() {
</a-row>
<!-- 剪裁椭圆 -->
<a-row :gutter="16" v-if="nodeState.form.clipCfg.type === 'ellipse'">
<a-row v-if="nodeState.form.clipCfg.type === 'ellipse'">
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
:label="
@@ -947,7 +942,7 @@ function fnModalCancel() {
</a-row>
<!-- 裁剪图形坐标 -->
<a-row :gutter="16">
<a-row>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
:label="t('views.monitor.topologyBuild.nodeFormClipX')"
@@ -992,7 +987,7 @@ function fnModalCancel() {
{{ t('views.monitor.topologyBuild.nodeFormIcon') }}
</a-divider>
<a-row :gutter="16">
<a-row>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
:label="t('views.monitor.topologyBuild.nodeFormIconShow')"
@@ -1016,7 +1011,7 @@ function fnModalCancel() {
</a-col>
</a-row>
<a-row :gutter="16">
<a-row>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
:label="t('views.monitor.topologyBuild.nodeFormIconWidth')"
@@ -1047,7 +1042,7 @@ function fnModalCancel() {
</a-col>
</a-row>
<a-row :gutter="16" v-if="nodeState.form.type === 'triangle'">
<a-row v-if="nodeState.form.type === 'triangle'">
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
:label="t('views.monitor.topologyBuild.nodeFormIconOffset')"
@@ -1087,7 +1082,7 @@ function fnModalCancel() {
</a-select>
</a-form-item>
<a-row :gutter="16">
<a-row>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
:label="t('views.monitor.topologyBuild.edgeFormSource')"
@@ -1118,7 +1113,7 @@ function fnModalCancel() {
</a-col>
</a-row>
<a-row :gutter="16">
<a-row>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
:label="t('views.monitor.topologyBuild.formStyleStroke')"
@@ -1146,7 +1141,7 @@ function fnModalCancel() {
</a-col>
</a-row>
<a-row :gutter="16">
<a-row>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
:label="t('views.monitor.topologyBuild.edgeFormStartArrow')"
@@ -1185,7 +1180,7 @@ function fnModalCancel() {
</a-input>
</a-form-item>
<a-row :gutter="16">
<a-row>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
:label="t('views.monitor.topologyBuild.formLabelStyleFill')"
@@ -1213,7 +1208,7 @@ function fnModalCancel() {
</a-col>
</a-row>
<a-row :gutter="16">
<a-row>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
:label="t('views.monitor.topologyBuild.formLabelRefX')"
@@ -1246,7 +1241,7 @@ function fnModalCancel() {
</a-col>
</a-row>
<a-row :gutter="16">
<a-row>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
:label="t('views.monitor.topologyBuild.formLabelPosition')"

View File

@@ -1,4 +1,4 @@
import { message, Form } from 'ant-design-vue/lib';
import { message, Form } from 'ant-design-vue/es';
import { reactive, toRaw, watch } from 'vue';
import { graphG6, selectSourceTargetOptions } from './useGraph';
import useI18n from '@/hooks/useI18n';

View File

@@ -1,4 +1,4 @@
import { message, Form } from 'ant-design-vue/lib';
import { message, Form } from 'ant-design-vue/es';
import { reactive, watch } from 'vue';
import useI18n from '@/hooks/useI18n';
import { graphG6 } from './useGraph';

View File

@@ -1,4 +1,4 @@
import { message, Form } from 'ant-design-vue/lib';
import { message, Form } from 'ant-design-vue/es';
import { reactive, watch } from 'vue';
import { graphG6 } from './useGraph';
import useI18n from '@/hooks/useI18n';

View File

@@ -1,6 +1,7 @@
<script setup lang="ts">
import { reactive, onMounted, ref, toRaw } from 'vue';
import { PageContainer } from 'antdv-pro-layout';
import { ProModal } from 'antdv-pro-modal';
import useI18n from '@/hooks/useI18n';
import GraphEditModal from './components/GraphEditModal.vue';
import useGraph, { graphG6 } from './/hooks/useGraph';
@@ -11,7 +12,8 @@ import {
saveGraphData,
} from '@/api/monitor/topology';
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
import { Form, Modal, message } from 'ant-design-vue/lib';
import { Form, Modal, message } from 'ant-design-vue/es';
import { parseBasePath } from '@/plugins/file-static-url';
const { t } = useI18n();
const { graphMode, graphModeOptions, handleRanderGraph, handleChangeMode } =
useGraph();
@@ -79,6 +81,14 @@ function fnGraphDataLoad(reload: boolean = false) {
getGraphData(graphState.group)
.then(res => {
if (res.code === RESULT_CODE_SUCCESS) {
res.data.nodes.map((item: any) => {
// 图片路径处理
if (item.img) item.img = parseBasePath(item.img);
if (item.icon.show && item.icon?.img) {
item.icon.img = parseBasePath(item.icon.img);
}
return item;
});
graphState.data = res.data;
}
})
@@ -95,7 +105,7 @@ function fnGraphDataLoad(reload: boolean = false) {
/**对话框对象信息状态类型 */
type ModalStateType = {
/**框是否显示 */
visible: boolean;
open: boolean;
/**标题 */
title: string;
/**表单数据 */
@@ -108,7 +118,7 @@ type ModalStateType = {
/**对话框对象信息状态 */
let modalState: ModalStateType = reactive({
visible: false,
open: false,
title: '图组',
form: {
group: '',
@@ -180,7 +190,7 @@ function fnModalOk() {
*/
function fnModalCancel() {
modalState.type = 'save';
modalState.visible = false;
modalState.open = false;
modalStateFrom.resetFields();
}
@@ -188,8 +198,8 @@ function fnModalCancel() {
function fnGraphDataSave() {
modalState.form.group = graphState.group;
modalState.type = 'save';
(modalState.title = t('views.monitor.topologyBuild.saveTtite')),
(modalState.visible = true);
modalState.title = t('views.monitor.topologyBuild.saveTtite');
modalState.open = true;
}
/**图组数据删除 */
@@ -244,57 +254,44 @@ onMounted(() => {
<template>
<PageContainer>
<a-card
:bordered="false"
:body-style="{ marginBottom: '24px', paddingBottom: 0 }"
>
<a-card :bordered="false" :body-style="{ marginBottom: '24px' }">
<!-- 表格搜索栏 -->
<a-form :model="graphState" name="graphState" layout="horizontal">
<a-row :gutter="16">
<a-col :lg="4" :md="12" :xs="24">
<a-form-item
:label="t('views.monitor.topologyBuild.graphMode')"
name="graphMode"
>
<a-select
:value="graphMode"
:options="graphModeOptions"
@change="handleChangeMode"
>
</a-select>
</a-form-item>
</a-col>
<a-col :lg="6" :md="12" :xs="24">
<a-form-item
:label="t('views.monitor.topologyBuild.graphGroup')"
name="group "
>
<a-select
v-model:value="graphState.group"
:options="graphState.groupOptions"
:placeholder="t('common.selectPlease')"
@change="fnGraphGroupChange"
/>
</a-form-item>
</a-col>
</a-row>
</a-form>
<a-row :gutter="16">
<a-col>
<span>{{ t('views.monitor.topologyBuild.graphMode') }}:</span>&nbsp;
<a-select
:value="graphMode"
:options="graphModeOptions"
@change="handleChangeMode"
>
</a-select>
</a-col>
<a-col>
<span>{{ t('views.monitor.topologyBuild.graphGroup') }}:</span>&nbsp;
<a-select
v-model:value="graphState.group"
:options="graphState.groupOptions"
:placeholder="t('common.selectPlease')"
@change="fnGraphGroupChange"
/>
</a-col>
</a-row>
</a-card>
<a-card :bordered="false" :body-style="{ padding: '0px' }">
<!-- 插槽-卡片左侧侧 -->
<template #title>
<div class="button-container" style="margin-bottom: -12px">
<a-space :size="8" align="center">
<span>
{{ t('views.monitor.topologyBuild.graphGroup') }}
{{ graphState.group }}
</span>
</div>
</a-space>
</template>
<!-- 插槽-卡片右侧 -->
<template #extra>
<div class="button-container" style="margin-bottom: -12px">
<a-space :size="8" align="center">
<template v-if="graphMode === 'edit'">
<a-button type="primary" size="small" @click="fnGraphDataSave">
<template #icon>
@@ -315,7 +312,7 @@ onMounted(() => {
{{ t('views.monitor.topologyBuild.graphDelete') }}
</a-button>
</template>
</div>
</a-space>
</template>
<div ref="graphG6Dom" class="chart"></div>
@@ -329,7 +326,7 @@ onMounted(() => {
:drag="true"
:keyboard="false"
:mask-closable="false"
:visible="modalState.visible"
:open="modalState.open"
:title="modalState.title"
:confirm-loading="modalState.confirmLoading"
@ok="fnModalOk"
@@ -341,7 +338,7 @@ onMounted(() => {
:label-col="{ span: 6 }"
:labelWrap="true"
>
<a-row :gutter="16">
<a-row>
<a-col :lg="24" :md="24" :xs="24">
<a-form-item
:label="t('views.monitor.topologyBuild.graphGroup')"

View File

@@ -4,9 +4,8 @@ import {
editNeConfigData,
} from '@/api/ne/neConfig';
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
import { Modal } from 'ant-design-vue/lib';
import { SizeType } from 'ant-design-vue/lib/config-provider';
import message from 'ant-design-vue/lib/message';
import { Modal,message } from 'ant-design-vue/es';
import { SizeType } from 'ant-design-vue/es/config-provider';
import { reactive, watch } from 'vue';
/**
@@ -88,7 +87,7 @@ export default function useConfigArray({
modalState.title = `${treeState.selectNode.paramDisplay} ${from.title}`;
modalState.key = from.key;
modalState.data = from.record.filter((v: any) => !Array.isArray(v.array));
modalState.visible = true;
modalState.open = true;
// 关闭嵌套
arrayState.arrayChildExpandKeys = [];
@@ -233,7 +232,7 @@ export default function useConfigArray({
modalState.title = `${treeState.selectNode.paramDisplay} ${from.title}`;
modalState.key = from.key;
modalState.data = from.record.filter((v: any) => !Array.isArray(v.array));
modalState.visible = true;
modalState.open = true;
}
/**多列表新增单行确认 */

View File

@@ -4,9 +4,8 @@ import {
delNeConfigData,
} from '@/api/ne/neConfig';
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
import { Modal } from 'ant-design-vue/lib';
import { SizeType } from 'ant-design-vue/lib/config-provider';
import message from 'ant-design-vue/lib/message';
import { Modal, message } from 'ant-design-vue/es';
import { SizeType } from 'ant-design-vue/es/config-provider';
import { nextTick, reactive } from 'vue';
/**
@@ -174,7 +173,7 @@ export default function useConfigArrayChild({
modalState.title = `${arrayChildState.title} ${from.title}`;
modalState.key = from.key;
modalState.data = from.record.filter((v: any) => !Array.isArray(v.array));
modalState.visible = true;
modalState.open = true;
}
/**多列表嵌套行编辑确认 */
@@ -285,7 +284,7 @@ export default function useConfigArrayChild({
modalState.title = `${arrayChildState.title} ${from.title}`;
modalState.key = from.key;
modalState.data = from.record.filter((v: any) => !Array.isArray(v.array));
modalState.visible = true;
modalState.open = true;
}
/**多列表新增单行确认 */

View File

@@ -1,7 +1,7 @@
import { editNeConfigData } from '@/api/ne/neConfig';
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
import { SizeType } from 'ant-design-vue/lib/config-provider';
import message from 'ant-design-vue/lib/message';
import { SizeType } from 'ant-design-vue/es/config-provider';
import { message } from 'ant-design-vue/es';
import { reactive, toRaw } from 'vue';
/**

View File

@@ -1,8 +1,9 @@
<script setup lang="ts">
import { reactive, ref, onMounted, toRaw, watch } from 'vue';
import { PageContainer } from 'antdv-pro-layout';
import { message } from 'ant-design-vue/lib';
import { DataNode } from 'ant-design-vue/lib/tree';
import { ProModal } from 'antdv-pro-modal';
import { message } from 'ant-design-vue/es';
import { DataNode } from 'ant-design-vue/es/tree';
import useI18n from '@/hooks/useI18n';
import TableColumnsDnd from '@/components/TableColumnsDnd/index.vue';
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
@@ -250,7 +251,7 @@ function fnGetNeConfig() {
/**对话框对象信息状态类型 */
type ModalStateType = {
/**添加框是否显示 */
visible: boolean;
open: boolean;
/**标题 */
title: string;
/**表单数据 */
@@ -267,7 +268,7 @@ type ModalStateType = {
/**对话框对象信息状态 */
let modalState: ModalStateType = reactive({
visible: false,
open: false,
title: 'Item',
from: {},
confirmLoading: false,
@@ -301,7 +302,7 @@ function fnModalOk() {
* 进行表达规则校验
*/
function fnModalCancel() {
modalState.visible = false;
modalState.open = false;
modalState.from = {};
modalState.type = 'arrayAdd';
modalState.key = '';
@@ -310,7 +311,7 @@ function fnModalCancel() {
// 监听新增编辑弹窗
watch(
() => modalState.visible,
() => modalState.open,
val => {
// SMF需要选择配置的UPF id
if (val && neTypeSelect.value[0] === 'SMF') {
@@ -441,7 +442,7 @@ onMounted(() => {
<a-card
size="small"
:bordered="false"
:body-style="{ maxHeight: '650px', 'overflow-y': 'auto' }"
:body-style="{ maxHeight: '600px', 'overflow-y': 'auto' }"
:loading="treeState.selectLoading"
>
<template #title>
@@ -824,10 +825,10 @@ onMounted(() => {
:drag="true"
:width="800"
:destroyOnClose="true"
:body-style="{ maxHeight: '650px', 'overflow-y': 'auto' }"
:body-style="{ maxHeight: '600px', 'overflow-y': 'auto' }"
:keyboard="false"
:mask-closable="false"
:visible="modalState.visible"
:open="modalState.open"
:title="modalState.title"
:confirm-loading="modalState.confirmLoading"
@ok="fnModalOk"

View File

@@ -1,9 +1,10 @@
<script setup lang="ts">
import { reactive, ref, onMounted, toRaw } from 'vue';
import { PageContainer } from 'antdv-pro-layout';
import { Form, Modal, TableColumnsType, message } from 'ant-design-vue/lib';
import { SizeType } from 'ant-design-vue/lib/config-provider';
import { MenuInfo } from 'ant-design-vue/lib/menu/src/interface';
import { ProModal } from 'antdv-pro-modal';
import { Form, Modal, TableColumnsType, message } from 'ant-design-vue/es';
import { SizeType } from 'ant-design-vue/es/config-provider';
import { MenuInfo } from 'ant-design-vue/es/menu/src/interface';
import useNeInfoStore from '@/store/modules/neinfo';
import useI18n from '@/hooks/useI18n';
import useDictStore from '@/store/modules/dict';
@@ -267,7 +268,7 @@ function fnRecordDelete(id: string) {
/**对话框对象信息状态类型 */
type ModalStateType = {
/**新增框或修改框是否显示 */
visibleByEdit: boolean;
openByEdit: boolean;
/**标题 */
title: string;
/**表单数据 */
@@ -278,7 +279,7 @@ type ModalStateType = {
/**对话框对象信息状态 */
let modalState: ModalStateType = reactive({
visibleByEdit: false,
openByEdit: false,
title: '备份记录',
from: {
id: undefined,
@@ -298,7 +299,7 @@ function fnModalVisibleByEdit(row: Record<string, any>) {
modalState.from.name = row.name;
modalState.from.remark = row.remark;
modalState.title = t('views.ne.neConfigBackup.title', { txt: row.id });
modalState.visibleByEdit = true;
modalState.openByEdit = true;
}
/**对话框内表单属性和校验规则 */
@@ -332,7 +333,7 @@ function fnModalOk() {
content: t('common.msgSuccess', { msg: modalState.title }),
duration: 3,
});
modalState.visibleByEdit = false;
modalState.openByEdit = false;
modalStateFrom.resetFields();
fnGetList();
} else {
@@ -358,7 +359,7 @@ function fnModalOk() {
* 进行表达规则校验
*/
function fnModalCancel() {
modalState.visibleByEdit = false;
modalState.openByEdit = false;
modalStateFrom.resetFields();
}
@@ -557,7 +558,7 @@ onMounted(() => {
:destroyOnClose="true"
:keyboard="false"
:mask-closable="false"
:visible="modalState.visibleByEdit"
:open="modalState.openByEdit"
:title="modalState.title"
:confirm-loading="modalState.confirmLoading"
@ok="fnModalOk"

View File

@@ -0,0 +1,503 @@
<script setup lang="ts">
import { reactive, onMounted, toRaw, watch } from 'vue';
import { ProModal } from 'antdv-pro-modal';
import { Form, message } from 'ant-design-vue/es';
import useI18n from '@/hooks/useI18n';
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
import useDictStore from '@/store/modules/dict';
const { getDict } = useDictStore();
import {
addNeHost,
getNeHost,
testNeHost,
updateNeHost,
} from '@/api/ne/neHost';
const { t } = useI18n();
const emit = defineEmits(['ok', 'cancel', 'update:open']);
const props = defineProps({
open: {
type: Boolean,
default: false,
},
/**记录ID */
editId: {
type: String,
default: '',
},
/**分组可选网元 */
neGroup: {
type: Boolean,
default: false,
},
});
/**字典数据 */
let dict: {
/**主机类型 */
neHostType: DictType[];
/**分组 */
neHostGroupId: DictType[];
/**认证模式 */
neHostAuthMode: DictType[];
} = reactive({
neHostType: [],
neHostGroupId: [],
neHostAuthMode: [],
});
/**对话框对象信息状态类型 */
type ModalStateType = {
/**新增框或修改框是否显示 */
openByEdit: boolean;
/**标题 */
title: string;
/**表单数据 */
from: Record<string, any>;
/**确定按钮 loading */
confirmLoading: boolean;
};
/**对话框对象信息状态 */
let modalState: ModalStateType = reactive({
openByEdit: false,
title: '信息',
from: {
hostId: undefined,
hostType: 'ssh',
groupId: '0',
title: '',
addr: '',
port: 22,
user: '',
authMode: '0',
password: '',
privateKey: '',
passPhrase: '',
remark: '',
},
confirmLoading: false,
uploadFiles: [],
});
/**对话框内表单属性和校验规则 */
const modalStateFrom = Form.useForm(
modalState.from,
reactive({
title: [
{
required: true,
min: 1,
max: 50,
message: t('views.ne.neHost.titlePlease'),
},
],
addr: [
{
required: true,
min: 1,
max: 128,
message: t('views.ne.neHost.addrPlease'),
},
],
port: [
{
required: true,
message: t('views.ne.neHost.portPlease'),
},
],
user: [
{
required: true,
min: 1,
max: 50,
message: t('views.ne.neHost.userPlease'),
},
],
password: [
{
required: true,
min: 1,
max: 128,
message: t('views.ne.neHost.passwordPlease'),
},
],
privateKey: [
{
required: true,
min: 1,
max: 3000,
message: t('views.ne.neHost.privateKeyPlease'),
},
],
})
);
/**
* 对话框弹出确认执行函数
* 进行表达规则校验
*/
function fnModalOk() {
if (modalState.confirmLoading) return;
const form = toRaw(modalState.from);
const validateArr = ['title', 'addr', 'port', 'user'];
if (form.authMode === '0') {
validateArr.push('password');
} else {
validateArr.push('privateKey');
}
modalStateFrom
.validate(validateArr)
.then(() => {
modalState.confirmLoading = true;
const neHost = form.hostId ? updateNeHost(form) : addNeHost(form);
const hide = message.loading(t('common.loading'), 0);
neHost
.then(res => {
if (res.code === RESULT_CODE_SUCCESS) {
message.success({
content: t('common.operateOk'),
duration: 2,
});
// 返回无引用信息
emit('ok', JSON.parse(JSON.stringify(form)));
fnModalCancel();
} else {
message.error({
content: `${res.msg}`,
duration: 2,
});
}
})
.finally(() => {
modalState.confirmLoading = false;
hide();
});
})
.catch(e => {
message.error(t('common.errorFields', { num: e.errorFields.length }), 3);
});
}
/**
* 对话框弹出关闭执行函数
* 进行表达规则校验
*/
function fnModalCancel() {
modalState.openByEdit = false;
modalState.confirmLoading = false;
modalStateFrom.resetFields();
emit('cancel');
emit('update:open', false);
}
/**
* 对话框弹出显示为 ID编辑
* @param id id
*/
function fnModalVisibleById(id: string) {
if (modalState.confirmLoading) return;
const hide = message.loading(t('common.loading'), 0);
modalState.confirmLoading = true;
getNeHost(id)
.then(res => {
if (res.code === RESULT_CODE_SUCCESS && res.data) {
modalState.from = Object.assign(modalState.from, res.data);
modalState.title = t('views.ne.neHost.editTitle');
modalState.openByEdit = true;
} else {
message.error(t('common.getInfoFail'), 2);
}
})
.finally(() => {
modalState.confirmLoading = false;
hide();
});
}
/**
* 对话框弹出测试连接
*/
function fnModalTest() {
if (modalState.confirmLoading) return;
const form = toRaw(modalState.from);
const validateArr = ['title', 'addr', 'port', 'user'];
if (form.authMode === '0') {
validateArr.push('password');
}
if (form.authMode === '1') {
validateArr.push('privateKey');
}
modalStateFrom
.validate(validateArr)
.then(() => {
modalState.confirmLoading = true;
const hide = message.loading(t('common.loading'), 0);
testNeHost(form)
.then(res => {
if (res.code === RESULT_CODE_SUCCESS) {
message.success({
content: t('views.ne.neHost.testOk'),
duration: 2,
});
} else {
message.error({
content: `${res.msg}`,
duration: 2,
});
}
})
.finally(() => {
modalState.confirmLoading = false;
hide();
});
})
.catch(e => {
message.error(t('common.errorFields', { num: e.errorFields.length }), 3);
});
}
/**监听是否显示,初始数据 */
watch(
() => props.open,
val => {
if (val) {
if (props.editId) {
fnModalVisibleById(props.editId);
} else {
modalStateFrom.resetFields();
modalState.title = t('views.ne.neHost.addTitle');
modalState.openByEdit = true;
}
}
}
);
onMounted(() => {
// 初始字典数据
Promise.allSettled([
getDict('ne_host_type'),
getDict('ne_host_groupId'),
getDict('ne_host_authMode'),
]).then(resArr => {
if (resArr[0].status === 'fulfilled') {
dict.neHostType = resArr[0].value;
}
if (resArr[1].status === 'fulfilled') {
if (props.neGroup) {
dict.neHostGroupId = resArr[1].value.filter(item => item.value !== '1');
} else {
dict.neHostGroupId = resArr[1].value;
}
}
if (resArr[2].status === 'fulfilled') {
dict.neHostAuthMode = resArr[2].value;
}
});
});
</script>
<template>
<ProModal
:drag="true"
:width="800"
:destroyOnClose="true"
:keyboard="false"
:mask-closable="false"
:open="modalState.openByEdit"
:title="modalState.title"
:confirm-loading="modalState.confirmLoading"
@ok="fnModalOk"
@cancel="fnModalCancel"
>
<a-form
name="modalStateFromByEdit"
layout="horizontal"
:label-col="{ span: 6 }"
:label-wrap="true"
>
<a-row>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item :label="t('views.ne.neHost.hostType')" name="hostType">
<a-select
v-model:value="modalState.from.hostType"
default-value="ssh"
:options="dict.neHostType"
:disabled="!!modalState.from.hostId"
>
</a-select>
</a-form-item>
</a-col>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item :label="t('views.ne.neHost.groupId')" name="groupId">
<a-select
v-model:value="modalState.from.groupId"
default-value="0"
:options="dict.neHostGroupId"
:disabled="!!modalState.from.hostId"
>
</a-select>
</a-form-item>
</a-col>
</a-row>
<a-form-item
:label="t('views.ne.neHost.title')"
name="title"
v-bind="modalStateFrom.validateInfos.title"
:label-col="{ span: 3 }"
:label-wrap="true"
>
<a-input
v-model:value="modalState.from.title"
allow-clear
:maxlength="50"
:placeholder="t('common.inputPlease')"
>
</a-input>
</a-form-item>
<a-row>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
:label="t('views.ne.neHost.addr')"
name="addr"
v-bind="modalStateFrom.validateInfos.addr"
>
<a-input
v-model:value="modalState.from.addr"
allow-clear
:maxlength="128"
:placeholder="t('common.inputPlease')"
>
</a-input>
</a-form-item>
</a-col>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
:label="t('views.ne.neHost.port')"
name="port"
v-bind="modalStateFrom.validateInfos.port"
>
<a-input-number
v-model:value="modalState.from.port"
:min="10"
:max="65535"
:step="1"
:maxlength="5"
style="width: 100%"
></a-input-number>
</a-form-item>
</a-col>
</a-row>
<a-row>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
:label="t('views.ne.neHost.user')"
name="user"
v-bind="modalStateFrom.validateInfos.user"
>
<a-input
v-model:value="modalState.from.user"
allow-clear
:maxlength="32"
:placeholder="t('common.inputPlease')"
>
</a-input>
</a-form-item>
</a-col>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item :label="t('views.ne.neHost.authMode')" name="authMode">
<a-select
v-model:value="modalState.from.authMode"
default-value="0"
:options="dict.neHostAuthMode"
>
</a-select>
</a-form-item>
</a-col>
</a-row>
<a-form-item
v-if="modalState.from.authMode === '0'"
:label="t('views.ne.neHost.password')"
name="password"
v-bind="modalStateFrom.validateInfos.password"
:label-col="{ span: 3 }"
:label-wrap="true"
>
<a-input-password
v-model:value="modalState.from.password"
:maxlength="128"
:placeholder="t('common.inputPlease')"
>
</a-input-password>
</a-form-item>
<template v-if="modalState.from.authMode === '1'">
<a-form-item
:label="t('views.ne.neHost.privateKey')"
name="privateKey"
v-bind="modalStateFrom.validateInfos.privateKey"
:label-col="{ span: 3 }"
:label-wrap="true"
>
<a-textarea
v-model:value="modalState.from.privateKey"
:auto-size="{ minRows: 4, maxRows: 6 }"
:maxlength="3000"
:show-count="true"
:placeholder="t('views.ne.neHost.privateKeyPlease')"
/>
</a-form-item>
<a-form-item
:label="t('views.ne.neHost.passPhrase')"
name="passPhrase"
:label-col="{ span: 3 }"
:label-wrap="true"
>
<a-input-password
v-model:value="modalState.from.passPhrase"
:maxlength="128"
:placeholder="t('common.inputPlease')"
>
</a-input-password>
</a-form-item>
</template>
<a-form-item
:label="t('common.remark')"
name="remark"
:label-col="{ span: 3 }"
:label-wrap="true"
>
<a-textarea
v-model:value="modalState.from.remark"
:auto-size="{ minRows: 1, maxRows: 6 }"
:maxlength="450"
:show-count="true"
:placeholder="t('common.inputPlease')"
/>
</a-form-item>
<a-form-item
:label="t('views.ne.neHost.test')"
name="test"
:label-col="{ span: 3 }"
:label-wrap="true"
>
<a-button
type="primary"
shape="round"
@click="fnModalTest"
:loading="modalState.confirmLoading"
>
<template #icon><LinkOutlined /></template>
</a-button>
</a-form-item>
</a-form>
</ProModal>
</template>
<style lang="less" scoped></style>

View File

@@ -1,24 +1,20 @@
<script setup lang="ts">
import { reactive, onMounted, toRaw } from 'vue';
import { reactive, onMounted, toRaw, defineAsyncComponent } from 'vue';
import { PageContainer } from 'antdv-pro-layout';
import { SizeType } from 'ant-design-vue/lib/config-provider';
import { MenuInfo } from 'ant-design-vue/lib/menu/src/interface';
import { ColumnsType } from 'ant-design-vue/lib/table';
import { Form, Modal, message } from 'ant-design-vue/lib';
import { SizeType } from 'ant-design-vue/es/config-provider';
import { MenuInfo } from 'ant-design-vue/es/menu/src/interface';
import { ColumnsType } from 'ant-design-vue/es/table';
import { Modal, message } from 'ant-design-vue/es';
import { parseDateToStr } from '@/utils/date-utils';
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
import {
addNeHost,
delNeHost,
getNeHost,
listNeHost,
testNeHost,
updateNeHost,
} from '@/api/ne/neHost';
import { delNeHost, listNeHost } from '@/api/ne/neHost';
import useDictStore from '@/store/modules/dict';
import useI18n from '@/hooks/useI18n';
const { getDict } = useDictStore();
const { t } = useI18n();
const EditModal = defineAsyncComponent(
() => import('./components/EditModal.vue')
);
/**字典数据 */
let dict: {
@@ -39,7 +35,7 @@ let queryParams = reactive({
/**主机类型 */
hostType: undefined,
/**分组 */
groupId: undefined,
groupId: '1',
/**名称 */
title: '',
/**当前页数 */
@@ -52,7 +48,7 @@ let queryParams = reactive({
function fnQueryReset() {
queryParams = Object.assign(queryParams, {
hostType: undefined,
groupId: undefined,
groupId: '1',
title: '',
pageNum: 1,
pageSize: 20,
@@ -211,115 +207,31 @@ function fnGetList(pageNum?: number) {
/**对话框对象信息状态类型 */
type ModalStateType = {
/**新增框或修改框是否显示 */
visibleByEdit: boolean;
/**标题 */
title: string;
/**表单数据 */
from: Record<string, any>;
openByEdit: boolean;
/**记录ID */
hostId: string;
/**确定按钮 loading */
confirmLoading: boolean;
};
/**对话框对象信息状态 */
let modalState: ModalStateType = reactive({
visibleByEdit: false,
title: '信息',
from: {
hostId: undefined,
hostType: 'ssh',
groupId: '0',
title: '',
addr: '',
port: 22,
user: '',
authMode: '0',
password: '',
privateKey: '',
passPhrase: '',
remark: '',
},
openByEdit: false,
hostId: '',
confirmLoading: false,
});
/**对话框内表单属性和校验规则 */
const modalStateFrom = Form.useForm(
modalState.from,
reactive({
title: [
{
required: true,
min: 1,
max: 50,
message: t('views.ne.neHost.titlePlease'),
},
],
addr: [
{
required: true,
min: 1,
max: 128,
message: t('views.ne.neHost.addrPlease'),
},
],
port: [
{
required: true,
message: t('views.ne.neHost.portPlease'),
},
],
user: [
{
required: true,
min: 1,
max: 50,
message: t('views.ne.neHost.userPlease'),
},
],
password: [
{
required: true,
min: 1,
max: 128,
message: t('views.ne.neHost.passwordPlease'),
},
],
privateKey: [
{
required: true,
min: 1,
max: 3000,
message: t('views.ne.neHost.privateKeyPlease'),
},
],
})
);
/**
* 对话框弹出显示为 新增或者修改
* @param roleId 角色编号ID, 不传为新增
*/
function fnModalVisibleByEdit(roleId?: string | number) {
function fnModalVisibleByEdit(roleId?: string) {
if (!roleId) {
modalStateFrom.resetFields();
modalState.title = t('views.ne.neHost.addTitle');
modalState.visibleByEdit = true;
modalState.hostId = '';
} else {
if (modalState.confirmLoading) return;
const hide = message.loading(t('common.loading'), 0);
modalState.confirmLoading = true;
// 查询角色详细同时根据角色ID查询菜单下拉树结构
getNeHost(roleId).then(res => {
modalState.confirmLoading = false;
hide();
if (res.code === RESULT_CODE_SUCCESS && res.data) {
modalState.from = Object.assign(modalState.from, res.data);
modalState.title = t('views.ne.neHost.editTitle');
modalState.visibleByEdit = true;
} else {
message.error(t('common.getInfoFail'), 2);
}
});
modalState.hostId = roleId;
}
modalState.openByEdit = true;
}
/**
@@ -327,44 +239,8 @@ function fnModalVisibleByEdit(roleId?: string | number) {
* 进行表达规则校验
*/
function fnModalOk() {
if (modalState.confirmLoading) return;
const form = toRaw(modalState.from);
const validateArr = ['title', 'addr', 'port', 'user'];
if (form.authMode === '0') {
validateArr.push('password');
} else {
validateArr.push('privateKey');
}
modalStateFrom
.validate(validateArr)
.then(() => {
modalState.confirmLoading = true;
const neHost = form.hostId ? updateNeHost(form) : addNeHost(form);
const hide = message.loading(t('common.loading'), 0);
neHost
.then(res => {
if (res.code === RESULT_CODE_SUCCESS) {
message.success({
content: t('common.operateOk'),
duration: 2,
});
fnModalCancel();
fnGetList(1);
} else {
message.error({
content: `${res.msg}`,
duration: 2,
});
}
})
.finally(() => {
modalState.confirmLoading = false;
hide();
});
})
.catch(e => {
message.error(t('common.errorFields', { num: e.errorFields.length }), 3);
});
// 获取列表数据
fnGetList();
}
/**
@@ -372,8 +248,8 @@ function fnModalOk() {
* 进行表达规则校验
*/
function fnModalCancel() {
modalState.visibleByEdit = false;
modalStateFrom.resetFields();
modalState.openByEdit = false;
modalState.hostId = '';
}
/**
@@ -405,48 +281,6 @@ function fnRecordDelete(hostId: string) {
});
}
/**
* 对话框弹出测试连接
*/
function fnModalTest() {
if (modalState.confirmLoading) return;
const form = toRaw(modalState.from);
const validateArr = ['title', 'addr', 'port', 'user'];
if (form.authMode === '0') {
validateArr.push('password');
}
if (form.authMode === '1') {
validateArr.push('privateKey');
}
modalStateFrom
.validate(validateArr)
.then(() => {
modalState.confirmLoading = true;
const hide = message.loading(t('common.loading'), 0);
testNeHost(form)
.then(res => {
if (res.code === RESULT_CODE_SUCCESS) {
message.success({
content: t('views.ne.neHost.testOk'),
duration: 2,
});
} else {
message.error({
content: `${res.msg}`,
duration: 2,
});
}
})
.finally(() => {
modalState.confirmLoading = false;
hide();
});
})
.catch(e => {
message.error(t('common.errorFields', { num: e.errorFields.length }), 3);
});
}
onMounted(() => {
// 初始字典数据
Promise.allSettled([
@@ -531,10 +365,10 @@ onMounted(() => {
<a-card :bordered="false" :body-style="{ padding: '0px' }">
<!-- 插槽-卡片左侧侧 -->
<template #title>
<a-button type="primary" @click.prevent="fnModalVisibleByEdit()">
<!-- <a-button type="primary" @click.prevent="fnModalVisibleByEdit()">
<template #icon><PlusOutlined /></template>
{{ t('common.addText') }}
</a-button>
</a-button> -->
</template>
<!-- 插槽-卡片右侧 -->
@@ -611,7 +445,7 @@ onMounted(() => {
<template #icon><FormOutlined /></template>
</a-button>
</a-tooltip>
<a-tooltip>
<!-- <a-tooltip>
<template #title>{{ t('common.deleteText') }}</template>
<a-button
type="link"
@@ -619,218 +453,19 @@ onMounted(() => {
>
<template #icon><DeleteOutlined /></template>
</a-button>
</a-tooltip>
</a-tooltip> -->
</a-space>
</template>
</template>
</a-table>
<!-- 新增框或修改框 -->
<ProModal
:drag="true"
:width="800"
:destroyOnClose="true"
:keyboard="false"
:mask-closable="false"
:visible="modalState.visibleByEdit"
:title="modalState.title"
:confirm-loading="modalState.confirmLoading"
<EditModal
v-model:open="modalState.openByEdit"
:edit-id="modalState.hostId"
@ok="fnModalOk"
@cancel="fnModalCancel"
>
<a-form
name="modalStateFromByEdit"
layout="horizontal"
:label-col="{ span: 6 }"
:label-wrap="true"
>
<a-row :gutter="16">
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
:label="t('views.ne.neHost.hostType')"
name="hostType"
>
<a-select
v-model:value="modalState.from.hostType"
default-value="ssh"
:options="dict.neHostType"
>
</a-select>
</a-form-item>
</a-col>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item :label="t('views.ne.neHost.groupId')" name="groupId">
<a-select
v-model:value="modalState.from.groupId"
default-value="0"
:options="dict.neHostGroupId"
>
</a-select>
</a-form-item>
</a-col>
</a-row>
<a-form-item
:label="t('views.ne.neHost.title')"
name="title"
v-bind="modalStateFrom.validateInfos.title"
:label-col="{ span: 3 }"
:label-wrap="true"
>
<a-input
v-model:value="modalState.from.title"
allow-clear
:maxlength="50"
:placeholder="t('common.inputPlease')"
>
</a-input>
</a-form-item>
<a-row :gutter="16">
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
:label="t('views.ne.neHost.addr')"
name="addr"
v-bind="modalStateFrom.validateInfos.addr"
>
<a-input
v-model:value="modalState.from.addr"
allow-clear
:maxlength="128"
:placeholder="t('common.inputPlease')"
>
</a-input>
</a-form-item>
</a-col>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
:label="t('views.ne.neHost.port')"
name="port"
v-bind="modalStateFrom.validateInfos.port"
>
<a-input-number
v-model:value="modalState.from.port"
:min="10"
:max="65535"
:step="1"
:maxlength="5"
style="width: 100%"
></a-input-number>
</a-form-item>
</a-col>
</a-row>
<a-row :gutter="16">
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
:label="t('views.ne.neHost.user')"
name="user"
v-bind="modalStateFrom.validateInfos.user"
>
<a-input
v-model:value="modalState.from.user"
allow-clear
:maxlength="32"
:placeholder="t('common.inputPlease')"
>
</a-input>
</a-form-item>
</a-col>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
:label="t('views.ne.neHost.authMode')"
name="authMode"
>
<a-select
v-model:value="modalState.from.authMode"
default-value="0"
:options="dict.neHostAuthMode"
>
</a-select>
</a-form-item>
</a-col>
</a-row>
<a-form-item
v-if="modalState.from.authMode === '0'"
:label="t('views.ne.neHost.password')"
name="password"
v-bind="modalStateFrom.validateInfos.password"
:label-col="{ span: 3 }"
:label-wrap="true"
>
<a-input-password
v-model:value="modalState.from.password"
:maxlength="128"
:placeholder="t('common.inputPlease')"
>
</a-input-password>
</a-form-item>
<template v-if="modalState.from.authMode === '1'">
<a-form-item
:label="t('views.ne.neHost.privateKey')"
name="privateKey"
v-bind="modalStateFrom.validateInfos.privateKey"
:label-col="{ span: 3 }"
:label-wrap="true"
>
<a-textarea
v-model:value="modalState.from.privateKey"
:auto-size="{ minRows: 4, maxRows: 6 }"
:maxlength="3000"
:show-count="true"
:placeholder="t('views.ne.neHost.privateKeyPlease')"
/>
</a-form-item>
<a-form-item
:label="t('views.ne.neHost.passPhrase')"
name="passPhrase"
:label-col="{ span: 3 }"
:label-wrap="true"
>
<a-input-password
v-model:value="modalState.from.passPhrase"
:maxlength="128"
:placeholder="t('common.inputPlease')"
>
</a-input-password>
</a-form-item>
</template>
<a-form-item
:label="t('common.remark')"
name="remark"
:label-col="{ span: 3 }"
:label-wrap="true"
>
<a-textarea
v-model:value="modalState.from.remark"
:auto-size="{ minRows: 1, maxRows: 6 }"
:maxlength="450"
:show-count="true"
:placeholder="t('common.inputPlease')"
/>
</a-form-item>
<a-form-item
:label="t('views.ne.neHost.test')"
name="test"
:label-col="{ span: 3 }"
:label-wrap="true"
>
<a-button
type="primary"
shape="round"
@click="fnModalTest"
:loading="modalState.confirmLoading"
>
<template #icon><LinkOutlined /></template>
</a-button>
</a-form-item>
</a-form>
</ProModal>
></EditModal>
</a-card>
</PageContainer>
</template>

View File

@@ -1,10 +1,11 @@
<script setup lang="ts">
import { reactive, onMounted, toRaw } from 'vue';
import { PageContainer } from 'antdv-pro-layout';
import { SizeType } from 'ant-design-vue/lib/config-provider';
import { MenuInfo } from 'ant-design-vue/lib/menu/src/interface';
import { ColumnsType } from 'ant-design-vue/lib/table';
import { Form, Modal, message } from 'ant-design-vue/lib';
import { ProModal } from 'antdv-pro-modal';
import { SizeType } from 'ant-design-vue/es/config-provider';
import { MenuInfo } from 'ant-design-vue/es/menu/src/interface';
import { ColumnsType } from 'ant-design-vue/es/table';
import { Form, Modal, message } from 'ant-design-vue/es';
import { parseDateToStr } from '@/utils/date-utils';
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
import {
@@ -179,7 +180,7 @@ function fnGetList(pageNum?: number) {
/**对话框对象信息状态类型 */
type ModalStateType = {
/**新增框或修改框是否显示 */
visibleByEdit: boolean;
openByEdit: boolean;
/**标题 */
title: string;
/**表单数据 */
@@ -190,7 +191,7 @@ type ModalStateType = {
/**对话框对象信息状态 */
let modalState: ModalStateType = reactive({
visibleByEdit: false,
openByEdit: false,
title: '信息',
from: {
cmdId: undefined,
@@ -234,7 +235,7 @@ function fnModalVisibleByEdit(roleId?: string | number) {
if (!roleId) {
modalStateFrom.resetFields();
modalState.title = t('views.ne.neHostCmd.addTitle');
modalState.visibleByEdit = true;
modalState.openByEdit = true;
} else {
if (modalState.confirmLoading) return;
const hide = message.loading(t('common.loading'), 0);
@@ -246,7 +247,7 @@ function fnModalVisibleByEdit(roleId?: string | number) {
if (res.code === RESULT_CODE_SUCCESS && res.data) {
modalState.from = Object.assign(modalState.from, res.data);
modalState.title = t('views.ne.neHostCmd.editTitle');
modalState.visibleByEdit = true;
modalState.openByEdit = true;
} else {
message.error(t('common.getInfoFail'), 2);
}
@@ -297,7 +298,7 @@ function fnModalOk() {
* 进行表达规则校验
*/
function fnModalCancel() {
modalState.visibleByEdit = false;
modalState.openByEdit = false;
modalStateFrom.resetFields();
}
@@ -503,7 +504,7 @@ onMounted(() => {
:destroyOnClose="true"
:keyboard="false"
:mask-closable="false"
:visible="modalState.visibleByEdit"
:open="modalState.openByEdit"
:title="modalState.title"
:confirm-loading="modalState.confirmLoading"
@ok="fnModalOk"
@@ -515,7 +516,7 @@ onMounted(() => {
:label-col="{ span: 6 }"
:label-wrap="true"
>
<a-row :gutter="16">
<a-row>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
:label="t('views.ne.neHostCmd.cmdType')"

View File

@@ -1,10 +1,10 @@
<script setup lang="ts">
import { reactive, toRaw, watch } from 'vue';
import { Form, Modal, Upload, message, notification } from 'ant-design-vue/lib';
import useI18n from '@/hooks/useI18n';
import { ProModal } from 'antdv-pro-modal';
import { Form, Modal, Upload, message, notification } from 'ant-design-vue/es';
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
import { UploadRequestOption } from 'ant-design-vue/lib/vc-upload/interface';
import { FileType, UploadFile } from 'ant-design-vue/lib/upload/interface';
import { UploadRequestOption } from 'ant-design-vue/es/vc-upload/interface';
import { FileType, UploadFile } from 'ant-design-vue/es/upload/interface';
import {
exportNeConfigBackup,
importNeConfigBackup,
@@ -12,10 +12,11 @@ import {
} from '@/api/ne/neConfigBackup';
import saveAs from 'file-saver';
import { uploadFile } from '@/api/tool/file';
import useI18n from '@/hooks/useI18n';
const { t } = useI18n();
const emit = defineEmits(['ok', 'cancel', 'update:visible']);
const emit = defineEmits(['ok', 'cancel', 'update:open']);
const props = defineProps({
visible: {
open: {
type: Boolean,
default: false,
},
@@ -79,7 +80,7 @@ function typeChange(value: any) {
/**对话框对象信息状态类型 */
type ModalStateType = {
/**新增框或修改框是否显示 */
visibleByEdit: boolean;
openByEdit: boolean;
/**标题 */
title: string;
/**表单数据 */
@@ -97,7 +98,7 @@ type ModalStateType = {
/**对话框对象信息状态 */
let modalState: ModalStateType = reactive({
visibleByEdit: false,
openByEdit: false,
title: '配置文件导入',
from: {
neType: '',
@@ -163,12 +164,12 @@ function fnModalOk() {
* 进行表达规则校验
*/
function fnModalCancel() {
modalState.visibleByEdit = false;
modalState.openByEdit = false;
modalState.confirmLoading = false;
modalStateFrom.resetFields();
modalState.uploadFiles = [];
emit('cancel');
emit('update:visible', false);
emit('update:open', false);
}
/**表单上传前删除 */
@@ -224,14 +225,14 @@ function fnUploadFile(up: UploadRequestOption) {
/**监听是否显示,初始数据 */
watch(
() => props.visible,
() => props.open,
val => {
if (val) {
if (props.neType && props.neId) {
modalState.from.neType = props.neType;
modalState.from.neId = props.neId;
modalState.title = t('views.ne.neInfo.backConf.title');
modalState.visibleByEdit = true;
modalState.openByEdit = true;
}
}
}
@@ -283,14 +284,14 @@ defineExpose({
:width="800"
:keyboard="false"
:mask-closable="false"
:visible="modalState.visibleByEdit"
:open="modalState.openByEdit"
:title="modalState.title"
:confirm-loading="modalState.confirmLoading"
@ok="fnModalOk"
@cancel="fnModalCancel"
>
<a-form name="modalStateFrom" layout="horizontal" :label-col="{ span: 6 }">
<a-row :gutter="16">
<a-row>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item :label="t('views.ne.common.neType')" name="neType">
{{ modalState.from.neType }}

View File

@@ -1,18 +1,19 @@
<script setup lang="ts">
import { reactive, onMounted, toRaw, watch } from 'vue';
import { message, Form, Modal } from 'ant-design-vue/lib';
import useI18n from '@/hooks/useI18n';
import { ProModal } from 'antdv-pro-modal';
import { message, Form, Modal } from 'ant-design-vue/es';
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
import { NE_TYPE_LIST } from '@/constants/ne-constants';
import { regExpIPv4, regExpIPv6 } from '@/utils/regular-utils';
import { getNeInfo, addNeInfo, updateNeInfo } from '@/api/ne/neInfo';
import { neHostAuthorizedRSA, testNeHost } from '@/api/ne/neHost';
import useDictStore from '@/store/modules/dict';
import useI18n from '@/hooks/useI18n';
const { getDict } = useDictStore();
const { t } = useI18n();
const emit = defineEmits(['ok', 'cancel', 'update:visible']);
const emit = defineEmits(['ok', 'cancel', 'update:open']);
const props = defineProps({
visible: {
open: {
type: Boolean,
default: false,
},
@@ -87,7 +88,7 @@ function fnHostAuthorized(row: Record<string, any>) {
/**对话框对象信息状态类型 */
type ModalStateType = {
/**新增框或修改框是否显示 */
visibleByEdit: boolean;
openByEdit: boolean;
/**标题 */
title: string;
/**表单数据 */
@@ -98,7 +99,7 @@ type ModalStateType = {
/**对话框对象信息状态 */
let modalState: ModalStateType = reactive({
visibleByEdit: false,
openByEdit: false,
title: '网元',
from: {
id: undefined,
@@ -214,7 +215,7 @@ function fnModalVisibleByEdit(editId: string) {
if (!editId) {
modalStateFrom.resetFields();
modalState.title = t('views.ne.neInfo.addTitle');
modalState.visibleByEdit = true;
modalState.openByEdit = true;
} else {
if (modalState.confirmLoading) return;
const hide = message.loading(t('common.loading'), 0);
@@ -225,7 +226,7 @@ function fnModalVisibleByEdit(editId: string) {
if (res.code === RESULT_CODE_SUCCESS) {
Object.assign(modalState.from, res.data);
modalState.title = t('views.ne.neInfo.editTitle');
modalState.visibleByEdit = true;
modalState.openByEdit = true;
} else {
message.error(t('common.getInfoFail'), 2);
}
@@ -274,11 +275,11 @@ function fnModalOk() {
* 进行表达规则校验
*/
function fnModalCancel() {
modalState.visibleByEdit = false;
modalState.openByEdit = false;
modalState.confirmLoading = false;
modalStateFrom.resetFields();
emit('cancel');
emit('update:visible', false);
emit('update:open', false);
}
/**表单修改网元类型 */
@@ -341,7 +342,7 @@ function fnNeIPChange(e: any) {
/**监听是否显示,初始数据 */
watch(
() => props.visible,
() => props.open,
val => {
if (val) fnModalVisibleByEdit(props.editId);
}
@@ -372,10 +373,10 @@ onMounted(() => {
:drag="true"
:width="800"
:destroyOnClose="true"
:body-style="{ maxHeight: '650px', 'overflow-y': 'auto' }"
:body-style="{ maxHeight: '600px', 'overflow-y': 'auto' }"
:keyboard="false"
:mask-closable="false"
:visible="modalState.visibleByEdit"
:open="modalState.openByEdit"
:title="modalState.title"
:confirm-loading="modalState.confirmLoading"
@ok="fnModalOk"
@@ -387,7 +388,7 @@ onMounted(() => {
:label-col="{ span: 6 }"
:labelWrap="true"
>
<a-row :gutter="16">
<a-row>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
:label="t('views.ne.common.neType')"
@@ -409,7 +410,7 @@ onMounted(() => {
<template #title>
{{ t('views.ne.common.neTypeTip') }}
</template>
<InfoCircleOutlined style="color: rgba(0, 0, 0, 0.45)" />
<InfoCircleOutlined style="opacity: 0.45; color: inherit" />
</a-tooltip>
</template>
</a-input>
@@ -437,7 +438,7 @@ onMounted(() => {
</a-col>
</a-row>
<a-row :gutter="16">
<a-row>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
:label="t('views.ne.common.neId')"
@@ -456,7 +457,7 @@ onMounted(() => {
<template #title>
{{ t('views.ne.common.neIdTip') }}
</template>
<InfoCircleOutlined style="color: rgba(0, 0, 0, 0.45)" />
<InfoCircleOutlined style="opacity: 0.45; color: inherit" />
</a-tooltip>
</template>
</a-input>
@@ -479,7 +480,7 @@ onMounted(() => {
</a-col>
</a-row>
<a-row :gutter="16">
<a-row>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
:label="t('views.ne.common.ipAddr')"
@@ -500,7 +501,7 @@ onMounted(() => {
{{ t('views.ne.common.ipAddrTip') }}
</div>
</template>
<InfoCircleOutlined style="color: rgba(0, 0, 0, 0.45)" />
<InfoCircleOutlined style="opacity: 0.45; color: inherit" />
</a-tooltip>
</template>
</a-input>
@@ -525,7 +526,7 @@ onMounted(() => {
<template #title>
<div>{{ t('views.ne.common.portTip') }}</div>
</template>
<InfoCircleOutlined style="color: rgba(0, 0, 0, 0.45)" />
<InfoCircleOutlined style="opacity: 0.45; color: inherit" />
</a-tooltip>
</template>
</a-input-number>
@@ -553,13 +554,13 @@ onMounted(() => {
{{ t('views.ne.common.rmUidTip') }}
</div>
</template>
<InfoCircleOutlined style="color: rgba(0, 0, 0, 0.45)" />
<InfoCircleOutlined style="opacity: 0.45; color: inherit" />
</a-tooltip>
</template>
</a-input>
</a-form-item>
<a-row :gutter="16">
<a-row>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item :label="t('views.ne.neInfo.neAddress')" name="neAddress">
<a-input
@@ -573,7 +574,7 @@ onMounted(() => {
<template #title>
<div>{{ t('views.ne.neInfo.neAddressTip') }}</div>
</template>
<InfoCircleOutlined style="color: rgba(0, 0, 0, 0.45)" />
<InfoCircleOutlined style="opacity: 0.45; color: inherit" />
</a-tooltip>
</template>
</a-input>
@@ -591,7 +592,7 @@ onMounted(() => {
</a-col>
</a-row>
<a-row :gutter="16">
<a-row>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
:label="t('views.ne.neInfo.vendorName')"
@@ -649,7 +650,7 @@ onMounted(() => {
{{ `${host.hostType.toUpperCase()} ${host.port}` }}
</span>
</template>
<a-row :gutter="16">
<a-row>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item :label="t('views.ne.neHost.addr')">
<a-input
@@ -662,7 +663,10 @@ onMounted(() => {
</a-form-item>
</a-col>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item :label="t('views.ne.neHost.port')" name="port">
<a-form-item
:label="t('views.ne.neHost.port')"
name="neHost.port"
>
<a-input-number
v-model:value="host.port"
:min="10"
@@ -690,7 +694,7 @@ onMounted(() => {
</a-input>
</a-form-item>
<a-row :gutter="16" v-if="host.hostType === 'ssh'">
<a-row v-if="host.hostType === 'ssh'">
<a-col :lg="12" :md="12" :xs="24">
<a-form-item :label="t('views.ne.neHost.user')">
<a-input

View File

@@ -1,13 +1,14 @@
<script setup lang="ts">
import { reactive, toRaw, watch } from 'vue';
import { message, Form } from 'ant-design-vue/lib';
import { ProModal } from 'antdv-pro-modal';
import { message, Form } from 'ant-design-vue/es';
import useI18n from '@/hooks/useI18n';
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
import { getOAMFile, saveOAMFile } from '@/api/ne/neInfo';
const { t } = useI18n();
const emit = defineEmits(['ok', 'cancel', 'update:visible']);
const emit = defineEmits(['ok', 'cancel', 'update:open']);
const props = defineProps({
visible: {
open: {
type: Boolean,
default: false,
},
@@ -25,7 +26,7 @@ const props = defineProps({
/**对话框对象信息状态类型 */
type ModalStateType = {
/**新增框或修改框是否显示 */
visibleByEdit: boolean;
openByEdit: boolean;
/**标题 */
title: string;
/**是否同步 */
@@ -38,7 +39,7 @@ type ModalStateType = {
/**对话框对象信息状态 */
let modalState: ModalStateType = reactive({
visibleByEdit: false,
openByEdit: false,
title: 'OAM Configuration',
sync: true,
from: {
@@ -87,7 +88,7 @@ function fnModalVisibleByTypeAndId(neType: string, neId: string) {
kpiTimer: data.kpiConfig.timer,
});
modalState.title = t('views.ne.neInfo.oam.title');
modalState.visibleByEdit = true;
modalState.openByEdit = true;
} else {
message.error(res.msg, 3);
}
@@ -142,16 +143,16 @@ function fnModalOk() {
* 进行表达规则校验
*/
function fnModalCancel() {
modalState.visibleByEdit = false;
modalState.openByEdit = false;
modalState.confirmLoading = false;
modalStateFrom.resetFields();
emit('cancel');
emit('update:visible', false);
emit('update:open', false);
}
/**监听是否显示,初始数据 */
watch(
() => props.visible,
() => props.open,
val => {
if (val) {
if (props.neType && props.neId) {
@@ -166,10 +167,10 @@ watch(
<ProModal
:drag="true"
:destroyOnClose="true"
:body-style="{ maxHeight: '650px', 'overflow-y': 'auto' }"
:body-style="{ maxHeight: '600px', 'overflow-y': 'auto' }"
:keyboard="false"
:mask-closable="false"
:visible="modalState.visibleByEdit"
:open="modalState.openByEdit"
:title="modalState.title"
:confirm-loading="modalState.confirmLoading"
@ok="fnModalOk"
@@ -196,7 +197,7 @@ watch(
<a-collapse class="collapse" ghost>
<a-collapse-panel header="OAM">
<a-row :gutter="16">
<a-row>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
:label="t('views.ne.neInfo.oam.oamEnable')"
@@ -239,7 +240,7 @@ watch(
</a-form-item>
</a-collapse-panel>
<a-collapse-panel header="SNMP">
<a-row :gutter="16">
<a-row>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
:label="t('views.ne.neInfo.oam.snmpEnable')"
@@ -271,7 +272,7 @@ watch(
</a-row>
</a-collapse-panel>
<a-collapse-panel header="KPI">
<a-row :gutter="16">
<a-row>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
:label="t('views.ne.neInfo.oam.kpiEnable')"

View File

@@ -1,5 +1,5 @@
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
import { Modal, message } from 'ant-design-vue/lib';
import { Modal, message } from 'ant-design-vue/es';
import useI18n from '@/hooks/useI18n';
import { useRouter } from 'vue-router';
import { updateNeConfigReload } from '@/api/configManage/configParam';

View File

@@ -1,10 +1,10 @@
<script setup lang="ts">
import { reactive, onMounted, toRaw, defineAsyncComponent, ref } from 'vue';
import { PageContainer } from 'antdv-pro-layout';
import { message, Modal } from 'ant-design-vue/lib';
import { SizeType } from 'ant-design-vue/lib/config-provider';
import { MenuInfo } from 'ant-design-vue/lib/menu/src/interface';
import { ColumnsType } from 'ant-design-vue/lib/table';
import { message, Modal } from 'ant-design-vue/es';
import { SizeType } from 'ant-design-vue/es/config-provider';
import { MenuInfo } from 'ant-design-vue/es/menu/src/interface';
import { ColumnsType } from 'ant-design-vue/es/table';
import useI18n from '@/hooks/useI18n';
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
import useNeInfoStore from '@/store/modules/neinfo';
@@ -177,11 +177,11 @@ function fnTableSelectedRowKeys(keys: (string | number)[]) {
/**对话框对象信息状态类型 */
type ModalStateType = {
/**配置备份框是否显示 */
visibleByBackConf: boolean;
openByBackConf: boolean;
/**OAM文件配置框是否显示 */
visibleByOAM: boolean;
openByOAM: boolean;
/**新增框或修改框是否显示 */
visibleByEdit: boolean;
openByEdit: boolean;
/**新增框或修改框ID */
editId: string;
/**OAM框网元类型ID */
@@ -193,9 +193,9 @@ type ModalStateType = {
/**对话框对象信息状态 */
let modalState: ModalStateType = reactive({
visibleByBackConf: false,
visibleByOAM: false,
visibleByEdit: false,
openByBackConf: false,
openByOAM: false,
openByEdit: false,
editId: '',
neId: '',
neType: '',
@@ -212,7 +212,7 @@ function fnModalVisibleByEdit(row?: Record<string, any>) {
} else {
modalState.editId = row.id;
}
modalState.visibleByEdit = !modalState.visibleByEdit;
modalState.openByEdit = !modalState.openByEdit;
}
/**
@@ -256,9 +256,9 @@ function fnModalEditOk(from: Record<string, any>) {
*/
function fnModalEditCancel() {
modalState.editId = '';
modalState.visibleByEdit = false;
modalState.visibleByOAM = false;
modalState.visibleByBackConf = false;
modalState.openByEdit = false;
modalState.openByOAM = false;
modalState.openByBackConf = false;
}
/**
@@ -334,7 +334,7 @@ function fnRecordMore(type: string | number, row: Record<string, any>) {
case 'oam':
modalState.neId = row.neId;
modalState.neType = row.neType;
modalState.visibleByOAM = !modalState.visibleByOAM;
modalState.openByOAM = !modalState.openByOAM;
break;
case 'backConfExport':
backConf.value.exportConf(row.neType, row.neId);
@@ -342,7 +342,7 @@ function fnRecordMore(type: string | number, row: Record<string, any>) {
case 'backConfImport':
modalState.neId = row.neId;
modalState.neType = row.neType;
modalState.visibleByBackConf = !modalState.visibleByBackConf;
modalState.openByBackConf = !modalState.openByBackConf;
break;
default:
console.warn(type);
@@ -655,7 +655,7 @@ onMounted(() => {
</template>
</template>
<template #expandedRowRender="{ record }">
<a-row :gutter="16">
<a-row>
<a-col :offset="2" :lg="8" :md="8" :xs="8">
<a-divider orientation="left">
{{ t('views.ne.neInfo.info') }}
@@ -753,7 +753,7 @@ onMounted(() => {
<!-- 新增框或修改框 -->
<EditModal
v-model:visible="modalState.visibleByEdit"
v-model:open="modalState.openByEdit"
:edit-id="modalState.editId"
@ok="fnModalEditOk"
@cancel="fnModalEditCancel"
@@ -761,7 +761,7 @@ onMounted(() => {
<!-- OAM编辑框 -->
<OAMModal
v-model:visible="modalState.visibleByOAM"
v-model:open="modalState.openByOAM"
:ne-id="modalState.neId"
:ne-type="modalState.neType"
@cancel="fnModalEditCancel"
@@ -770,7 +770,7 @@ onMounted(() => {
<!-- 配置文件备份框 -->
<BackConfModal
ref="backConf"
v-model:visible="modalState.visibleByBackConf"
v-model:open="modalState.openByBackConf"
:ne-id="modalState.neId"
:ne-type="modalState.neType"
@cancel="fnModalEditCancel"

View File

@@ -1,6 +1,7 @@
<script setup lang="ts">
import { reactive, onMounted, toRaw, watch } from 'vue';
import { Form, Modal, Upload, message } from 'ant-design-vue/lib';
import { ProModal } from 'antdv-pro-modal';
import { Form, Modal, Upload, message } from 'ant-design-vue/es';
import useI18n from '@/hooks/useI18n';
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
import {
@@ -8,16 +9,16 @@ import {
getNeLicense,
getNeLicenseByTypeAndID,
} from '@/api/ne/neLicense';
import { UploadRequestOption } from 'ant-design-vue/lib/vc-upload/interface';
import { FileType } from 'ant-design-vue/lib/upload/interface';
import { UploadRequestOption } from 'ant-design-vue/es/vc-upload/interface';
import { FileType } from 'ant-design-vue/es/upload/interface';
import { uploadFile } from '@/api/tool/file';
import { useClipboard } from '@vueuse/core';
import saveAs from 'file-saver';
const { copy } = useClipboard({ legacy: true });
const { t } = useI18n();
const emit = defineEmits(['ok', 'cancel', 'update:visible']);
const emit = defineEmits(['ok', 'cancel', 'update:open']);
const props = defineProps({
visible: {
open: {
type: Boolean,
default: false,
},
@@ -45,7 +46,7 @@ const props = defineProps({
/**对话框对象信息状态类型 */
type ModalStateType = {
/**新增框或修改框是否显示 */
visibleByEdit: boolean;
openByEdit: boolean;
/**标题 */
title: string;
/**表单数据 */
@@ -66,7 +67,7 @@ type ModalStateType = {
/**对话框对象信息状态 */
let modalState: ModalStateType = reactive({
visibleByEdit: false,
openByEdit: false,
title: '授权文件',
from: {
id: '',
@@ -136,12 +137,12 @@ function fnModalOk() {
* 进行表达规则校验
*/
function fnModalCancel() {
modalState.visibleByEdit = false;
modalState.openByEdit = false;
modalState.confirmLoading = false;
modalStateFrom.resetFields();
modalState.uploadFiles = [];
emit('cancel');
emit('update:visible', false);
emit('update:open', false);
}
/**表单上传前检查或转换压缩 */
@@ -227,7 +228,7 @@ function fnModalVisibleById(id: string) {
modalState.from.licensePath = '';
modalState.from.reload = props.reload;
modalState.title = t('views.ne.neLicense.updateTtile');
modalState.visibleByEdit = true;
modalState.openByEdit = true;
} else {
message.error(res.msg, 3);
}
@@ -252,7 +253,7 @@ function fnModalVisibleByTypeAndId(neType: string, neId: string) {
modalState.from.licensePath = '';
modalState.from.reload = props.reload;
modalState.title = t('views.ne.neLicense.updateTtile');
modalState.visibleByEdit = true;
modalState.openByEdit = true;
} else {
message.error(res.msg, 3);
}
@@ -265,7 +266,7 @@ function fnModalVisibleByTypeAndId(neType: string, neId: string) {
/**监听是否显示,初始数据 */
watch(
() => props.visible,
() => props.open,
val => {
if (val) {
if (props.editId) {
@@ -288,7 +289,7 @@ onMounted(() => {});
:destroyOnClose="true"
:keyboard="false"
:mask-closable="false"
:visible="modalState.visibleByEdit"
:open="modalState.openByEdit"
:title="modalState.title"
:confirm-loading="modalState.confirmLoading"
@ok="fnModalOk"
@@ -301,7 +302,7 @@ onMounted(() => {});
:label-col="{ span: 6 }"
:labelWrap="true"
>
<a-row :gutter="16">
<a-row>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
:label-col="{ span: 12 }"

View File

@@ -1,16 +1,17 @@
<script setup lang="ts">
import { reactive, onMounted, watch, PropType, h } from 'vue';
import { message, notification, Upload } from 'ant-design-vue/lib';
import useI18n from '@/hooks/useI18n';
import { message, notification, Upload } from 'ant-design-vue/es';
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
import { UploadRequestOption } from 'ant-design-vue/lib/vc-upload/interface';
import { FileType } from 'ant-design-vue/lib/upload/interface';
import { UploadRequestOption } from 'ant-design-vue/es/vc-upload/interface';
import { FileType } from 'ant-design-vue/es/upload/interface';
import { ProModal } from 'antdv-pro-modal';
import { uploadFile } from '@/api/tool/file';
import { changeNeLicense } from '@/api/ne/neLicense';
import useI18n from '@/hooks/useI18n';
const { t } = useI18n();
const emit = defineEmits(['ok', 'cancel', 'update:visible']);
const emit = defineEmits(['ok', 'cancel', 'update:open']);
const props = defineProps({
visible: {
open: {
type: Boolean,
default: false,
},
@@ -24,7 +25,7 @@ const props = defineProps({
/**对话框对象信息状态类型 */
type ModalStateType = {
/**新增框或修改框是否显示 */
visibleByUploadFile: boolean;
openByUploadFile: boolean;
/**标题 */
title: string;
/**授权文件路径 */
@@ -37,7 +38,7 @@ type ModalStateType = {
/**对话框对象信息状态 */
let modalState: ModalStateType = reactive({
visibleByUploadFile: false,
openByUploadFile: false,
licensePath: '',
uploadFiles: [],
title: '授权文件',
@@ -117,12 +118,12 @@ async function fnModalOk() {
* 进行表达规则校验
*/
function fnModalCancel() {
modalState.visibleByUploadFile = false;
modalState.openByUploadFile = false;
modalState.confirmLoading = false;
modalState.licensePath = '';
modalState.uploadFiles = [];
emit('cancel');
emit('update:visible', false);
emit('update:open', false);
}
/**表单上传前检查或转换压缩 */
@@ -172,11 +173,11 @@ function fnUploadFile(up: UploadRequestOption) {
/**监听是否显示,初始数据 */
watch(
() => props.visible,
() => props.open,
val => {
if (val) {
modalState.title = t('views.ne.neLicense.updateTtile');
modalState.visibleByUploadFile = true;
modalState.openByUploadFile = true;
}
}
);
@@ -190,7 +191,7 @@ onMounted(() => {});
:destroyOnClose="true"
:keyboard="false"
:mask-closable="false"
:visible="modalState.visibleByUploadFile"
:open="modalState.openByUploadFile"
:title="modalState.title"
:confirm-loading="modalState.confirmLoading"
:cancel-button-props="{ disabled: modalState.confirmLoading }"

View File

@@ -1,9 +1,9 @@
<script setup lang="ts">
import { reactive, ref, onMounted, toRaw, defineAsyncComponent } from 'vue';
import { PageContainer } from 'antdv-pro-layout';
import { Modal, TableColumnsType, message } from 'ant-design-vue/lib';
import { SizeType } from 'ant-design-vue/lib/config-provider';
import { MenuInfo } from 'ant-design-vue/lib/menu/src/interface';
import { Modal, TableColumnsType, message } from 'ant-design-vue/es';
import { SizeType } from 'ant-design-vue/es/config-provider';
import { MenuInfo } from 'ant-design-vue/es/menu/src/interface';
import useNeInfoStore from '@/store/modules/neinfo';
import useI18n from '@/hooks/useI18n';
import useDictStore from '@/store/modules/dict';
@@ -208,7 +208,7 @@ function fnGetList(pageNum?: number) {
/**对话框对象信息状态类型 */
type ModalStateType = {
/**新增框或修改框是否显示 */
visibleByEdit: boolean;
openByEdit: boolean;
/**授权记录ID */
licenseId: string;
/**确定按钮 loading */
@@ -217,7 +217,7 @@ type ModalStateType = {
/**对话框对象信息状态 */
let modalState: ModalStateType = reactive({
visibleByEdit: false,
openByEdit: false,
licenseId: '',
confirmLoading: false,
});
@@ -228,7 +228,7 @@ let modalState: ModalStateType = reactive({
*/
function fnModalVisibleByEdit(licenseId: string) {
modalState.licenseId = licenseId;
modalState.visibleByEdit = true;
modalState.openByEdit = true;
}
/**
@@ -245,7 +245,7 @@ function fnModalOk() {
* 进行表达规则校验
*/
function fnModalCancel() {
modalState.visibleByEdit = false;
modalState.openByEdit = false;
modalState.licenseId = '';
}
@@ -413,7 +413,7 @@ onMounted(() => {
:loading="modalState.confirmLoading"
@click.prevent="fnRecordStateBatch()"
>
<template #icon><SecurityScanOutlined /></template>
<template #icon><CloudSyncOutlined /></template>
{{ t('views.ne.neLicense.reloadBatch') }}
</a-button>
</a-space>
@@ -505,19 +505,19 @@ onMounted(() => {
</template>
<template v-if="column.key === 'id'">
<a-space :size="8" align="center">
<a-tooltip placement="topRight">
<template #title>{{ t('views.ne.neLicense.reload') }}</template>
<a-button type="link" @click.prevent="fnRecordState(record)">
<template #icon><CloudSyncOutlined /> </template>
</a-button>
</a-tooltip>
<a-tooltip placement="topRight">
<template #title>{{ t('views.ne.neLicense.change') }}</template>
<a-button
type="link"
@click.prevent="fnModalVisibleByEdit(record.id)"
>
<template #icon><InteractionOutlined /> </template>
</a-button>
</a-tooltip>
<a-tooltip placement="topRight">
<template #title>{{ t('views.ne.neLicense.reload') }}</template>
<a-button type="link" @click.prevent="fnRecordState(record)">
<template #icon><SecurityScanOutlined /> </template>
<template #icon><CloudUploadOutlined /> </template>
</a-button>
</a-tooltip>
</a-space>
@@ -528,7 +528,7 @@ onMounted(() => {
<!-- 文件上传框 -->
<EditModal
v-model:visible="modalState.visibleByEdit"
v-model:open="modalState.openByEdit"
:edit-id="modalState.licenseId"
@ok="fnModalOk"
@cancel="fnModalCancel"

View File

@@ -1,5 +1,5 @@
<script setup lang="ts">
import { Form, Modal, message } from 'ant-design-vue/lib';
import { Form, Modal, message } from 'ant-design-vue/es';
import { onMounted, reactive, toRaw } from 'vue';
import { addNeInfo, getNeInfoByTypeAndID, updateNeInfo } from '@/api/ne/neInfo';
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
@@ -344,7 +344,7 @@ onMounted(() => {
:label-col="{ span: 6 }"
:labelWrap="true"
>
<a-row :gutter="16">
<a-row>
<a-col :lg="6" :md="6" :xs="24" :offset="6">
<a-form-item
:label="t('views.ne.common.neType')"
@@ -368,7 +368,7 @@ onMounted(() => {
<template #title>
{{ t('views.ne.common.neTypeTip') }}
</template>
<InfoCircleOutlined style="color: rgba(0, 0, 0, 0.45)" />
<InfoCircleOutlined style="opacity: 0.45; color: inherit;" />
</a-tooltip>
</template>
</a-input>
@@ -392,7 +392,7 @@ onMounted(() => {
<template #title>
{{ t('views.ne.common.neIdTip') }}
</template>
<InfoCircleOutlined style="color: rgba(0, 0, 0, 0.45)" />
<InfoCircleOutlined style="opacity: 0.45; color: inherit;" />
</a-tooltip>
</template>
</a-input>
@@ -400,7 +400,7 @@ onMounted(() => {
</a-col>
</a-row>
<a-row :gutter="16">
<a-row>
<a-col :lg="6" :md="6" :xs="24" :offset="6">
<a-form-item
:label="t('views.ne.common.ipAddr')"
@@ -422,7 +422,7 @@ onMounted(() => {
{{ t('views.ne.common.ipAddrTip') }}
</div>
</template>
<InfoCircleOutlined style="color: rgba(0, 0, 0, 0.45)" />
<InfoCircleOutlined style="opacity: 0.45; color: inherit;" />
</a-tooltip>
</template>
</a-input>
@@ -447,7 +447,7 @@ onMounted(() => {
<template #title>
<div>{{ t('views.ne.common.portTip') }}</div>
</template>
<InfoCircleOutlined style="color: rgba(0, 0, 0, 0.45)" />
<InfoCircleOutlined style="opacity: 0.45; color: inherit;" />
</a-tooltip>
</template>
</a-input-number>

View File

@@ -1,5 +1,5 @@
<script setup lang="ts">
import { Modal, message } from 'ant-design-vue/lib';
import { Modal, message } from 'ant-design-vue/es';
import { defineAsyncComponent, onMounted, reactive, toRaw } from 'vue';
import { fnToStepName, stepState } from '../hooks/useStep';
import useI18n from '@/hooks/useI18n';
@@ -10,7 +10,7 @@ import {
} from '@/constants/result-constants';
import { listNeSoftware, newNeVersion } from '@/api/ne/neSoftware';
import { parseDateToStr } from '@/utils/date-utils';
import { ColumnsType } from 'ant-design-vue/lib/table';
import { ColumnsType } from 'ant-design-vue/es/table';
const { t } = useI18n();
const EditModal = defineAsyncComponent(
() => import('../../../ne/neSoftware/components/EditModal.vue')
@@ -152,7 +152,7 @@ type StateType = {
/**文件操作类型 上传 or 选择 */
optionType: 'upload' | 'option';
/**文件上传 */
visibleByFile: boolean;
openByFile: boolean;
/**网元拓展包列表类型 */
depType: string[];
/**软件包信息数据 */
@@ -172,7 +172,7 @@ type StateType = {
let state: StateType = reactive({
stepNext: false,
optionType: 'option',
visibleByFile: false,
openByFile: false,
depType: [],
from: {
id: undefined,
@@ -200,7 +200,7 @@ function fnOptionTypeChange() {
/**对话框弹出 */
function fnModalOpen() {
state.visibleByFile = !state.visibleByFile;
state.openByFile = !state.openByFile;
}
/**对话框弹出确认执行函数*/
@@ -210,7 +210,7 @@ function fnModalOk(e: any) {
/**对话框弹出关闭执行函数*/
function fnModalCancel() {
state.visibleByFile = false;
state.openByFile = false;
}
/**版本安装 */
@@ -382,7 +382,7 @@ onMounted(() => {
<!-- 文件上传框 -->
<EditModal
v-model:visible="state.visibleByFile"
v-model:open="state.openByFile"
@ok="fnModalOk"
@cancel="fnModalCancel"
></EditModal>

Some files were not shown because too many files have changed in this diff Show More