295 lines
7.3 KiB
Vue
295 lines
7.3 KiB
Vue
<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: #158e56;
|
|
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>
|