新增自定义首页

This commit is contained in:
lai
2024-10-16 14:12:31 +08:00
parent ba98b37306
commit 53d9e63c36
6 changed files with 589 additions and 434 deletions

View File

@@ -1782,6 +1782,9 @@ export default {
reset: "System Reset",
resetInstruction: "A system reset will erase all data in the current system, please proceed with caution!!!!",
resetTipContent: 'Are you sure you want to clear all data from the current system and insist on continuing?',
homeInstruction:'Set the system home page',
home: 'System home page',
homeTip:'Do you want to submit the current interface as the system interface?',
},
role:{
allScopeOptions:'All data permissions',

View File

@@ -1782,6 +1782,9 @@ export default {
reset: "系统重置",
resetInstruction: "系统重置将会清除当前系统内所有数据,请谨慎操作!!!",
resetTipContent: '确认要清除当前系统内所有数据并坚持继续吗?',
homeInstruction:'设置系统首页界面',
home: '系统首页',
homeTip:'确认要提交当前界面为系统界面吗?',
},
role:{
allScopeOptions:'全部数据权限',

View File

@@ -1,446 +1,38 @@
<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 { reactive, toRaw, ref, onMounted, onBeforeUnmount, markRaw } from 'vue';
import { listMain } from '@/api/index';
import useI18n from '@/hooks/useI18n';
import { TooltipComponent } from 'echarts/components';
import { GaugeChart } from 'echarts/charts';
import { CanvasRenderer } from 'echarts/renderers';
import * as echarts from 'echarts/core';
import { TitleComponent, LegendComponent } from 'echarts/components';
import { PieChart } from 'echarts/charts';
import { LabelLayout } from 'echarts/features';
import { useRoute } from 'vue-router';
import useAppStore from '@/store/modules/app';
import useDictStore from '@/store/modules/dict';
const { getDict } = useDictStore();
const appStore = useAppStore();
const route = useRoute();
const { t } = useI18n();
import {
defineAsyncComponent,
onMounted,
toRaw,
shallowRef,
ref,
reactive,
} from 'vue';
import { listMenu } from '@/api/system/menu';
import { getConfig, changeValue } from '@/api/system/config';
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
import { message } from 'ant-design-vue';
echarts.use([
TooltipComponent,
GaugeChart,
TitleComponent,
LegendComponent,
PieChart,
CanvasRenderer,
LabelLayout,
]);
/**图DOM节点实例对象 */
const statusBar = ref<HTMLElement | undefined>(undefined);
/**图实例对象 */
const statusBarChart = ref<any>(null);
/**网元状态字典数据 */
let indexColor = ref<DictType[]>([
{ label: 'Normal', value: 'normal', tagType: '', tagClass: '#91cc75' },
{
label: 'Abnormal',
value: 'abnormal',
tagType: '',
tagClass: '#ee6666',
},
]);
/**表格字段列 */
//customRender(){} ----单元格处理
let tableColumns: ColumnsType = [
{
title: t('views.index.object'),
dataIndex: 'name',
align: 'center',
key: 'status',
},
{
title: t('views.index.realNeStatus'),
dataIndex: 'status',
align: 'center',
customRender(opt) {
if (opt.value == 'Normal') return t('views.index.normal');
return t('views.index.abnormal');
},
},
{
title: t('views.index.reloadTime'),
dataIndex: 'refresh',
align: 'center',
},
{
title: t('views.index.version'),
dataIndex: 'version',
align: 'center',
},
{
title: t('views.index.serialNum'),
dataIndex: 'serialNum',
align: 'center',
},
{
title: t('views.index.expiryDate'),
dataIndex: 'expiryDate',
align: 'center',
},
{
title: t('views.index.ipAddress'),
dataIndex: 'ipAddress',
key: 'groupName',
align: 'center',
},
];
/**表格状态类型 */
type TabeStateType = {
/**加载等待 */
loading: boolean;
/**紧凑型 */
size: string;
/**搜索栏 */
seached: boolean;
/**记录数据 */
data: object[];
/**勾选记录 */
selectedRowKeys: (string | number)[];
};
/**表格状态 */
let tableState: TabeStateType = reactive({
loading: false,
size: 'middle',
seached: false,
data: [],
selectedRowKeys: [],
});
/**表格状态 */
let nfInfo: any = reactive({
obj: 'OMC',
version: appStore.version,
status: t('views.index.normal'),
outTimeDate: '',
serialNum: appStore.serialNum,
});
/**表格状态类型 */
type nfStateType = {
/**主机名 */
hostName: string;
/**操作系统信息 */
osInfo: string;
/**数据库信息 */
dbInfo: string;
/**IP地址 */
ipAddress: string;
/**端口 */
port: number;
/**版本 */
version: string;
/**CPU利用率 */
cpuUse: string;
/**内存使用 */
memoryUse: string;
/**用户容量 */
capability: number;
/**序列号 */
serialNum: string;
/**许可证到期日期 */
/* selectedRowKeys: (string | number)[];*/
expiryDate: string;
};
/**网元详细信息 */
let pronInfo: nfStateType = reactive({
hostName: '5gc',
osInfo: 'Linux 5gc 4.15.0-112-generic 2020 x86_64 GNU/Linux',
dbInfo: 'db v9.9.9',
ipAddress: '-',
port: 33030,
version: '-',
cpuUse: '-',
memoryUse: '-',
capability: 0,
serialNum: '-',
expiryDate: '-',
});
/**查询网元状态列表 */
function fnGetList(one: boolean) {
if (tableState.loading) return;
one && (tableState.loading = true);
listMain().then(res => {
tableState.data = res;
tableState.loading = false;
var rightNum = 0;
var errorNum = 0;
// if (res.length) nfInfo.serialNum = res[0].serialNum;
for (let i = 0; i < res.length; i++) {
if (res[i].status == '正常' || res[i].status == 'Normal') {
rightNum++;
} else {
errorNum++;
}
}
const optionData: any = {
title: {
text: '',
subtext: '',
left: 'center',
},
tooltip: {
trigger: 'item',
},
legend: {
orient: 'vertical',
left: 'left',
},
color: indexColor.value.map(item => item.tagClass),
series: [
{
name: t('views.index.realNeStatus'),
type: 'pie',
radius: '70%',
center: ['50%', '50%'],
data: [
{ value: rightNum, name: t('views.index.normal') },
{ value: errorNum, name: t('views.index.abnormal') },
],
emphasis: {
itemStyle: {
shadowBlur: 10,
shadowOffsetX: 0,
shadowColor: 'rgba(0, 0, 0, 0.5)',
},
},
label: {},
},
],
};
fnDesign(statusBar.value, optionData);
});
}
function fnDesign(container: HTMLElement | undefined, option: any) {
if (!container) return;
if (!statusBarChart.value) {
statusBarChart.value = markRaw(echarts.init(container, 'light'));
}
option && statusBarChart.value.setOption(option);
// 创建 ResizeObserver 实例
var observer = new ResizeObserver(entries => {
if (statusBarChart.value) {
statusBarChart.value.resize();
}
});
// 监听元素大小变化
observer.observe(container);
}
/**抽屉 网元详细信息 */
const visible = ref(false);
const closeDrawer = () => {
visible.value = false;
};
/**抽屉 网元详细信息 */
/**监听表格行事件*/
function rowClick(record: any, index: any) {
return {
onClick: (event: any) => {
if (
toRaw(record).status == '异常' ||
toRaw(record).status == 'Abnormal'
) {
message.error(t('views.index.neStatus'), 2);
return false;
} else {
let pronData = toRaw(record);
const totalMemInKB = pronData.memUsage?.totalMem;
const nfUsedMemInKB = pronData.memUsage?.nfUsedMem;
const sysMemUsageInKB = pronData.memUsage?.sysMemUsage;
// 将KB转换为MB
const totalMemInMB = Math.round((totalMemInKB / 1024) * 100) / 100;
const nfUsedMemInMB = Math.round((nfUsedMemInKB / 1024) * 100) / 100;
const sysMemUsageInMB =
Math.round((sysMemUsageInKB / 1024) * 100) / 100;
//渲染详细信息
pronInfo = {
hostName: pronData.hostName,
osInfo: pronData.osInfo,
dbInfo: pronData.dbInfo,
ipAddress: pronData.ipAddress,
port: pronData.port,
version: pronData.version,
cpuUse:
pronData.name +
':' +
pronData.cpuUsage?.nfCpuUsage / 100 +
'%; ' +
'SYS:' +
pronData.cpuUsage?.sysCpuUsage / 100 +
'%',
memoryUse:
'Total:' +
totalMemInMB +
'MB; ' +
pronData.name +
':' +
nfUsedMemInMB +
'MB; SYS:' +
sysMemUsageInMB +
'MB',
capability: pronData.capability,
serialNum: pronData.serialNum,
expiryDate: pronData.expiryDate,
};
}
visible.value = true;
},
};
}
let timer: any;
/**
* 国际化翻译转换
*/
function fnLocale() {
let title = route.meta.title as string;
if (title.indexOf('router.') !== -1) {
title = t(title);
}
appStore.setTitle(title);
}
// 异步加载组件
const currentComponent = shallowRef(
defineAsyncComponent(() => import('./neStatus/index.vue'))
);
onMounted(() => {
getDict('index_status')
.then(res => {
if (res.length > 0) {
indexColor.value = res;
//获取当前系统设置的首页路径 111为configID
getConfig(111).then(res => {
if (res.code === RESULT_CODE_SUCCESS && res.data) {
if (res.data.configValue) {
currentComponent.value = defineAsyncComponent(
() => import(`./${res.data.configValue}.vue`)
);
}
})
.finally(() => {
fnLocale();
fnGetList(true);
timer = setInterval(() => fnGetList(false), 10000); // 每隔10秒执行一次
});
});
// 在组件卸载之前清除定时器
onBeforeUnmount(() => {
clearInterval(timer);
}
});
});
</script>
<template>
<PageContainer :breadcrumb="{}">
<div>
<a-drawer :visible="visible" @close="closeDrawer" :width="700">
<a-descriptions bordered :column="1" :label-style="{ width: '160px' }">
<a-descriptions-item :label="t('views.index.hostName')">
{{ pronInfo.hostName }}
</a-descriptions-item>
<a-descriptions-item :label="t('views.index.osInfo')">
{{ pronInfo.osInfo }}
</a-descriptions-item>
<!-- <a-descriptions-item :label="t('views.index.dbInfo')">
{{ pronInfo.dbInfo }}
</a-descriptions-item> -->
<a-descriptions-item :label="t('views.index.ipAddress')">
{{ pronInfo.ipAddress }}
</a-descriptions-item>
<!-- <a-descriptions-item :label="t('views.index.port')">
{{ pronInfo.port }}
</a-descriptions-item> -->
<a-descriptions-item :label="t('views.index.version')">
{{ pronInfo.version }}
</a-descriptions-item>
<a-descriptions-item :label="t('views.index.cpuUse')">
{{ pronInfo.cpuUse }}
</a-descriptions-item>
<a-descriptions-item :label="t('views.index.memoryUse')">
{{ pronInfo.memoryUse }}
</a-descriptions-item>
<a-descriptions-item :label="t('views.index.capability')">
{{ pronInfo.capability }}
</a-descriptions-item>
<a-descriptions-item :label="t('views.index.serialNum')">
{{ pronInfo.serialNum }}
</a-descriptions-item>
<a-descriptions-item :label="t('views.index.expiryDate')">
{{ pronInfo.expiryDate }}
</a-descriptions-item>
</a-descriptions>
</a-drawer>
</div>
<a-row :gutter="16">
<a-col :lg="14" :md="16" :xs="24">
<!-- 表格列表 -->
<a-table
class="table"
row-key="id"
:columns="tableColumns"
:loading="tableState.loading"
:data-source="tableState.data"
:pagination="false"
:scroll="{ x: true }"
:customRow="rowClick"
>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'status'">
<div v-if="record.status == '正常' || record.status == 'Normal'">
<a-tag color="blue">{{ record.name }}</a-tag>
</div>
<div v-else>
<a-tag color="pink">{{ record.name }}</a-tag>
</div>
</template>
</template>
</a-table>
</a-col>
<a-col :lg="10" :md="8" :xs="24">
<a-card :title="t('views.index.runStatus')" style="margin-bottom: 16px">
<div style="width: 100%; min-height: 200px" ref="statusBar"></div>
</a-card>
<a-card :title="t('views.index.mark')" style="margin-top: 16px">
<a-descriptions
bordered
:column="1"
:label-style="{ width: '160px' }"
>
<a-descriptions-item :label="t('views.index.object')">{{
nfInfo.obj
}}</a-descriptions-item>
<template v-if="nfInfo.obj === 'OMC'">
<a-descriptions-item :label="t('views.index.versionNum')">{{
nfInfo.version
}}</a-descriptions-item>
<a-descriptions-item :label="t('views.index.systemStatus')">{{
nfInfo.status
}}</a-descriptions-item>
</template>
<template v-else>
<a-descriptions-item :label="t('views.index.serialNum')">{{
nfInfo.serialNum
}}</a-descriptions-item>
<a-descriptions-item :label="t('views.index.expiryDate')">{{
nfInfo.outTimeDate
}}</a-descriptions-item>
</template>
</a-descriptions>
</a-card>
</a-col>
</a-row>
</PageContainer>
<component :is="currentComponent" />
</template>
<style lang="less" scoped></style>

View File

@@ -0,0 +1,446 @@
<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 { reactive, toRaw, ref, onMounted, onBeforeUnmount, markRaw } from 'vue';
import { listMain } from '@/api/index';
import useI18n from '@/hooks/useI18n';
import { TooltipComponent } from 'echarts/components';
import { GaugeChart } from 'echarts/charts';
import { CanvasRenderer } from 'echarts/renderers';
import * as echarts from 'echarts/core';
import { TitleComponent, LegendComponent } from 'echarts/components';
import { PieChart } from 'echarts/charts';
import { LabelLayout } from 'echarts/features';
import { useRoute } from 'vue-router';
import useAppStore from '@/store/modules/app';
import useDictStore from '@/store/modules/dict';
const { getDict } = useDictStore();
const appStore = useAppStore();
const route = useRoute();
const { t } = useI18n();
echarts.use([
TooltipComponent,
GaugeChart,
TitleComponent,
LegendComponent,
PieChart,
CanvasRenderer,
LabelLayout,
]);
/**图DOM节点实例对象 */
const statusBar = ref<HTMLElement | undefined>(undefined);
/**图实例对象 */
const statusBarChart = ref<any>(null);
/**网元状态字典数据 */
let indexColor = ref<DictType[]>([
{ label: 'Normal', value: 'normal', tagType: '', tagClass: '#91cc75' },
{
label: 'Abnormal',
value: 'abnormal',
tagType: '',
tagClass: '#ee6666',
},
]);
/**表格字段列 */
//customRender(){} ----单元格处理
let tableColumns: ColumnsType = [
{
title: t('views.index.object'),
dataIndex: 'name',
align: 'center',
key: 'status',
},
{
title: t('views.index.realNeStatus'),
dataIndex: 'status',
align: 'center',
customRender(opt) {
if (opt.value == 'Normal') return t('views.index.normal');
return t('views.index.abnormal');
},
},
{
title: t('views.index.reloadTime'),
dataIndex: 'refresh',
align: 'center',
},
{
title: t('views.index.version'),
dataIndex: 'version',
align: 'center',
},
{
title: t('views.index.serialNum'),
dataIndex: 'serialNum',
align: 'center',
},
{
title: t('views.index.expiryDate'),
dataIndex: 'expiryDate',
align: 'center',
},
{
title: t('views.index.ipAddress'),
dataIndex: 'ipAddress',
key: 'groupName',
align: 'center',
},
];
/**表格状态类型 */
type TabeStateType = {
/**加载等待 */
loading: boolean;
/**紧凑型 */
size: string;
/**搜索栏 */
seached: boolean;
/**记录数据 */
data: object[];
/**勾选记录 */
selectedRowKeys: (string | number)[];
};
/**表格状态 */
let tableState: TabeStateType = reactive({
loading: false,
size: 'middle',
seached: false,
data: [],
selectedRowKeys: [],
});
/**表格状态 */
let nfInfo: any = reactive({
obj: 'OMC',
version: appStore.version,
status: t('views.index.normal'),
outTimeDate: '',
serialNum: appStore.serialNum,
});
/**表格状态类型 */
type nfStateType = {
/**主机名 */
hostName: string;
/**操作系统信息 */
osInfo: string;
/**数据库信息 */
dbInfo: string;
/**IP地址 */
ipAddress: string;
/**端口 */
port: number;
/**版本 */
version: string;
/**CPU利用率 */
cpuUse: string;
/**内存使用 */
memoryUse: string;
/**用户容量 */
capability: number;
/**序列号 */
serialNum: string;
/**许可证到期日期 */
/* selectedRowKeys: (string | number)[];*/
expiryDate: string;
};
/**网元详细信息 */
let pronInfo: nfStateType = reactive({
hostName: '5gc',
osInfo: 'Linux 5gc 4.15.0-112-generic 2020 x86_64 GNU/Linux',
dbInfo: 'db v9.9.9',
ipAddress: '-',
port: 33030,
version: '-',
cpuUse: '-',
memoryUse: '-',
capability: 0,
serialNum: '-',
expiryDate: '-',
});
/**查询网元状态列表 */
function fnGetList(one: boolean) {
if (tableState.loading) return;
one && (tableState.loading = true);
listMain().then(res => {
tableState.data = res;
tableState.loading = false;
var rightNum = 0;
var errorNum = 0;
// if (res.length) nfInfo.serialNum = res[0].serialNum;
for (let i = 0; i < res.length; i++) {
if (res[i].status == '正常' || res[i].status == 'Normal') {
rightNum++;
} else {
errorNum++;
}
}
const optionData: any = {
title: {
text: '',
subtext: '',
left: 'center',
},
tooltip: {
trigger: 'item',
},
legend: {
orient: 'vertical',
left: 'left',
},
color: indexColor.value.map(item => item.tagClass),
series: [
{
name: t('views.index.realNeStatus'),
type: 'pie',
radius: '70%',
center: ['50%', '50%'],
data: [
{ value: rightNum, name: t('views.index.normal') },
{ value: errorNum, name: t('views.index.abnormal') },
],
emphasis: {
itemStyle: {
shadowBlur: 10,
shadowOffsetX: 0,
shadowColor: 'rgba(0, 0, 0, 0.5)',
},
},
label: {},
},
],
};
fnDesign(statusBar.value, optionData);
});
}
function fnDesign(container: HTMLElement | undefined, option: any) {
if (!container) return;
if (!statusBarChart.value) {
statusBarChart.value = markRaw(echarts.init(container, 'light'));
}
option && statusBarChart.value.setOption(option);
// 创建 ResizeObserver 实例
var observer = new ResizeObserver(entries => {
if (statusBarChart.value) {
statusBarChart.value.resize();
}
});
// 监听元素大小变化
observer.observe(container);
}
/**抽屉 网元详细信息 */
const visible = ref(false);
const closeDrawer = () => {
visible.value = false;
};
/**抽屉 网元详细信息 */
/**监听表格行事件*/
function rowClick(record: any, index: any) {
return {
onClick: (event: any) => {
if (
toRaw(record).status == '异常' ||
toRaw(record).status == 'Abnormal'
) {
message.error(t('views.index.neStatus'), 2);
return false;
} else {
let pronData = toRaw(record);
const totalMemInKB = pronData.memUsage?.totalMem;
const nfUsedMemInKB = pronData.memUsage?.nfUsedMem;
const sysMemUsageInKB = pronData.memUsage?.sysMemUsage;
// 将KB转换为MB
const totalMemInMB = Math.round((totalMemInKB / 1024) * 100) / 100;
const nfUsedMemInMB = Math.round((nfUsedMemInKB / 1024) * 100) / 100;
const sysMemUsageInMB =
Math.round((sysMemUsageInKB / 1024) * 100) / 100;
//渲染详细信息
pronInfo = {
hostName: pronData.hostName,
osInfo: pronData.osInfo,
dbInfo: pronData.dbInfo,
ipAddress: pronData.ipAddress,
port: pronData.port,
version: pronData.version,
cpuUse:
pronData.name +
':' +
pronData.cpuUsage?.nfCpuUsage / 100 +
'%; ' +
'SYS:' +
pronData.cpuUsage?.sysCpuUsage / 100 +
'%',
memoryUse:
'Total:' +
totalMemInMB +
'MB; ' +
pronData.name +
':' +
nfUsedMemInMB +
'MB; SYS:' +
sysMemUsageInMB +
'MB',
capability: pronData.capability,
serialNum: pronData.serialNum,
expiryDate: pronData.expiryDate,
};
}
visible.value = true;
},
};
}
let timer: any;
/**
* 国际化翻译转换
*/
function fnLocale() {
let title = route.meta.title as string;
if (title.indexOf('router.') !== -1) {
title = t(title);
}
appStore.setTitle(title);
}
onMounted(() => {
getDict('index_status')
.then(res => {
if (res.length > 0) {
indexColor.value = res;
}
})
.finally(() => {
fnLocale();
fnGetList(true);
timer = setInterval(() => fnGetList(false), 10000); // 每隔10秒执行一次
});
});
// 在组件卸载之前清除定时器
onBeforeUnmount(() => {
clearInterval(timer);
});
</script>
<template>
<PageContainer :breadcrumb="{}">
<div>
<a-drawer :visible="visible" @close="closeDrawer" :width="700">
<a-descriptions bordered :column="1" :label-style="{ width: '160px' }">
<a-descriptions-item :label="t('views.index.hostName')">{{
pronInfo.hostName
}}</a-descriptions-item>
<a-descriptions-item :label="t('views.index.osInfo')">{{
pronInfo.osInfo
}}</a-descriptions-item>
<a-descriptions-item :label="t('views.index.dbInfo')">{{
pronInfo.dbInfo
}}</a-descriptions-item>
<a-descriptions-item :label="t('views.index.ipAddress')">{{
pronInfo.ipAddress
}}</a-descriptions-item>
<a-descriptions-item :label="t('views.index.port')">{{
pronInfo.port
}}</a-descriptions-item>
<a-descriptions-item :label="t('views.index.version')">{{
pronInfo.version
}}</a-descriptions-item>
<a-descriptions-item :label="t('views.index.cpuUse')">{{
pronInfo.cpuUse
}}</a-descriptions-item>
<a-descriptions-item :label="t('views.index.memoryUse')">{{
pronInfo.memoryUse
}}</a-descriptions-item>
<a-descriptions-item :label="t('views.index.capability')">{{
pronInfo.capability
}}</a-descriptions-item>
<a-descriptions-item :label="t('views.index.serialNum')">{{
pronInfo.serialNum
}}</a-descriptions-item>
<a-descriptions-item :label="t('views.index.expiryDate')">{{
pronInfo.expiryDate
}}</a-descriptions-item>
</a-descriptions>
</a-drawer>
</div>
<a-row :gutter="16">
<a-col :lg="14" :md="16" :xs="24">
<!-- 表格列表 -->
<a-table
class="table"
row-key="id"
:columns="tableColumns"
:loading="tableState.loading"
:data-source="tableState.data"
:pagination="false"
:scroll="{ x: true }"
:customRow="rowClick"
>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'status'">
<div v-if="record.status == '正常' || record.status == 'Normal'">
<a-tag color="blue">{{ record.name }}</a-tag>
</div>
<div v-else>
<a-tag color="pink">{{ record.name }}</a-tag>
</div>
</template>
</template>
</a-table>
</a-col>
<a-col :lg="10" :md="8" :xs="24">
<a-card :title="t('views.index.runStatus')" style="margin-bottom: 16px">
<div style="width: 100%; min-height: 200px" ref="statusBar"></div>
</a-card>
<a-card :title="t('views.index.mark')" style="margin-top: 16px">
<a-descriptions
bordered
:column="1"
:label-style="{ width: '160px' }"
>
<a-descriptions-item :label="t('views.index.object')">{{
nfInfo.obj
}}</a-descriptions-item>
<template v-if="nfInfo.obj === 'OMC'">
<a-descriptions-item :label="t('views.index.versionNum')">{{
nfInfo.version
}}</a-descriptions-item>
<a-descriptions-item :label="t('views.index.systemStatus')">{{
nfInfo.status
}}</a-descriptions-item>
</template>
<template v-else>
<a-descriptions-item :label="t('views.index.serialNum')">{{
nfInfo.serialNum
}}</a-descriptions-item>
<a-descriptions-item :label="t('views.index.expiryDate')">{{
nfInfo.outTimeDate
}}</a-descriptions-item>
</template>
</a-descriptions>
</a-card>
</a-col>
</a-row>
</PageContainer>
</template>
<style lang="less" scoped></style>

View File

@@ -0,0 +1,106 @@
<script lang="ts" setup>
import { Modal, message } from 'ant-design-vue/lib';
import { onMounted, reactive, toRaw } from 'vue';
import useAppStore from '@/store/modules/app';
import useI18n from '@/hooks/useI18n';
import { CACHE_LOCAL_I18N } from '@/constants/cache-keys-constants';
import { localSet } from '@/utils/cache-local-utils';
import { listMenu } from '@/api/system/menu';
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
import { getConfig, changeValue } from '@/api/system/config';
const appStore = useAppStore();
const { t, optionsLocale } = useI18n();
type StateType = {
edite: boolean;
loading: boolean;
open: boolean;
default: any;
options: any;
};
let state: StateType = reactive({
edite: false,
loading: false,
open: false,
default: '',
options: [],
});
/**提交保存 */
function fnSave() {
Modal.confirm({
title: t('common.tipTitle'),
content: t('views.system.setting.homeTip'),
onOk() {
// 发送请求
const hide = message.loading(t('common.loading'), 0);
state.loading = true;
changeValue({ key: 'sys.homePage', value: state.default })
.then(res => {
if (res.code === RESULT_CODE_SUCCESS) {
message.success(t('views.system.setting.saveSuccess'), 3);
} else {
message.error(res.msg, 3);
}
})
.finally(() => {
state.loading = false;
hide();
});
},
});
}
onMounted(() => {
listMenu(toRaw({ status: 1 })).then(res => {
if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.data)) {
// 过滤旧前端菜单以及不是菜单类型以及路径为空
res.data = res.data
.filter(i => i.perms !== 'page' && i.menuType === 'M' && i.component)
.map((item: any) => {
state.options.push({
label: item.menuName,
value: item.component,
});
});
}
});
//获取当前系统设置的首页路径 111为configID
getConfig(111).then(res => {
if (res.code === RESULT_CODE_SUCCESS && res.data) {
state.default = res.data.configValue;
}
});
});
</script>
<template>
<a-row :gutter="16">
<a-col :lg="12" :md="12" :xs="24" style="margin-bottom: 30px">
<a-form-item :label="t('views.system.setting.home')">
<a-select
ref="select"
v-model:value="state.default"
style="width: 240px"
:options="state.options"
></a-select>
</a-form-item>
<a-button type="primary" @click="fnSave">
{{ t('views.system.setting.saveSubmit') }}
</a-button>
</a-col>
<a-col :lg="12" :md="12" :xs="24">
<a-typography>
<a-typography-paragraph>
{{ t('views.system.setting.homeInstruction') }}
</a-typography-paragraph>
</a-typography>
</a-col>
</a-row>
</template>
<style lang="less" scoped></style>

View File

@@ -8,6 +8,7 @@ import ChangeHelpDoc from './components/change-help-doc.vue';
import ChangeOfficialUrl from './components/change-official-url.vue';
import ChangeI18n from './components/change-i18n.vue';
import SystemReset from './components/system-reset.vue';
import ChangeHome from './components/change-home-index.vue';
import useI18n from '@/hooks/useI18n';
const { t } = useI18n();
</script>
@@ -49,6 +50,10 @@ const { t } = useI18n();
</a-divider>
<ChangeI18n></ChangeI18n>
</div>
<a-divider orientation="left">
系统首页设置
</a-divider>
<ChangeHome></ChangeHome>
<a-divider orientation="left">
{{ t('views.system.setting.reset') }}
</a-divider>