init
This commit is contained in:
294
src/views/screen/components/OverviewPanel.vue
Normal file
294
src/views/screen/components/OverviewPanel.vue
Normal file
@@ -0,0 +1,294 @@
|
||||
<template>
|
||||
<div class="left-top">
|
||||
<div class="panel-title">人员管理</div>
|
||||
<img style="margin: 8px 0" src="@/assets/images/title_border_line_1.png" />
|
||||
|
||||
<div class="top-card">
|
||||
<div class="top-card-left">
|
||||
<div>
|
||||
<img width="33px" src="@/assets/images/1_224520_821.png" />
|
||||
</div>
|
||||
<span>总计</span>
|
||||
<div class="number-wrapper">
|
||||
<span class="total-number" v-for="(digit, index) in totalCountDigits" :key="index">
|
||||
{{ digit }}
|
||||
</span>
|
||||
</div>
|
||||
<span>人</span>
|
||||
</div>
|
||||
|
||||
<div class="top-card-right">
|
||||
<div class="top-card-right-item">
|
||||
<img width="18px" src="@/assets/images/v2_rel0n8.png" />
|
||||
<span>正式员工</span>
|
||||
<div class="type-number-wrapper" style="margin-left: 2vw">
|
||||
<span class="type-number" v-for="(digit, index) in formalEmployeeDigits" :key="index">
|
||||
{{ digit }}
|
||||
</span>
|
||||
</div>
|
||||
<span>人</span>
|
||||
</div>
|
||||
|
||||
<div class="top-card-right-item">
|
||||
<img width="18px" src="@/assets/images/v2_rel0n23.png" />
|
||||
<span>外协人员</span>
|
||||
<div class="type-number-wrapper" style="margin-left: 1vw">
|
||||
<span class="type-number" v-for="(digit, index) in externalStaffDigits" :key="index">
|
||||
{{ digit }}
|
||||
</span>
|
||||
</div>
|
||||
<span>人</span>
|
||||
</div>
|
||||
|
||||
<div class="top-card-right-item">
|
||||
<img width="18px" src="@/assets/images/24508_654.png" />
|
||||
<span>访客</span>
|
||||
<div class="type-number-wrapper">
|
||||
<span class="type-number" v-for="(digit, index) in visitorDigits" :key="index">
|
||||
{{ digit }}
|
||||
</span>
|
||||
</div>
|
||||
<span>人</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="bottom-card-overview">
|
||||
<div class="bottom-card-title">
|
||||
<span>各园区统计</span>
|
||||
<img width="50%" style="margin: 8px 0" src="@/assets/images/line_1.png" />
|
||||
</div>
|
||||
<Echart :options="barChartOption" class="bar-chart" height="17.5vh" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, watch, computed } from 'vue'
|
||||
import { rgbToHex } from '@/utils/color'
|
||||
|
||||
interface Props {
|
||||
totalCount: number
|
||||
formalEmployeeCount: number
|
||||
externalStaffCount: number
|
||||
visitorCount: number
|
||||
parkStatistics?: Array<{
|
||||
name: string
|
||||
formal: number
|
||||
external: number
|
||||
visitor: number
|
||||
}>
|
||||
}
|
||||
|
||||
const props = defineProps<Props>()
|
||||
|
||||
const totalCountDigits = computed(() => String(props.totalCount).split('').map(Number))
|
||||
const formalEmployeeDigits = computed(() => String(props.formalEmployeeCount).split('').map(Number))
|
||||
const externalStaffDigits = computed(() => String(props.externalStaffCount).split('').map(Number))
|
||||
const visitorDigits = computed(() => String(props.visitorCount).split('').map(Number))
|
||||
|
||||
// 图表引用
|
||||
const barChartOption = ref({
|
||||
legend: {
|
||||
top: '10%',
|
||||
right: '15%',
|
||||
orient: 'vertical' as const,
|
||||
textStyle: {
|
||||
color: '#ffffff',
|
||||
fontSize: '11px'
|
||||
}
|
||||
},
|
||||
grid: {
|
||||
left: '5%',
|
||||
right: '30%',
|
||||
top: '10%',
|
||||
bottom: '15%'
|
||||
},
|
||||
xAxis: {
|
||||
type: 'category' as const,
|
||||
data: [],
|
||||
axisLabel: {
|
||||
color: '#ffffff',
|
||||
fontSize: 10
|
||||
},
|
||||
axisLine: {
|
||||
lineStyle: { color: '#334155' }
|
||||
}
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value' as const,
|
||||
axisLabel: {
|
||||
color: '#ffffff',
|
||||
fontSize: 10
|
||||
},
|
||||
axisLine: {
|
||||
lineStyle: { color: '#334155' }
|
||||
},
|
||||
splitLine: {
|
||||
lineStyle: { color: '#334155' }
|
||||
}
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: '正式员工',
|
||||
type: 'bar' as const,
|
||||
data: [],
|
||||
itemStyle: { color: rgbToHex(99, 196, 251) },
|
||||
barWidth: '15%'
|
||||
},
|
||||
{
|
||||
name: '外协人员',
|
||||
type: 'bar' as const,
|
||||
data: [],
|
||||
itemStyle: { color: rgbToHex(251, 246, 85) },
|
||||
barWidth: '15%'
|
||||
},
|
||||
{
|
||||
name: '访客',
|
||||
type: 'bar' as const,
|
||||
data: [],
|
||||
itemStyle: { color: rgbToHex(200, 69, 237) },
|
||||
barWidth: '15%'
|
||||
}
|
||||
]
|
||||
})
|
||||
|
||||
// 监听数据变化,更新图表
|
||||
watch(() => props.parkStatistics, (newVal) => {
|
||||
console.log('parkStatistics changed:', { newVal })
|
||||
refreshCharts(newVal)
|
||||
}, { deep: true })
|
||||
|
||||
// 更新图表数据
|
||||
const refreshCharts = (parkStatistics): void => {
|
||||
const option = { ...barChartOption.value }
|
||||
option.xAxis.data = parkStatistics.map(park => park.name)
|
||||
option.series[0].data = parkStatistics.map(park => park.formal)
|
||||
option.series[1].data = parkStatistics.map(park => park.external)
|
||||
option.series[2].data = parkStatistics.map(park => park.visitor)
|
||||
barChartOption.value = option
|
||||
}
|
||||
|
||||
// 组件挂载后初始化图表
|
||||
onMounted(() => {
|
||||
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.left-top {
|
||||
padding: 0 5px;
|
||||
background-image: url('@/assets/images/screen/left_top_img.png'), url('@/assets/images/screen/left_center_img.png'), url('@/assets/images/screen/left_bottom_img.png');
|
||||
background-position: top center, left center, bottom center;
|
||||
background-repeat: no-repeat, no-repeat, no-repeat;
|
||||
background-size: 100% 90px, cover, 100% 68px;
|
||||
flex: 1;
|
||||
|
||||
.panel-title {
|
||||
margin: 4px 20px 0;
|
||||
font-size: 0.8rem;
|
||||
font-weight: bold;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.top-card {
|
||||
display: flex;
|
||||
padding: 0 20px;
|
||||
column-gap: 15px;
|
||||
font-size: 0.8rem;
|
||||
|
||||
.top-card-left {
|
||||
display: flex;
|
||||
height: 12vh;
|
||||
min-width: 15vw;
|
||||
padding: 0 10px;
|
||||
background-image: url('@/assets/imgs/total_count_card_bg.png');
|
||||
background-size: cover;
|
||||
column-gap: 6px;
|
||||
align-items: center;
|
||||
|
||||
.number-wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 2px;
|
||||
font-size: 0.8rem;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.total-number {
|
||||
display: inline-block;
|
||||
width: 26px;
|
||||
height: 50px;
|
||||
font-size: 0.8rem;
|
||||
line-height: 50px;
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
background-color: rgb(177 74 201 / 100%);
|
||||
border-radius: 4px;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
}
|
||||
|
||||
.top-card-right {
|
||||
display: flex;
|
||||
height: 12vh;
|
||||
min-width: 20vw;
|
||||
background-image: url('@/assets/imgs/staff_types_bg.png');
|
||||
background-position: top center;
|
||||
background-size: cover;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
row-gap: 4px;
|
||||
|
||||
.top-card-right-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
column-gap: 5px;
|
||||
padding: 0 10px;
|
||||
font-size: 0.7rem;
|
||||
color: #fff;
|
||||
|
||||
.type-number-wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 2px;
|
||||
font-size: 0.8rem;
|
||||
color: #fff;
|
||||
|
||||
.type-number {
|
||||
display: inline-block;
|
||||
width: 14px;
|
||||
height: 25px;
|
||||
font-size: 0.9rem;
|
||||
line-height: 25px;
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
background-color: #1afb8f;
|
||||
border-radius: 2px;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.bottom-card-overview {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.bottom-card-title {
|
||||
display: flex;
|
||||
margin-top: 5px;
|
||||
margin-left: -15%;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.bar-chart {
|
||||
flex: 1;
|
||||
width: 80%;
|
||||
min-height: 17.5vh;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user