2
0

fix:仪表盘界面(未接通)

This commit is contained in:
zhongzm
2025-01-10 14:28:59 +08:00
parent 4708df2a6f
commit 28200f4931
7 changed files with 506 additions and 122 deletions

View File

@@ -1,109 +1,231 @@
<script setup lang="ts">
import { computed } from 'vue';
import { createReusableTemplate } from '@vueuse/core';
import { $t } from '@/locales';
import { computed, ref } from 'vue';
import {
EnvironmentOutlined,
EditOutlined,
CopyOutlined,
DeleteOutlined,
HomeOutlined,
SearchOutlined,
PlusOutlined
} from '@ant-design/icons-vue';
defineOptions({
name: 'CardData'
});
interface CardData {
key: string;
title: string;
value: number;
unit: string;
color: {
start: string;
end: string;
};
icon: string;
interface SiteData {
id: number;
name: string;
region: string;
alerts: number;
gateway: string;
switches: string;
olts: string;
eaps: string;
}
const cardData = computed<CardData[]>(() => [
// 搜索和分页状态
const searchValue = ref('');
const currentPage = ref(1);
const pageSize = ref(10);
// 表格列定义
const columns = [
{
key: 'visitCount',
title: $t('page.home.visitCount'),
value: 9725,
unit: '',
color: {
start: '#ec4786',
end: '#b955a4'
},
icon: 'ant-design:bar-chart-outlined'
title: 'NAME',
key: 'name',
dataIndex: 'name'
},
{
key: 'turnover',
title: $t('page.home.turnover'),
value: 1026,
unit: '$',
color: {
start: '#865ec0',
end: '#5144b4'
},
icon: 'ant-design:money-collect-outlined'
title: 'COUNTRY/REGION',
key: 'region',
dataIndex: 'region'
},
{
key: 'downloadCount',
title: $t('page.home.downloadCount'),
value: 970925,
unit: '',
color: {
start: '#56cdf3',
end: '#719de3'
},
icon: 'carbon:document-download'
title: 'ALERTS',
key: 'alerts',
dataIndex: 'alerts',
width: 100
},
{
key: 'dealCount',
title: $t('page.home.dealCount'),
value: 9527,
unit: '',
color: {
start: '#fcbc25',
end: '#f68057'
},
icon: 'ant-design:trademark-circle-outlined'
title: 'GATEWAY',
key: 'gateway',
dataIndex: 'gateway',
width: 100
},
{
title: 'SWITCHES',
key: 'switches',
dataIndex: 'switches',
width: 100
},
{
title: 'OLTS',
key: 'olts',
dataIndex: 'olts',
width: 100
},
{
title: 'EAPS',
key: 'eaps',
dataIndex: 'eaps',
width: 100
},
{
title: 'ACTION',
key: 'action',
width: 150,
fixed: 'right'
}
];
const siteData = computed<SiteData[]>(() => [
{
id: 1,
name: 'wfc-dev-omada1-site1',
region: 'China mainland',
alerts: 0,
gateway: '-',
switches: '0 / 0',
olts: '0 / 0',
eaps: '1 / 1'
},
{
id: 2,
name: 'wfc-dev-omada1-site2',
region: 'China mainland',
alerts: 0,
gateway: '-',
switches: '0 / 0',
olts: '0 / 0',
eaps: '0 / 1'
}
]);
interface GradientBgProps {
gradientColor: string;
}
// 按钮操作处理函数
const handleEdit = (record: SiteData) => {
console.log('Edit:', record);
};
const [DefineGradientBg, GradientBg] = createReusableTemplate<GradientBgProps>();
const handleCopy = (record: SiteData) => {
console.log('Copy:', record);
};
function getGradientColor(color: CardData['color']) {
return `linear-gradient(to bottom right, ${color.start}, ${color.end})`;
}
const handleDelete = (record: SiteData) => {
console.log('Delete:', record);
};
const handleHome = (record: SiteData) => {
console.log('Home:', record);
};
// 分页处理函数
// const handlePageChange = (page: number) => {
// currentPage.value = page;
// };
// const handlePageSizeChange = (size: number) => {
// pageSize.value = size;
// currentPage.value = 1;
// };
// const handleGoToPage = () => {
// // 处理跳转页面逻辑
// console.log('Go to page:', currentPage.value);
// };
</script>
<template>
<ACard :bordered="false" size="small" class="card-wrapper">
<!-- define component start: GradientBg -->
<DefineGradientBg v-slot="{ $slots, gradientColor }">
<div class="rd-8px px-16px pb-4px pt-8px text-white" :style="{ backgroundImage: gradientColor }">
<component :is="$slots.default" />
<div class="flex justify-between items-center mb-16px">
<div class="flex items-center gap-8px">
<span class="text-16px font-medium">Site List</span>
<!-- <span class="text-12px text-gray-500">1-2 of 2 records</span>-->
</div>
</DefineGradientBg>
<!-- define component end: GradientBg -->
<div class="flex items-center gap-16px">
<AInput
v-model:value="searchValue"
placeholder="Search Site Name"
class="w-240px"
allow-clear
>
<template #prefix>
<search-outlined />
</template>
</AInput>
<AButton type="primary">
<template #icon>
<plus-outlined />
</template>
Import Site
</AButton>
<AButton type="primary">
<template #icon>
<plus-outlined />
</template>
Add New Site
</AButton>
</div>
</div>
<ARow :gutter="[16, 16]">
<ACol v-for="item in cardData" :key="item.key" :span="24" :md="12" :lg="6">
<GradientBg :gradient-color="getGradientColor(item.color)" class="flex-1">
<h3 class="text-16px">{{ item.title }}</h3>
<div class="flex justify-between pt-12px">
<SvgIcon :icon="item.icon" class="text-32px" />
<CountTo
:prefix="item.unit"
:start-value="1"
:end-value="item.value"
class="text-30px text-white dark:text-dark"
/>
<ATable
:columns="columns"
:data-source="siteData"
:pagination="false"
:scroll="{ x: 1200 }"
row-key="id"
>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'name'">
<div class="flex items-center gap-8px">
<environment-outlined class="text-16px" />
<span>{{ record.name }}</span>
</div>
</GradientBg>
</ACol>
</ARow>
</template>
<template v-else-if="column.key === 'alerts'">
<ATag v-if="record.alerts > 0" color="error">{{ record.alerts }}</ATag>
<span v-else>{{ record.alerts }}</span>
</template>
<template v-else-if="column.key === 'action'">
<div class="flex items-center gap-8px">
<edit-outlined class="cursor-pointer text-primary" @click="handleEdit(record)" />
<copy-outlined class="cursor-pointer text-primary" @click="handleCopy(record)" />
<delete-outlined class="cursor-pointer text-red-500" @click="handleDelete(record)" />
<home-outlined class="cursor-pointer text-primary" @click="handleHome(record)" />
</div>
</template>
</template>
</ATable>
<div class="flex justify-between items-center mt-16px">
<div class="text-12px text-gray-500">
Showing 1-2 of 2 records
</div>
<div class="flex items-center gap-8px">
<ASelect v-model:value="pageSize" style="width: 100px">
<ASelectOption :value="10">10 / page</ASelectOption>
<ASelectOption :value="20">20 / page</ASelectOption>
<ASelectOption :value="50">50 / page</ASelectOption>
</ASelect>
<span class="text-12px text-gray-500">Go to page:</span>
<AInput v-model:value="currentPage" style="width: 50px" />
<AButton>Go</AButton>
</div>
</div>
</ACard>
</template>
<style scoped></style>
<style scoped>
.card-wrapper {
margin-bottom: 16px;
}
.cursor-pointer {
cursor: pointer;
}
.w-240px {
width: 240px;
}
</style>