人员缴费分析
This commit is contained in:
@@ -1,12 +1,515 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="p-2 h-full flex flex-col">
|
<div class="personnel p-2 h-full flex flex-col">
|
||||||
<Pageheader></Pageheader>
|
<div class="flex flex-items-center searchBox">
|
||||||
<div class="flex-1 color-gray flex h-full font-size-6 flex-center">系统还在维护中,敬请期待...</div>
|
<div class="searchLabel">选择日期</div>
|
||||||
|
<el-date-picker
|
||||||
|
v-model="date"
|
||||||
|
type="date"
|
||||||
|
placeholder="选择日期"
|
||||||
|
value-format="yyyy-MM-dd"
|
||||||
|
style="width: 400px; margin-right: 10px"
|
||||||
|
></el-date-picker>
|
||||||
|
<el-button type="primary">查询</el-button>
|
||||||
|
<el-button>重置</el-button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<el-row :gutter="20">
|
||||||
|
<el-col :span="16">
|
||||||
|
<div class="cardbox">
|
||||||
|
<div>收入来源</div>
|
||||||
|
<div class="cardbody" style="height: 200px">
|
||||||
|
<div class="flex flex-col flex-items-center flex-1">
|
||||||
|
<Echarts :options="options"></Echarts>
|
||||||
|
<div>停车费</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex flex-col flex-items-center flex-1">
|
||||||
|
<Echarts :options="options"></Echarts>
|
||||||
|
<div>物业费</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex flex-col flex-items-center flex-1">
|
||||||
|
<Echarts :options="options"></Echarts>
|
||||||
|
<div>商铺租金</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex flex-col flex-items-center flex-1">
|
||||||
|
<Echarts :options="options"></Echarts>
|
||||||
|
<div>水电费</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex flex-col flex-items-center flex-1">
|
||||||
|
<Echarts :options="options"></Echarts>
|
||||||
|
<div>维修费</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="8">
|
||||||
|
<div class="cardbox">
|
||||||
|
<div>缴费方式</div>
|
||||||
|
<div class="cardbody w-full" style="height: 150px">
|
||||||
|
<Echarts :options="options2"></Echarts>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
<div class="" style="height: 20px"></div>
|
||||||
|
<el-row :gutter="20">
|
||||||
|
<el-col :span="16">
|
||||||
|
<div class="cardbox w-full" style="height: 400px">
|
||||||
|
<Echarts :options="options3"></Echarts>
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="8">
|
||||||
|
<div class="cardbox w-full" style="height: 400px">
|
||||||
|
<div class="" style="height: 50px; margin-bottom: 20px">缴费方式</div>
|
||||||
|
<div flex flex-items-center justify-center>
|
||||||
|
<ul class="legendbox">
|
||||||
|
<li>小程序</li>
|
||||||
|
<li>物业缴费</li>
|
||||||
|
<li>手机APP</li>
|
||||||
|
</ul>
|
||||||
|
<ul class="circlebox">
|
||||||
|
<li>70%</li>
|
||||||
|
<li>20%</li>
|
||||||
|
<li>10%</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
<div class="" style="height: 20px"></div>
|
||||||
|
<el-row>
|
||||||
|
<el-col :span="24">
|
||||||
|
<div class="cardbox w-full" style="height: 450px">
|
||||||
|
<Echarts :options="flowLineOption"></Echarts>
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
|
import Echarts from '@/components/Echarts/index.vue';
|
||||||
|
import { EChartsOption } from 'echarts';
|
||||||
|
import { getLast7Days, getLastNDays } from '@/utils/time';
|
||||||
|
|
||||||
|
/** 入住情况 */
|
||||||
|
const options = shallowRef<EChartsOption>({
|
||||||
|
tooltip: { show: false },
|
||||||
|
series: [
|
||||||
|
// 1. 底层细圆环(灰色底色)
|
||||||
|
{
|
||||||
|
type: 'pie',
|
||||||
|
radius: ['60%', '80%'], // 细一点
|
||||||
|
clockwise: true,
|
||||||
|
data: [100],
|
||||||
|
itemStyle: { color: '#ebeef5' },
|
||||||
|
emphasis: { disabled: true },
|
||||||
|
label: { show: false }
|
||||||
|
},
|
||||||
|
// 2. 上层粗圆环(进度条)
|
||||||
|
{
|
||||||
|
type: 'pie',
|
||||||
|
radius: ['60%', '85%'], // 粗一点
|
||||||
|
clockwise: true,
|
||||||
|
itemStyle: {
|
||||||
|
color: '#409eff',
|
||||||
|
borderRadius: 10
|
||||||
|
},
|
||||||
|
emphasis: { disabled: true },
|
||||||
|
label: {
|
||||||
|
show: true,
|
||||||
|
position: 'center',
|
||||||
|
fontSize: 20,
|
||||||
|
fontWeight: 'bold',
|
||||||
|
formatter: '85%'
|
||||||
|
},
|
||||||
|
data: [{ value: 85 }, { value: 15, itemStyle: { color: 'transparent' } }]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
/** 入住类型 */
|
||||||
|
const options1 = shallowRef<EChartsOption>({
|
||||||
|
legend: {
|
||||||
|
top: 'center',
|
||||||
|
left: '0',
|
||||||
|
orient: 'vertical',
|
||||||
|
itemGap: 50
|
||||||
|
},
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
name: 'Access From',
|
||||||
|
type: 'pie',
|
||||||
|
radius: ['50%', '100%'],
|
||||||
|
avoidLabelOverlap: false,
|
||||||
|
left: '50%',
|
||||||
|
label: {
|
||||||
|
show: false,
|
||||||
|
position: 'center'
|
||||||
|
},
|
||||||
|
tooltip: {
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
emphasis: {
|
||||||
|
label: {
|
||||||
|
show: false,
|
||||||
|
fontSize: 20,
|
||||||
|
fontWeight: 'bold'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
labelLine: {
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
data: [
|
||||||
|
{ value: 25, name: '业主', itemStyle: { color: '#0a74fe' } },
|
||||||
|
{ value: 25, name: '租户', itemStyle: { color: '#fe3d4e' } },
|
||||||
|
{ value: 25, name: '亲属', itemStyle: { color: '#00cf7f' } },
|
||||||
|
{ value: 25, name: '其他', itemStyle: { color: '#f48e3b' } }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
/** 缴费方式 */
|
||||||
|
const options2 = shallowRef<EChartsOption>({
|
||||||
|
legend: {
|
||||||
|
top: 'center',
|
||||||
|
left: '0',
|
||||||
|
orient: 'vertical',
|
||||||
|
itemGap: 50
|
||||||
|
},
|
||||||
|
clockwise: true,
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
name: 'Access From',
|
||||||
|
type: 'pie',
|
||||||
|
startAngle: 280,
|
||||||
|
radius: ['50%', '100%'],
|
||||||
|
avoidLabelOverlap: false,
|
||||||
|
left: '50%',
|
||||||
|
label: {
|
||||||
|
show: false,
|
||||||
|
position: 'center'
|
||||||
|
},
|
||||||
|
tooltip: {
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
emphasis: {
|
||||||
|
label: {
|
||||||
|
show: false,
|
||||||
|
fontSize: 20,
|
||||||
|
fontWeight: 'bold'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
labelLine: {
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
data: [
|
||||||
|
{ value: 50, name: '支付宝', itemStyle: { color: '#0a74fe' } },
|
||||||
|
{ value: 30, name: '微信', itemStyle: { color: '#f74043' } },
|
||||||
|
{ value: 20, name: '线下', itemStyle: { color: '#fcd152' } }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
// ! 年龄分布 -------------------------------------------------------------------------------------
|
||||||
|
const agesX = ['6岁以下', '6-11岁', '11-14岁', '15-24岁', '25-30岁', '31-40岁', '41-50岁', '51-61岁', '61-65岁', '65-70岁', '70岁以上'];
|
||||||
|
const agesData = [520, 680, 460, 750, 1350, 1860, 1420, 960, 630, 380, 210];
|
||||||
|
// 🔥 关键:灰色背景数据 = 最大值 - 真实数据(互补100%)
|
||||||
|
const maxValue = 2000; // 设定总高度(可自行调整)
|
||||||
|
const middleHeight = 20;
|
||||||
|
const barwidth = '10%';
|
||||||
|
const bgData = agesData.map((item) => maxValue - item - middleHeight);
|
||||||
|
const bgData2 = agesData.map((item) => middleHeight);
|
||||||
|
/** 年龄分布 */
|
||||||
|
const options3 = shallowRef<EChartsOption>({
|
||||||
|
title: {
|
||||||
|
text: '住户年龄分布',
|
||||||
|
left: '0',
|
||||||
|
top: '0',
|
||||||
|
textStyle: { fontSize: 16, fontWeight: 'bold' }
|
||||||
|
},
|
||||||
|
grid: {
|
||||||
|
left: '3%',
|
||||||
|
right: '4%',
|
||||||
|
top: '12%',
|
||||||
|
bottom: '8%',
|
||||||
|
containLabel: true
|
||||||
|
},
|
||||||
|
tooltip: {
|
||||||
|
trigger: 'item',
|
||||||
|
confine: true,
|
||||||
|
axisPointer: { type: 'shadow' }
|
||||||
|
},
|
||||||
|
// 鼠标悬浮高亮当前,其他隐藏
|
||||||
|
|
||||||
|
xAxis: { type: 'category', data: agesX, axisLabel: { interval: 0 } },
|
||||||
|
yAxis: {
|
||||||
|
type: 'value',
|
||||||
|
splitLine: { show: true, lineStyle: { color: '#eee' } }
|
||||||
|
},
|
||||||
|
series: [
|
||||||
|
// 蓝色真实数据
|
||||||
|
{
|
||||||
|
type: 'bar',
|
||||||
|
barWidth: barwidth,
|
||||||
|
data: agesData,
|
||||||
|
itemStyle: {
|
||||||
|
color: '#409eff',
|
||||||
|
borderRadius: [4, 4, 0, 0]
|
||||||
|
},
|
||||||
|
stack: 'total'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'bar',
|
||||||
|
barWidth: barwidth,
|
||||||
|
data: bgData2,
|
||||||
|
tooltip: { show: false }, // 关键:不显示提示
|
||||||
|
itemStyle: {
|
||||||
|
color: '#fff'
|
||||||
|
},
|
||||||
|
stack: 'total'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'bar',
|
||||||
|
barWidth: barwidth,
|
||||||
|
data: bgData,
|
||||||
|
tooltip: { show: false }, // 关键:不显示提示
|
||||||
|
itemStyle: {
|
||||||
|
color: 'rgba(180, 180, 180, 0.2)'
|
||||||
|
},
|
||||||
|
stack: 'total'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
// ! 年龄分布 -------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// ! 职业分布比例 -------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// ! 职业分布比例 -------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// ! 人员流动情况 -------------------------------------------------------------------------------------
|
||||||
|
// 近10天日期
|
||||||
|
const dayX = getLast7Days(10);
|
||||||
|
|
||||||
|
// 小区真实规模:人员流入 / 流出 数据
|
||||||
|
const inData = [97, 145, 63, 112, 88, 156, 74, 131, 102, 59];
|
||||||
|
const outData = [121, 85, 142, 71, 135, 93, 116, 66, 148, 104];
|
||||||
|
|
||||||
|
/** 进十日缴费数量情况 - 平滑折线图 */
|
||||||
|
const flowLineOption = shallowRef<EChartsOption>({
|
||||||
|
title: {
|
||||||
|
text: '进十日缴费数量趋势',
|
||||||
|
left: 0,
|
||||||
|
top: 0,
|
||||||
|
textStyle: { fontSize: 14, fontWeight: 'normal' }
|
||||||
|
},
|
||||||
|
tooltip: {
|
||||||
|
trigger: 'axis',
|
||||||
|
confine: true
|
||||||
|
},
|
||||||
|
grid: {
|
||||||
|
left: '3%',
|
||||||
|
right: '4%',
|
||||||
|
top: '12%',
|
||||||
|
bottom: '8%',
|
||||||
|
containLabel: true
|
||||||
|
},
|
||||||
|
legend: {
|
||||||
|
data: ['已缴费', '未缴费'],
|
||||||
|
right: 10,
|
||||||
|
top: 0
|
||||||
|
},
|
||||||
|
xAxis: {
|
||||||
|
type: 'category',
|
||||||
|
data: dayX,
|
||||||
|
boundaryGap: false,
|
||||||
|
axisLine: { lineStyle: { color: '#eee' } }
|
||||||
|
},
|
||||||
|
yAxis: {
|
||||||
|
type: 'value',
|
||||||
|
splitLine: {
|
||||||
|
show: true,
|
||||||
|
lineStyle: { color: '#eee' }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
name: '已缴费',
|
||||||
|
type: 'line',
|
||||||
|
smooth: true, // 平滑折线 核心
|
||||||
|
data: inData,
|
||||||
|
symbol: 'circle',
|
||||||
|
symbolSize: 6,
|
||||||
|
itemStyle: { color: '#f94144' },
|
||||||
|
lineStyle: { width: 4 },
|
||||||
|
areaStyle: {
|
||||||
|
color: {
|
||||||
|
type: 'linear',
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
x2: 0,
|
||||||
|
y2: 1,
|
||||||
|
colorStops: [
|
||||||
|
{ offset: 0, color: '#fbd7d9' },
|
||||||
|
{ offset: 1, color: '#fbd7d9' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '未缴费',
|
||||||
|
type: 'line',
|
||||||
|
smooth: true, // 平滑折线 核心
|
||||||
|
data: outData,
|
||||||
|
symbol: 'circle',
|
||||||
|
symbolSize: 6,
|
||||||
|
itemStyle: { color: '#f9c74f' },
|
||||||
|
lineStyle: { width: 4 },
|
||||||
|
areaStyle: {
|
||||||
|
color: {
|
||||||
|
type: 'linear',
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
x2: 0,
|
||||||
|
y2: 1,
|
||||||
|
colorStops: [
|
||||||
|
{ offset: 0, color: '#fcf2dc' },
|
||||||
|
{ offset: 1, color: '#fcf2dc' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
// ! 人员流动情况 -------------------------------------------------------------------------------------
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss"></style>
|
<style scoped lang="scss">
|
||||||
|
.personnel {
|
||||||
|
background: linear-gradient(180deg, #deedff 0%, #f8f9fe 50%);
|
||||||
|
.el-button {
|
||||||
|
width: 80px;
|
||||||
|
height: 32px;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
.searchBox {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
.searchLabel {
|
||||||
|
width: 100px;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
}
|
||||||
|
// 入住清空
|
||||||
|
.cardbox {
|
||||||
|
background: linear-gradient(180deg, rgba(255, 255, 255, 0.2) 0%, #ffffff 70%);
|
||||||
|
border-radius: 16px 16px 16px 16px;
|
||||||
|
border: 2px solid #ffffff;
|
||||||
|
font-size: 20px;
|
||||||
|
padding: 20px;
|
||||||
|
min-height: 275px;
|
||||||
|
.cardbody {
|
||||||
|
padding: 0 30px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
.card_leftbox {
|
||||||
|
text-align: center;
|
||||||
|
.labelbox {
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
.valuebox {
|
||||||
|
font-weight: 600;
|
||||||
|
font-size: 36px;
|
||||||
|
color: #222222;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.echartsbox {
|
||||||
|
width: 400px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.legendbox {
|
||||||
|
font-size: 0.8rem;
|
||||||
|
li {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
position: relative;
|
||||||
|
width: 100px;
|
||||||
|
height: 50px;
|
||||||
|
line-height: 50px;
|
||||||
|
text-align: left;
|
||||||
|
padding-left: 30px;
|
||||||
|
&::after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 50%;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
display: block;
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: #c893fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:first-of-type {
|
||||||
|
&::after {
|
||||||
|
background: #4a3aff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&:last-of-type {
|
||||||
|
&::after {
|
||||||
|
background: #1e1b39;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.circlebox {
|
||||||
|
margin-left: 60px;
|
||||||
|
position: relative;
|
||||||
|
width: 300px;
|
||||||
|
height: 200px;
|
||||||
|
transform: translateY(-40px);
|
||||||
|
li {
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
top: 0;
|
||||||
|
width: 150px;
|
||||||
|
height: 150px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background-color: #c893fd;
|
||||||
|
border: 3px solid white;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
color: #fff;
|
||||||
|
font-size: 1.4rem;
|
||||||
|
font-weight: 450;
|
||||||
|
z-index: 10;
|
||||||
|
&:nth-child(1) {
|
||||||
|
width: 200px;
|
||||||
|
height: 200px;
|
||||||
|
right: inherit;
|
||||||
|
left: 0px;
|
||||||
|
font-size: 2rem;
|
||||||
|
top: 30px;
|
||||||
|
z-index: 9;
|
||||||
|
background-color: #4a3aff;
|
||||||
|
}
|
||||||
|
&:nth-child(3) {
|
||||||
|
width: 100px;
|
||||||
|
height: 100px;
|
||||||
|
left: inherit;
|
||||||
|
top: inherit;
|
||||||
|
right: 50px;
|
||||||
|
font-size: 1.1rem;
|
||||||
|
bottom: -20px;
|
||||||
|
z-index: 11;
|
||||||
|
background-color: #1e1b39;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
@@ -1,12 +1,477 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="p-2 h-full flex flex-col">
|
<div class="personnel p-2 h-full flex flex-col">
|
||||||
<Pageheader></Pageheader>
|
<div class="flex flex-items-center searchBox">
|
||||||
<div class="flex-1 color-gray flex h-full font-size-6 flex-center">系统还在维护中,敬请期待...</div>
|
<div class="searchLabel">选择日期</div>
|
||||||
|
<el-date-picker
|
||||||
|
v-model="date"
|
||||||
|
type="date"
|
||||||
|
placeholder="选择日期"
|
||||||
|
value-format="yyyy-MM-dd"
|
||||||
|
style="width: 400px; margin-right: 10px"
|
||||||
|
></el-date-picker>
|
||||||
|
<el-button type="primary">查询</el-button>
|
||||||
|
<el-button>重置</el-button>
|
||||||
|
</div>
|
||||||
|
<el-row :gutter="20">
|
||||||
|
<el-col :span="8">
|
||||||
|
<div class="cardbox">
|
||||||
|
<div>入住情况</div>
|
||||||
|
<div class="cardbody" style="height: 200px">
|
||||||
|
<div class="card_leftbox">
|
||||||
|
<div class="valuebox">4889</div>
|
||||||
|
<div class="labelbox">入住人数</div>
|
||||||
|
</div>
|
||||||
|
<div class="echartsbox h-full">
|
||||||
|
<Echarts :options="options"></Echarts>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="8">
|
||||||
|
<div class="cardbox">
|
||||||
|
<div>住户分析情况</div>
|
||||||
|
<div class="cardbody w-full" style="height: 150px">
|
||||||
|
<Echarts :options="options1"></Echarts>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="8">
|
||||||
|
<div class="cardbox">
|
||||||
|
<div>男女比例</div>
|
||||||
|
<div class="cardbody w-full" style="height: 150px">
|
||||||
|
<Echarts :options="options2"></Echarts>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
<div class="" style="height: 20px"></div>
|
||||||
|
<el-row :gutter="20">
|
||||||
|
<el-col :span="16">
|
||||||
|
<div class="cardbox w-full" style="height: 400px">
|
||||||
|
<Echarts :options="options3"></Echarts>
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="8">
|
||||||
|
<div class="cardbox w-full" style="height: 400px">
|
||||||
|
<Echarts :options="options4"></Echarts>
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
<div class="" style="height: 20px"></div>
|
||||||
|
<el-row>
|
||||||
|
<el-col :span="24">
|
||||||
|
<div class="cardbox w-full" style="height: 450px">
|
||||||
|
<Echarts :options="flowLineOption"></Echarts>
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
|
import Echarts from '@/components/Echarts/index.vue';
|
||||||
|
import { EChartsOption } from 'echarts';
|
||||||
|
import { getLast7Days, getLastNDays } from '@/utils/time';
|
||||||
|
|
||||||
|
/** 入住情况 */
|
||||||
|
const options = shallowRef<EChartsOption>({
|
||||||
|
tooltip: { show: false },
|
||||||
|
series: [
|
||||||
|
// 1. 底层细圆环(灰色底色)
|
||||||
|
{
|
||||||
|
type: 'pie',
|
||||||
|
radius: ['68%', '90%'], // 细一点
|
||||||
|
clockwise: true,
|
||||||
|
data: [100],
|
||||||
|
itemStyle: { color: '#ebeef5' },
|
||||||
|
emphasis: { disabled: true },
|
||||||
|
label: { show: false }
|
||||||
|
},
|
||||||
|
// 2. 上层粗圆环(进度条)
|
||||||
|
{
|
||||||
|
type: 'pie',
|
||||||
|
radius: ['65%', '98%'], // 粗一点
|
||||||
|
clockwise: true,
|
||||||
|
itemStyle: {
|
||||||
|
color: '#409eff',
|
||||||
|
borderRadius: 10
|
||||||
|
},
|
||||||
|
emphasis: { disabled: true },
|
||||||
|
label: {
|
||||||
|
show: true,
|
||||||
|
position: 'center',
|
||||||
|
fontSize: 20,
|
||||||
|
fontWeight: 'bold',
|
||||||
|
formatter: ' 85% \n\n 入住率'
|
||||||
|
},
|
||||||
|
data: [{ value: 85 }, { value: 15, itemStyle: { color: 'transparent' } }]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
function getRingOption(percent) {
|
||||||
|
return {
|
||||||
|
tooltip: { show: false },
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
type: 'pie',
|
||||||
|
radius: ['78%', '88%'],
|
||||||
|
data: [100],
|
||||||
|
itemStyle: { color: '#ebeef5' },
|
||||||
|
emphasis: { disabled: true },
|
||||||
|
label: { show: false }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'pie',
|
||||||
|
radius: ['75%', '90%'],
|
||||||
|
itemStyle: { color: '#409eff', borderRadius: 10 },
|
||||||
|
emphasis: { disabled: true },
|
||||||
|
label: {
|
||||||
|
show: true,
|
||||||
|
position: 'center',
|
||||||
|
fontSize: 18,
|
||||||
|
fontWeight: 'bold',
|
||||||
|
formatter: percent + '%'
|
||||||
|
},
|
||||||
|
data: [{ value: percent }, { value: 100 - percent, itemStyle: { color: 'transparent' } }]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 入住类型 */
|
||||||
|
const options1 = shallowRef<EChartsOption>({
|
||||||
|
legend: {
|
||||||
|
top: 'center',
|
||||||
|
left: '0',
|
||||||
|
orient: 'vertical',
|
||||||
|
itemGap: 50
|
||||||
|
},
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
name: 'Access From',
|
||||||
|
type: 'pie',
|
||||||
|
radius: ['50%', '100%'],
|
||||||
|
avoidLabelOverlap: false,
|
||||||
|
left: '50%',
|
||||||
|
label: {
|
||||||
|
show: false,
|
||||||
|
position: 'center'
|
||||||
|
},
|
||||||
|
tooltip: {
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
emphasis: {
|
||||||
|
label: {
|
||||||
|
show: false,
|
||||||
|
fontSize: 20,
|
||||||
|
fontWeight: 'bold'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
labelLine: {
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
data: [
|
||||||
|
{ value: 25, name: '业主', itemStyle: { color: '#0a74fe' } },
|
||||||
|
{ value: 25, name: '租户', itemStyle: { color: '#fe3d4e' } },
|
||||||
|
{ value: 25, name: '亲属', itemStyle: { color: '#00cf7f' } },
|
||||||
|
{ value: 25, name: '其他', itemStyle: { color: '#f48e3b' } }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
/** 男女比例 */
|
||||||
|
const options2 = shallowRef<EChartsOption>({
|
||||||
|
legend: {
|
||||||
|
top: 'center',
|
||||||
|
left: '0',
|
||||||
|
orient: 'vertical',
|
||||||
|
itemGap: 50
|
||||||
|
},
|
||||||
|
clockwise: true,
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
name: 'Access From',
|
||||||
|
type: 'pie',
|
||||||
|
startAngle: 280,
|
||||||
|
radius: ['50%', '100%'],
|
||||||
|
avoidLabelOverlap: false,
|
||||||
|
left: '50%',
|
||||||
|
label: {
|
||||||
|
show: false,
|
||||||
|
position: 'center'
|
||||||
|
},
|
||||||
|
tooltip: {
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
emphasis: {
|
||||||
|
label: {
|
||||||
|
show: false,
|
||||||
|
fontSize: 20,
|
||||||
|
fontWeight: 'bold'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
labelLine: {
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
data: [
|
||||||
|
{ value: 60, name: '男', itemStyle: { color: '#0a74fe' } },
|
||||||
|
{ value: 40, name: '女', itemStyle: { color: '#f74043' } }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
// ! 年龄分布 -------------------------------------------------------------------------------------
|
||||||
|
const agesX = ['6岁以下', '6-11岁', '11-14岁', '15-24岁', '25-30岁', '31-40岁', '41-50岁', '51-61岁', '61-65岁', '65-70岁', '70岁以上'];
|
||||||
|
const agesData = [520, 680, 460, 750, 1350, 1860, 1420, 960, 630, 380, 210];
|
||||||
|
// 🔥 关键:灰色背景数据 = 最大值 - 真实数据(互补100%)
|
||||||
|
const maxValue = 2000; // 设定总高度(可自行调整)
|
||||||
|
const middleHeight = 20;
|
||||||
|
const barwidth = '10%';
|
||||||
|
const bgData = agesData.map((item) => maxValue - item - middleHeight);
|
||||||
|
const bgData2 = agesData.map((item) => middleHeight);
|
||||||
|
/** 年龄分布 */
|
||||||
|
const options3 = shallowRef<EChartsOption>({
|
||||||
|
title: {
|
||||||
|
text: '住户年龄分布',
|
||||||
|
left: '0',
|
||||||
|
top: '0',
|
||||||
|
textStyle: { fontSize: 16, fontWeight: 'bold' }
|
||||||
|
},
|
||||||
|
grid: {
|
||||||
|
left: '3%',
|
||||||
|
right: '4%',
|
||||||
|
top: '12%',
|
||||||
|
bottom: '8%',
|
||||||
|
containLabel: true
|
||||||
|
},
|
||||||
|
tooltip: {
|
||||||
|
trigger: 'item',
|
||||||
|
confine: true,
|
||||||
|
axisPointer: { type: 'shadow' }
|
||||||
|
},
|
||||||
|
// 鼠标悬浮高亮当前,其他隐藏
|
||||||
|
|
||||||
|
xAxis: { type: 'category', data: agesX, axisLabel: { interval: 0 } },
|
||||||
|
yAxis: {
|
||||||
|
type: 'value',
|
||||||
|
splitLine: { show: true, lineStyle: { color: '#eee' } }
|
||||||
|
},
|
||||||
|
series: [
|
||||||
|
// 蓝色真实数据
|
||||||
|
{
|
||||||
|
type: 'bar',
|
||||||
|
barWidth: barwidth,
|
||||||
|
data: agesData,
|
||||||
|
itemStyle: {
|
||||||
|
color: '#409eff',
|
||||||
|
borderRadius: [4, 4, 0, 0]
|
||||||
|
},
|
||||||
|
stack: 'total'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'bar',
|
||||||
|
barWidth: barwidth,
|
||||||
|
data: bgData2,
|
||||||
|
tooltip: { show: false }, // 关键:不显示提示
|
||||||
|
itemStyle: {
|
||||||
|
color: '#fff'
|
||||||
|
},
|
||||||
|
stack: 'total'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'bar',
|
||||||
|
barWidth: barwidth,
|
||||||
|
data: bgData,
|
||||||
|
tooltip: { show: false }, // 关键:不显示提示
|
||||||
|
itemStyle: {
|
||||||
|
color: 'rgba(180, 180, 180, 0.2)'
|
||||||
|
},
|
||||||
|
stack: 'total'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
// ! 年龄分布 -------------------------------------------------------------------------------------
|
||||||
|
// ! 职业分布比例 -------------------------------------------------------------------------------------
|
||||||
|
// 真实小区职业分布数据(上班族最多,依次递减)
|
||||||
|
const realData = [120, 260, 580, 620, 1480];
|
||||||
|
const options4 = shallowRef<EChartsOption>({
|
||||||
|
title: {
|
||||||
|
text: '职业分布比例',
|
||||||
|
left: '0',
|
||||||
|
top: '0',
|
||||||
|
textStyle: { fontSize: 16, fontWeight: 'bold' }
|
||||||
|
},
|
||||||
|
tooltip: {
|
||||||
|
trigger: 'axis',
|
||||||
|
axisPointer: {
|
||||||
|
type: 'shadow'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
xAxis: {
|
||||||
|
type: 'value',
|
||||||
|
boundaryGap: [0, 0.01]
|
||||||
|
},
|
||||||
|
yAxis: {
|
||||||
|
type: 'category',
|
||||||
|
data: ['其他', '自由职业', '学生', '全职妈妈', '上班族']
|
||||||
|
},
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
name: '2011',
|
||||||
|
type: 'bar',
|
||||||
|
itemStyle: {
|
||||||
|
color: '#fe3d4e'
|
||||||
|
},
|
||||||
|
data: realData
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
// ! 职业分布比例 -------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// ! 人员流动情况 -------------------------------------------------------------------------------------
|
||||||
|
// 近10天日期
|
||||||
|
const dayX = getLast7Days(10);
|
||||||
|
|
||||||
|
// 小区真实规模:人员流入 / 流出 数据
|
||||||
|
// 【全新打乱随机数据】小区人员流入 / 流出
|
||||||
|
const inData = [132, 76, 158, 91, 125, 68, 143, 84, 107, 162];
|
||||||
|
const outData = [95, 136, 72, 118, 83, 149, 65, 124, 101, 77];
|
||||||
|
|
||||||
|
/** 近十天人员流入流出 - 平滑折线图 */
|
||||||
|
const flowLineOption = shallowRef<EChartsOption>({
|
||||||
|
title: {
|
||||||
|
text: '近十日人员流动趋势',
|
||||||
|
left: 0,
|
||||||
|
top: 0,
|
||||||
|
textStyle: { fontSize: 14, fontWeight: 'normal' }
|
||||||
|
},
|
||||||
|
tooltip: {
|
||||||
|
trigger: 'axis',
|
||||||
|
confine: true
|
||||||
|
},
|
||||||
|
grid: {
|
||||||
|
left: '3%',
|
||||||
|
right: '4%',
|
||||||
|
top: '12%',
|
||||||
|
bottom: '8%',
|
||||||
|
containLabel: true
|
||||||
|
},
|
||||||
|
legend: {
|
||||||
|
data: ['人员流入', '人员流出'],
|
||||||
|
right: 10,
|
||||||
|
top: 0
|
||||||
|
},
|
||||||
|
xAxis: {
|
||||||
|
type: 'category',
|
||||||
|
data: dayX,
|
||||||
|
boundaryGap: false,
|
||||||
|
axisLine: { lineStyle: { color: '#eee' } }
|
||||||
|
},
|
||||||
|
yAxis: {
|
||||||
|
type: 'value',
|
||||||
|
splitLine: {
|
||||||
|
show: true,
|
||||||
|
lineStyle: { color: '#eee' }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
name: '人员流入',
|
||||||
|
type: 'line',
|
||||||
|
smooth: true, // 平滑折线 核心
|
||||||
|
data: inData,
|
||||||
|
symbol: 'circle',
|
||||||
|
symbolSize: 6,
|
||||||
|
itemStyle: { color: '#f94144' },
|
||||||
|
lineStyle: { width: 4 },
|
||||||
|
areaStyle: {
|
||||||
|
color: {
|
||||||
|
type: 'linear',
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
x2: 0,
|
||||||
|
y2: 1,
|
||||||
|
colorStops: [
|
||||||
|
{ offset: 0, color: '#fbd7d9' },
|
||||||
|
{ offset: 1, color: '#fbd7d9' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '人员流出',
|
||||||
|
type: 'line',
|
||||||
|
smooth: true, // 平滑折线 核心
|
||||||
|
data: outData,
|
||||||
|
symbol: 'circle',
|
||||||
|
symbolSize: 6,
|
||||||
|
itemStyle: { color: '#f9c74f' },
|
||||||
|
lineStyle: { width: 4 },
|
||||||
|
areaStyle: {
|
||||||
|
color: {
|
||||||
|
type: 'linear',
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
x2: 0,
|
||||||
|
y2: 1,
|
||||||
|
colorStops: [
|
||||||
|
{ offset: 0, color: '#fcf2dc' },
|
||||||
|
{ offset: 1, color: '#fcf2dc' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
// ! 人员流动情况 -------------------------------------------------------------------------------------
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss"></style>
|
<style scoped lang="scss">
|
||||||
|
.personnel {
|
||||||
|
background: linear-gradient(180deg, #deedff 0%, #f8f9fe 50%);
|
||||||
|
.el-button {
|
||||||
|
width: 80px;
|
||||||
|
height: 32px;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
.searchBox {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
.searchLabel {
|
||||||
|
width: 100px;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
}
|
||||||
|
// 入住清空
|
||||||
|
.cardbox {
|
||||||
|
background: linear-gradient(180deg, rgba(255, 255, 255, 0.2) 0%, #ffffff 70%);
|
||||||
|
border-radius: 16px 16px 16px 16px;
|
||||||
|
border: 2px solid #ffffff;
|
||||||
|
font-size: 20px;
|
||||||
|
padding: 20px;
|
||||||
|
min-height: 275px;
|
||||||
|
.cardbody {
|
||||||
|
padding: 0 30px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
.card_leftbox {
|
||||||
|
text-align: center;
|
||||||
|
.labelbox {
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
.valuebox {
|
||||||
|
font-weight: 600;
|
||||||
|
font-size: 36px;
|
||||||
|
color: #222222;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.echartsbox {
|
||||||
|
width: 400px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
Reference in New Issue
Block a user