fix:多选改checkbox

This commit is contained in:
zhongzm
2024-10-18 10:32:55 +08:00
parent d07230b582
commit 671c80972e
2 changed files with 111 additions and 74 deletions

View File

@@ -251,14 +251,14 @@ function fnGetListTitle() {
// 获取表头文字 // 获取表头文字
getKPITitle(state.neType[0]) getKPITitle(state.neType[0])
.then(res => { .then(res => {//处理getKPITitle返回的结果
if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.data)) { if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.data)) {//检查值
tableColumns.value = []; tableColumns.value = [];//设为空数组
const columns: ColumnsType = []; const columns: ColumnsType = [];//初始化,构建新表头
for (const item of res.data) { for (const item of res.data) {//遍历res.data
const kpiDisplay = item[`${language}Title`]; const kpiDisplay = item[`${language}Title`];//提取标题kpiDisplay和ID标识kpiValue
const kpiValue = item[`kpiId`]; const kpiValue = item[`kpiId`];
columns.push({ columns.push({//
title: kpiDisplay, title: kpiDisplay,
dataIndex: kpiValue, dataIndex: kpiValue,
align: 'left', align: 'left',
@@ -297,7 +297,7 @@ function fnGetListTitle() {
return false; return false;
} }
}) })
.then(result => { .then(result => {//result是前一个.then返回的值(true or false)
result && fnGetList(); result && fnGetList();
}); });
} }
@@ -334,27 +334,27 @@ function fnChangShowType() {
/**绘制图表 */ /**绘制图表 */
function fnRanderChart() { function fnRanderChart() {
const container: HTMLElement | undefined = kpiChartDom.value; const container: HTMLElement | undefined = kpiChartDom.value;//获取图表容器DOM元素
if (!container) return; if (!container) return;//若没有,则退出函数
kpiChart.value = markRaw(echarts.init(container, 'light')); kpiChart.value = markRaw(echarts.init(container, 'light'));
//初始化Echarts图表实例应用light主题并赋值给kpiChart.valuemarkRaw是vue函数用于标记对象为不可响应
const option: EChartsOption = { const option: EChartsOption = {//定义图表的配置对象tooltip的出发方式为axis
tooltip: { tooltip: {
trigger: 'axis', trigger: 'axis',
position: function (pt: any) { position: function (pt: any) {
return [pt[0], '10%']; return [pt[0], '10%'];
}, },
}, },
xAxis: { xAxis: {//x类别轴
type: 'category', type: 'category',
boundaryGap: false, boundaryGap: false,
data: [], // 数据x轴 data: [], // 数据x轴
}, },
yAxis: { yAxis: {//y类别轴
type: 'value', type: 'value',
boundaryGap: [0, '100%'], boundaryGap: [0, '100%'],
}, },
legend: { legend: {//图例垂直滚动
type: 'scroll', type: 'scroll',
orient: 'vertical', orient: 'vertical',
top: 40, top: 40,
@@ -367,13 +367,13 @@ function fnRanderChart() {
icon: 'circle', icon: 'circle',
selected: {}, selected: {},
}, },
grid: { grid: {//网格区域边距
left: '10%', left: '10%',
right: '30%', right: '30%',
bottom: '20%', bottom: '20%',
}, },
dataZoom: [ dataZoom: [
{ {//启用图表的数据缩放范围90%-100%
type: 'inside', type: 'inside',
start: 90, start: 90,
end: 100, end: 100,
@@ -385,9 +385,9 @@ function fnRanderChart() {
], ],
series: [], // 数据y轴 series: [], // 数据y轴
}; };
kpiChart.value.setOption(option); kpiChart.value.setOption(option);//设置图表配置项应用到kpiChart实例上
// 创建 ResizeObserver 实例 // 创建 ResizeObserver 实例 监听图表容器大小变化,并在变化时调整图表大小
var observer = new ResizeObserver(entries => { var observer = new ResizeObserver(entries => {
if (kpiChart.value) { if (kpiChart.value) {
kpiChart.value.resize(); kpiChart.value.resize();
@@ -452,6 +452,7 @@ function fnRanderChartData() {
// 用降序就反转 // 用降序就反转
let orgData = tableState.data; let orgData = tableState.data;
console.log(orgData);
if (queryParams.sortOrder === 'desc') { if (queryParams.sortOrder === 'desc') {
orgData = orgData.toReversed(); orgData = orgData.toReversed();
} }

View File

@@ -16,11 +16,15 @@ import { ColumnsType } from 'ant-design-vue/es/table';
import { generateColorRGBA } from '@/utils/generate-utils'; import { generateColorRGBA } from '@/utils/generate-utils';
import { LineSeriesOption } from 'echarts/charts'; import { LineSeriesOption } from 'echarts/charts';
import { OptionsType, WS } from '@/plugins/ws-websocket'; import { OptionsType, WS } from '@/plugins/ws-websocket';
import { Select } from 'ant-design-vue';
import { useDebounceFn } from '@vueuse/core'; import { useDebounceFn } from '@vueuse/core';
const { t, currentLocale } = useI18n(); const { t, currentLocale } = useI18n();
const neInfoStore = useNeInfoStore(); const neInfoStore = useNeInfoStore();
//WebSocket连接 //WebSocket连接
const ws = ref<WS | null>(null); const ws = ref<WS | null>(null);
//添加实时数据开关状态 //添加实时数据开关状态
const realTimeEnabled = ref(false); const realTimeEnabled = ref(false);
//实时数据开关 //实时数据开关
@@ -28,20 +32,27 @@ const handleRealTimeSwitch = (checked: any) => {
fnRealTimeSwitch(!!checked); fnRealTimeSwitch(!!checked);
}; };
// 定义所有可能的网元类型 // 定义所有可能的网元类型
const ALL_NE_TYPES = ['ims', 'amf', 'udm', 'smf', 'pcf','upf','mme','mocngw','smsc','cbc','ausf'] as const; const ALL_NE_TYPES = ['ims', 'amf', 'udm', 'smf', 'pcf','upf','mme','mocngw','smsc','cbc','ausf'] as const;
type AllChartType = typeof ALL_NE_TYPES[number]; type AllChartType = typeof ALL_NE_TYPES[number];
// 在 ALL_NE_TYPES 定义之后添加
const neTypeOptions = ALL_NE_TYPES.map(type => ({
label: type.toUpperCase(),
value: type
}));
// 使用 ref 来使 networkElementTypes 变为响应式,并使用 ALL_NE_TYPES 初始化 // 使用 ref 来使 networkElementTypes 变为响应式,并使用 ALL_NE_TYPES 初始化
const networkElementTypes = ref<AllChartType[]>([...ALL_NE_TYPES]); const networkElementTypes = ref<AllChartType[]>([...ALL_NE_TYPES]);
// 添加选择的网元类型,也使用 ALL_NE_TYPES 初始化 // 添加选择的网元类型
const selectedNeTypes = ref<AllChartType[]>([...ALL_NE_TYPES]); const selectedNeTypes = ref<AllChartType[]>([]);
// 临时状态 存储最新的选择 // 添加一个临时状态存储最新的选择
const latestSelectedTypes = ref<AllChartType[]>([]); const latestSelectedTypes = ref<AllChartType[]>([]);
// watch 函数 // 修改 watch 函数
watch(selectedNeTypes, (newTypes) => { watch(selectedNeTypes, (newTypes) => {
console.log('Selected types changed:', newTypes); console.log('Selected types changed:', newTypes);
// 立即更新 UI // 立即更新 UI
@@ -52,11 +63,11 @@ watch(selectedNeTypes, (newTypes) => {
debouncedUpdateCharts(); debouncedUpdateCharts();
}, { deep: true }); }, { deep: true });
// 防抖函数 // 修改防抖函数
const debouncedUpdateCharts = useDebounceFn(() => { const debouncedUpdateCharts = useDebounceFn(() => {
// 比较当前选择和最新选择 // 比较当前选择和最新选择
if (JSON.stringify(latestSelectedTypes.value) !== JSON.stringify(selectedNeTypes.value)) { if (JSON.stringify(latestSelectedTypes.value) !== JSON.stringify(selectedNeTypes.value)) {
// 如果不致,以最新选择为准 // 如果不致,以最新选择为准
selectedNeTypes.value = latestSelectedTypes.value; selectedNeTypes.value = latestSelectedTypes.value;
} }
@@ -92,7 +103,7 @@ const debouncedUpdateCharts = useDebounceFn(() => {
}); });
}, 300); }, 300);
// initCharts 函数 // 修改 initCharts 函数
const initCharts = async () => { const initCharts = async () => {
console.log('Initializing charts for:', networkElementTypes.value); console.log('Initializing charts for:', networkElementTypes.value);
@@ -132,7 +143,7 @@ const initCharts = async () => {
localStorage.setItem('chartOrder', JSON.stringify(chartOrder.value)); localStorage.setItem('chartOrder', JSON.stringify(chartOrder.value));
}; };
// 类型定义 // 添加类型定义
interface LayoutItem { interface LayoutItem {
x: number; x: number;
y: number; y: number;
@@ -148,7 +159,7 @@ const chartOrder = ref<Layout>(
JSON.parse(localStorage.getItem('chartOrder') || 'null') || JSON.parse(localStorage.getItem('chartOrder') || 'null') ||
networkElementTypes.value.map((type, index) => ({ networkElementTypes.value.map((type, index) => ({
x: index % 2 * 6, // 每行两个图表宽度为6 x: index % 2 * 6, // 每行两个图表宽度为6
y: Math.floor(index / 2) * 4, // 每个图表据 4 个单位高度 y: Math.floor(index / 2) * 4, // 每个图表据 4 个单位高度
w: 6, // 宽度为6单位 w: 6, // 宽度为6单位
h: 4, // 高度为4个单位 h: 4, // 高度为4个单位
i: type, // 使用网元类型作为唯一标识 i: type, // 使用网元类型作为唯一标识
@@ -238,7 +249,7 @@ const rangePicker = reactive<RangePicker>({
// dayjs('2024-09-20 23:59:59').valueOf().toString() // dayjs('2024-09-20 23:59:59').valueOf().toString()
// ] // ]
[ [
dayjs().startOf('day').valueOf().toString(), // 天 0 点 0 分 0 秒 dayjs().startOf('day').valueOf().toString(), // 天 0 点 0 分 0 秒
dayjs().valueOf().toString() // 当前时间 dayjs().valueOf().toString() // 当前时间
] ]
])) as Record<AllChartType, [string, string]>, ])) as Record<AllChartType, [string, string]>,
@@ -334,7 +345,7 @@ const initChart = (type: AllChartType) => {
} }
}); });
// 观察图表容器 // 开始观察图表容器
state.observer.value.observe(container); state.observer.value.observe(container);
}); });
}; };
@@ -408,13 +419,13 @@ function fnRealTimeSwitch(bool: boolean) {
} }
} }
// 接收数据后错误回 // 接收数据后错误回
function wsError() { function wsError() {
message.error(t('common.websocketError')); message.error(t('common.websocketError'));
} }
// wsMessage 数据回调 // 修改 wsMessage 数
function wsMessage(res: Record<string, any>) { function wsMessage(res: Record<string, any>) {
const { code, data } = res; const { code, data } = res;
if (code === RESULT_CODE_ERROR) { if (code === RESULT_CODE_ERROR) {
@@ -573,7 +584,7 @@ onMounted(async () => {
ws.value = new WS(); ws.value = new WS();
await neInfoStore.fnNelist(); await neInfoStore.fnNelist();
// 从本地存储中读取选中的网类型 // 从本地存储中读取选中的网类型
const savedSelectedNeTypes = localStorage.getItem('selectedNeTypes'); const savedSelectedNeTypes = localStorage.getItem('selectedNeTypes');
if (savedSelectedNeTypes) { if (savedSelectedNeTypes) {
const parsedSelectedNeTypes = JSON.parse(savedSelectedNeTypes) as AllChartType[]; const parsedSelectedNeTypes = JSON.parse(savedSelectedNeTypes) as AllChartType[];
@@ -625,6 +636,8 @@ onUnmounted(() => {
state.observer.value.disconnect(); state.observer.value.disconnect();
} }
}); });
// 不需要显式取消防抖函数
}); });
</script> </script>
@@ -642,16 +655,7 @@ onUnmounted(() => {
<span class="switch-label">{{ realTimeEnabled ? t('views.dashboard.cdr.realTimeDataStart') : t('views.dashboard.cdr.realTimeDataStop') }}</span> <span class="switch-label">{{ realTimeEnabled ? t('views.dashboard.cdr.realTimeDataStart') : t('views.dashboard.cdr.realTimeDataStop') }}</span>
</a-form-item> </a-form-item>
<a-form-item :label="t('views.ne.common.neType')" class="ne-type-select"> <a-form-item :label="t('views.ne.common.neType')" class="ne-type-select">
<a-select <a-checkbox-group v-model:value="selectedNeTypes" :options="neTypeOptions" />
v-model:value="selectedNeTypes"
mode="multiple"
style="min-width: 200px; width: 100%"
:placeholder="t('common.selectPlease')"
>
<a-select-option v-for="type in ALL_NE_TYPES" :key="type" :value="type">
{{ type.toUpperCase() }}
</a-select-option>
</a-select>
</a-form-item> </a-form-item>
</a-form> </a-form>
</a-card> </a-card>
@@ -682,31 +686,31 @@ onUnmounted(() => {
:min-h="3" :min-h="3"
:is-draggable="true" :is-draggable="true"
:is-resizable="true" :is-resizable="true"
:resizable-handles="['ne']" :resizable-handles="['se']"
drag-allow-from=".drag-handle" drag-allow-from=".ant-card-head"
drag-ignore-from=".no-drag" drag-ignore-from=".no-drag"
class="grid-item" class="grid-item"
> >
<div class="drag-handle"> <div class="date-picker-wrapper">
<DragOutlined /> <a-range-picker
v-model:value="rangePicker[item.i]"
:allow-clear="false"
bordered
:show-time="{ format: 'HH:mm:ss' }"
format="YYYY-MM-DD HH:mm:ss"
value-format="x"
:placeholder="rangePicker.placeholder"
:ranges="rangePicker.ranges"
style="width: 100%"
@change="() => fetchData(item.i)"
></a-range-picker>
</div> </div>
<a-card :bordered="false" class="card-container"> <a-card :bordered="false" class="card-container">
<template #title> <template #title>
<span class="no-drag">{{ item.i.toUpperCase() }}</span> <div class="card-title">
</template> <DragOutlined />
<template #extra> <span>{{ item.i.toUpperCase() }}</span>
<a-range-picker </div>
v-model:value="rangePicker[item.i]"
:allow-clear="false"
bordered
:show-time="{ format: 'HH:mm:ss' }"
format="YYYY-MM-DD HH:mm:ss"
value-format="x"
:placeholder="rangePicker.placeholder"
:ranges="rangePicker.ranges"
style="width: 100%"
@change="() => fetchData(item.i)"
></a-range-picker>
</template> </template>
<div class='chart'> <div class='chart'>
<div :ref="el => { if (el && chartStates[item.i]) chartStates[item.i].chartDom.value = el as HTMLElement }"></div> <div :ref="el => { if (el && chartStates[item.i]) chartStates[item.i].chartDom.value = el as HTMLElement }"></div>
@@ -732,12 +736,37 @@ onUnmounted(() => {
position: relative; position: relative;
} }
.date-picker-wrapper {
position: absolute;
top: -40px;
left: 0;
right: 0;
z-index: 1;
}
.card-container { .card-container {
height: 100%; height: 100%;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
} }
.card-title {
display: flex;
align-items: center;
cursor: move;
.anticon {
margin-right: 8px;
font-size: 16px;
color: #1890ff;
}
span {
font-size: 16px;
font-weight: 500;
}
}
.chart { .chart {
flex: 1; flex: 1;
min-height: 0; min-height: 0;
@@ -756,28 +785,31 @@ onUnmounted(() => {
} }
.drag-handle { .drag-handle {
position: absolute;
top: 0;
right: 0;
width: 24px;
height: 24px;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center;
background-color: rgba(24, 144, 255, 0.1);
border-radius: 4px;
cursor: move; cursor: move;
z-index: 100;
transition: background-color 0.3s;
&:hover { .anticon {
background-color: rgba(24, 144, 255, 0.2); margin-right: 8px;
font-size: 16px;
color: #1890ff;
}
span {
font-size: 16px;
font-weight: 500;
} }
} }
.ne-type-select { .ne-type-select {
flex-grow: 1; flex-grow: 1;
max-width: 100%; max-width: 100%;
:deep(.ant-checkbox-group) {
display: flex;
flex-wrap: wrap;
gap: 8px;
}
} }
:deep { :deep {
@@ -806,5 +838,9 @@ onUnmounted(() => {
.ant-select { .ant-select {
min-width: 200px; min-width: 200px;
} }
.ant-card-head {
cursor: move;
}
} }
</style> </style>