|
|
|
<template>
|
|
|
|
<div class="device-home">
|
|
|
|
<header class="device-status-blok">
|
|
|
|
<div
|
|
|
|
v-for="(item, idx) in summaryList"
|
|
|
|
:key="idx"
|
|
|
|
class="val-blok"
|
|
|
|
:style="{ backgroundColor: item.color }"
|
|
|
|
>
|
|
|
|
<div class="val">
|
|
|
|
<span>{{ item.label }}</span>
|
|
|
|
<span class="num">{{ item.value }}</span>
|
|
|
|
</div>
|
|
|
|
<Icon :icon="item.icon" :size="48" />
|
|
|
|
<!-- <img :src="item.icon" alt="" /> -->
|
|
|
|
</div>
|
|
|
|
</header>
|
|
|
|
<main>
|
|
|
|
<EdfsWrap title="库存数据" class="line">
|
|
|
|
<template #title-right>
|
|
|
|
<el-button-group size="small">
|
|
|
|
<template v-for="{ key, name } in filterData" :key="key">
|
|
|
|
<EdfsButton
|
|
|
|
:inner-text="name"
|
|
|
|
@click="onTimeSearch(key)"
|
|
|
|
:type="currentFilter === key ? 'success' : ''"
|
|
|
|
/>
|
|
|
|
</template>
|
|
|
|
</el-button-group>
|
|
|
|
</template>
|
|
|
|
<LineChart :data="lineChartData" :filterType="currentFilter" />
|
|
|
|
</EdfsWrap>
|
|
|
|
<EdfsWrap title="设备数据" class="pie">
|
|
|
|
<PieChart :data="pieData" />
|
|
|
|
</EdfsWrap>
|
|
|
|
</main>
|
|
|
|
<footer>
|
|
|
|
<EdfsWrap title="快捷入口" class="shortcut">
|
|
|
|
<div class="shortcut-list">
|
|
|
|
<template v-for="(item, idx) in shortcutList" :key="idx">
|
|
|
|
<div class="item" @click="onShortcutClick(item)">
|
|
|
|
<el-button :type="item.type as any" circle size="large">
|
|
|
|
<Icon :icon="item.icon" :size="24" />
|
|
|
|
</el-button>
|
|
|
|
<span>{{ item.title }}</span>
|
|
|
|
</div>
|
|
|
|
</template>
|
|
|
|
</div>
|
|
|
|
</EdfsWrap>
|
|
|
|
</footer>
|
|
|
|
</div>
|
|
|
|
</template>
|
|
|
|
|
|
|
|
<script setup lang="ts">
|
|
|
|
import EdfsWrap from '@/components/dashboard/Edfs-wrap.vue'
|
|
|
|
import { data } from './components/utils'
|
|
|
|
import LineChart from './components/line-chart.vue'
|
|
|
|
import PieChart from './components/pie-chart.vue'
|
|
|
|
import { Icon } from '@/components/dashboard/Icon/index'
|
|
|
|
import { useRouter } from 'vue-router'
|
|
|
|
import {
|
|
|
|
getDeviceStorageAndMaintainChart,
|
|
|
|
getDeviceSummary,
|
|
|
|
getDeviceSummaryByStatus,
|
|
|
|
} from '@/api/module/eam/device'
|
|
|
|
import dayjs from 'dayjs'
|
|
|
|
import { isResError } from '@/hooks/useMessage'
|
|
|
|
|
|
|
|
const router = useRouter()
|
|
|
|
|
|
|
|
const shortcutList = [
|
|
|
|
{
|
|
|
|
title: '设备管理',
|
|
|
|
icon: 'solar:server-square-linear',
|
|
|
|
type: 'primary',
|
|
|
|
path: '/device/data',
|
|
|
|
},
|
|
|
|
{
|
|
|
|
title: '设备库存',
|
|
|
|
icon: 'solar:box-outline',
|
|
|
|
type: 'success',
|
|
|
|
path: '/storage',
|
|
|
|
},
|
|
|
|
{
|
|
|
|
title: '测试计划',
|
|
|
|
icon: 'codicon:code-oss',
|
|
|
|
type: 'warning',
|
|
|
|
path: '/testSheet/plan',
|
|
|
|
},
|
|
|
|
]
|
|
|
|
|
|
|
|
function onShortcutClick(item: any) {
|
|
|
|
router.push(item.path)
|
|
|
|
}
|
|
|
|
|
|
|
|
const filterData = [
|
|
|
|
{
|
|
|
|
key: 0,
|
|
|
|
name: '本月',
|
|
|
|
},
|
|
|
|
{
|
|
|
|
key: 1,
|
|
|
|
name: '本年',
|
|
|
|
},
|
|
|
|
]
|
|
|
|
|
|
|
|
const summaryList = ref([
|
|
|
|
// {
|
|
|
|
// label: '设备总数',
|
|
|
|
// value: 0,
|
|
|
|
// icon: 'solar:server-square-linear',
|
|
|
|
// color: '#1E90FF',
|
|
|
|
// },
|
|
|
|
{
|
|
|
|
label: '积累入库',
|
|
|
|
value: 0,
|
|
|
|
icon: 'solar:inbox-in-broken',
|
|
|
|
key: 'storage',
|
|
|
|
color: '#4CAF50',
|
|
|
|
},
|
|
|
|
{
|
|
|
|
label: '积累出库',
|
|
|
|
value: 0,
|
|
|
|
key: 'outStorage',
|
|
|
|
icon: 'solar:inbox-out-outline',
|
|
|
|
color: '#2196F3',
|
|
|
|
},
|
|
|
|
{
|
|
|
|
label: '测试中设备',
|
|
|
|
value: 0,
|
|
|
|
icon: 'solar:document-add-outline',
|
|
|
|
key: 'testing',
|
|
|
|
color: '#FF9800',
|
|
|
|
},
|
|
|
|
{
|
|
|
|
label: '维修中',
|
|
|
|
icon: 'solar:minimalistic-magnifer-bug-outline',
|
|
|
|
value: 0,
|
|
|
|
key: 'repair',
|
|
|
|
color: '#F44336',
|
|
|
|
},
|
|
|
|
])
|
|
|
|
|
|
|
|
const currentFilter = ref(1)
|
|
|
|
function onTimeSearch(filter: number) {
|
|
|
|
currentFilter.value = filter
|
|
|
|
loadLineChartData()
|
|
|
|
}
|
|
|
|
const lineChartData = ref<any>([])
|
|
|
|
async function loadLineChartData() {
|
|
|
|
// 获取当前月
|
|
|
|
const curMonth = dayjs().month() + 1
|
|
|
|
const curYear = dayjs().year()
|
|
|
|
const res = await getDeviceStorageAndMaintainChart({
|
|
|
|
type: currentFilter.value,
|
|
|
|
year: curYear,
|
|
|
|
month: curMonth,
|
|
|
|
})
|
|
|
|
if (isResError(res)) return
|
|
|
|
lineChartData.value = res.data
|
|
|
|
}
|
|
|
|
|
|
|
|
const pieData = ref<any>([])
|
|
|
|
async function loadPieChartData() {
|
|
|
|
const res = await getDeviceSummaryByStatus()
|
|
|
|
if (isResError(res)) return
|
|
|
|
pieData.value = res.data.map((item: any) => {
|
|
|
|
return {
|
|
|
|
name: item.statusName,
|
|
|
|
value: item.count,
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
async function loadDeviceSummary() {
|
|
|
|
const res = await getDeviceSummary()
|
|
|
|
if (isResError(res)) return
|
|
|
|
const data = res.data
|
|
|
|
summaryList.value.forEach(item => {
|
|
|
|
item.value = !!data[item.key] ? data[item.key] : 0
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
onMounted(() => {
|
|
|
|
loadDeviceSummary()
|
|
|
|
loadLineChartData()
|
|
|
|
loadPieChartData()
|
|
|
|
})
|
|
|
|
</script>
|
|
|
|
|
|
|
|
<style scoped lang="scss">
|
|
|
|
.device-home {
|
|
|
|
width: 100%;
|
|
|
|
height: 100%;
|
|
|
|
display: flex;
|
|
|
|
flex-direction: column;
|
|
|
|
row-gap: 16px;
|
|
|
|
.device-status-blok {
|
|
|
|
box-sizing: border-box;
|
|
|
|
height: 110px;
|
|
|
|
display: flex;
|
|
|
|
user-select: none;
|
|
|
|
justify-content: space-between;
|
|
|
|
column-gap: 40px;
|
|
|
|
.val-blok {
|
|
|
|
display: flex;
|
|
|
|
font-size: 16px;
|
|
|
|
box-shadow: 0px 0px 10px 0px rgba(0, 0, 0, 0.2);
|
|
|
|
border-radius: 4px;
|
|
|
|
overflow: hidden;
|
|
|
|
background-color: var(--warp-bg);
|
|
|
|
height: 100%;
|
|
|
|
width: 33%;
|
|
|
|
padding: 0 30px;
|
|
|
|
align-items: center;
|
|
|
|
img {
|
|
|
|
width: 130px;
|
|
|
|
height: 100%;
|
|
|
|
}
|
|
|
|
|
|
|
|
.val {
|
|
|
|
display: flex;
|
|
|
|
justify-content: center;
|
|
|
|
flex-direction: column;
|
|
|
|
width: 100%;
|
|
|
|
|
|
|
|
row-gap: 6px;
|
|
|
|
|
|
|
|
height: 100%;
|
|
|
|
.num {
|
|
|
|
font-size: 30px;
|
|
|
|
font-weight: 600;
|
|
|
|
padding-right: 24px;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
main {
|
|
|
|
flex: 1;
|
|
|
|
display: flex;
|
|
|
|
column-gap: 16px;
|
|
|
|
.line {
|
|
|
|
flex: 0.58;
|
|
|
|
}
|
|
|
|
.pie {
|
|
|
|
flex: 0.42;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
footer {
|
|
|
|
height: 140px;
|
|
|
|
.shortcut-list {
|
|
|
|
display: flex;
|
|
|
|
align-items: center;
|
|
|
|
column-gap: 18px;
|
|
|
|
}
|
|
|
|
.item {
|
|
|
|
display: flex;
|
|
|
|
flex-direction: column;
|
|
|
|
align-items: center;
|
|
|
|
cursor: pointer;
|
|
|
|
span {
|
|
|
|
margin-top: 8px;
|
|
|
|
color: var(--label-color);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
:deep(.wrap-body) {
|
|
|
|
padding-top: 0;
|
|
|
|
padding-left: 20px;
|
|
|
|
}
|
|
|
|
:deep(.el-button) {
|
|
|
|
width: 52px;
|
|
|
|
height: 52px;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
</style>
|