7/10 缴费分析,人员分析 数据对接

This commit is contained in:
Zy
2026-07-10 17:44:28 +08:00
parent 3a808750ac
commit 298f93380c
46 changed files with 1065 additions and 673 deletions

View File

@@ -17,13 +17,13 @@
<el-col :lg="8" :xl="8">
<div class="cardbox">
<div>入住情况</div>
<div class="cardbody" style="height: 200px">
<div class="card_leftbox">
<div class="valuebox">{{ movein.totalResident }}</div>
<div class="labelbox">入住人数</div>
<div class="cardBody" style="height: 200px">
<div class="card_LeftBox">
<div class="valueBox">{{ MoveIn.totalResident }}</div>
<div class="labelBox">入住人数</div>
</div>
<div class="echartsbox h-full">
<Echarts :options="options"></Echarts>
<div class="echartsBox h-full">
<Echarts :options="options as EChartsOption"></Echarts>
</div>
</div>
</div>
@@ -31,16 +31,16 @@
<el-col :lg="10" :xl="8">
<div class="cardbox">
<div>住户类型情况</div>
<div class="cardbody w-full" style="height: 150px">
<Echarts :options="options1"></Echarts>
<div class="cardBody w-full" style="height: 180px">
<Echarts :options="options1 as EChartsOption"></Echarts>
</div>
</div>
</el-col>
<el-col :lg="6" :xl="8">
<div class="cardbox">
<div>男女比例</div>
<div class="cardbody w-full" style="height: 150px">
<Echarts :options="options2"></Echarts>
<div class="cardBody w-full" style="height: 180px">
<Echarts :options="options2 as EChartsOption"></Echarts>
</div>
</div>
</el-col>
@@ -56,7 +56,7 @@
<el-row style="margin-top: 20px; position: relative; z-index: 2">
<el-col :span="24">
<div class="cardbox w-full" style="height: 450px">
<Echarts :options="flowLineOption"></Echarts>
<Echarts :options="flowLineOption as EChartsOption"></Echarts>
</div>
</el-col>
</el-row>
@@ -68,12 +68,11 @@
</template>
<script setup lang="ts">
// TODO 人员分析
import { ref } from 'vue';
import Echarts from '@/components/Echarts/index.vue';
import { EChartsOption } from 'echarts';
import { getLastNDays } from '@/utils/time';
import { get_movein_moveout_list, get_movein_user_sex, get_movein_user_type, user_movein_list } from '@/api/system/Personnel';
import { get_movein_moveout_list, get_movein_user_sex, get_movein_user_type, get_person_age, user_movein_list } from '@/api/system/Personnel';
const date = ref('');
const open = ref(true);
@@ -86,25 +85,29 @@ onUnmounted(() => {
});
function reset() {
date.value = '';
date.value = getLastNDays(10)[0];
querySelect();
}
/** 入住情况 */
const options = ref<EChartsOption>({
tooltip: { show: false },
tooltip: { show: true, trigger: 'item' },
series: [
// 1. 底层细圆环(灰色底色)
{
name: '总房屋',
type: 'pie',
radius: ['68%', '90%'], // 细一点
clockwise: true,
data: [100],
itemStyle: { color: '#ebeef5' },
emphasis: { disabled: true },
tooltip: { show: false }, // 关键:不显示提示
label: { show: false }
},
// 2. 上层粗圆环(进度条)
{
name: '入住房屋',
type: 'pie',
radius: ['65%', '98%'], // 粗一点
clockwise: true,
@@ -132,33 +135,39 @@ const options = ref<EChartsOption>({
}
}
},
data: [{ value: 85 }, { value: 15, itemStyle: { color: 'transparent' } }]
data: [
{ value: 85 },
{
value: 15,
itemStyle: { color: 'transparent' }
}
]
}
]
});
/** 入住类型 */
/** 住户类型 */
const options1 = ref<EChartsOption>({
legend: {
top: 'center',
left: '0',
orient: 'vertical',
itemGap: 50
itemGap: 80
},
tooltip: {
trigger: 'item'
},
series: [
{
name: 'Access From',
name: '住户类型',
type: 'pie',
radius: ['50%', '100%'],
radius: ['45%', '95%'],
avoidLabelOverlap: false,
left: '50%',
label: {
show: false,
position: 'center'
},
tooltip: {
show: false
},
emphasis: {
label: {
show: false,
@@ -185,12 +194,15 @@ const options2 = ref<EChartsOption>({
top: 'center',
left: '0',
orient: 'vertical',
itemGap: 50
itemGap: 80
},
tooltip: {
trigger: 'item'
},
clockwise: true,
series: [
{
name: 'Access From',
name: '男女比例',
type: 'pie',
startAngle: 280,
radius: ['50%', '100%'],
@@ -200,9 +212,6 @@ const options2 = ref<EChartsOption>({
show: false,
position: 'center'
},
tooltip: {
show: false
},
emphasis: {
label: {
show: false,
@@ -221,15 +230,23 @@ const options2 = ref<EChartsOption>({
]
});
// ! 年龄分布 -------------------------------------------------------------------------------------
// ! 年龄分布 -----------------------------------------
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 agesData = ref(new Array(11).fill(0));
const maxValue = ref(10); // 设定总高度
const middleHeight = 0.05; // 中间白条高度
const barWidth = '10%'; // 柱状图粗度
const bgData = computed(() => {
return agesData.value.map((item) => {
const num = maxValue.value - item - middleHeight;
if (num > 0) {
return num;
} else {
return maxValue.value;
}
});
});
const bgData2 = agesX.map(() => middleHeight);
/** 年龄分布 */
const options3 = shallowRef<EChartsOption>({
title: {
@@ -250,19 +267,16 @@ const options3 = shallowRef<EChartsOption>({
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,
barWidth: barWidth,
data: agesData.value,
itemStyle: {
color: '#409eff',
borderRadius: [4, 4, 0, 0]
@@ -271,7 +285,7 @@ const options3 = shallowRef<EChartsOption>({
},
{
type: 'bar',
barWidth: barwidth,
barWidth: barWidth,
data: bgData2,
tooltip: { show: false }, // 关键:不显示提示
itemStyle: {
@@ -281,8 +295,8 @@ const options3 = shallowRef<EChartsOption>({
},
{
type: 'bar',
barWidth: barwidth,
data: bgData,
barWidth: barWidth,
data: bgData.value,
tooltip: { show: false }, // 关键:不显示提示
itemStyle: {
color: 'rgba(180, 180, 180, 0.2)'
@@ -291,6 +305,65 @@ const options3 = shallowRef<EChartsOption>({
}
]
});
function updateOptions3(data: number[]): EChartsOption {
return {
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: data,
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.value,
tooltip: { show: false }, // 关键:不显示提示
itemStyle: {
color: 'rgba(180, 180, 180, 0.2)'
},
stack: 'total'
}
]
};
}
// ! 年龄分布 -------------------------------------------------------------------------------------
// ! 人员流动情况 -------------------------------------------------------------------------------------
@@ -388,7 +461,7 @@ const flowLineOption = ref<EChartsOption>({
}
]
});
function flowLineOptionFun(days: string[], indata: number[], outdata: number[]): EChartsOption {
function flowLineOptionFun(days: string[], InData: number[], OutData: number[]): EChartsOption {
return {
title: {
text: '近十日人员流动趋势',
@@ -430,7 +503,7 @@ function flowLineOptionFun(days: string[], indata: number[], outdata: number[]):
name: '人员流入',
type: 'line',
smooth: true, // 平滑折线 核心
data: indata,
data: InData,
symbol: 'circle',
symbolSize: 6,
itemStyle: { color: '#f94144' },
@@ -453,7 +526,7 @@ function flowLineOptionFun(days: string[], indata: number[], outdata: number[]):
name: '人员流出',
type: 'line',
smooth: true, // 平滑折线 核心
data: outdata,
data: OutData,
symbol: 'circle',
symbolSize: 6,
itemStyle: { color: '#f9c74f' },
@@ -477,34 +550,43 @@ function flowLineOptionFun(days: string[], indata: number[], outdata: number[]):
}
// ! 人员流动情况 -------------------------------------------------------------------------------------
const movein = ref({
const MoveIn = ref({
totalResident: 0,
totalHouse: 0
});
function init() {
// 获取入住情况
moveinFun();
// 入住情况
MoveInFun();
// 入住类型
moveinUserType();
moveinUserSex();
moveinUserMoveinOut();
MoveInUserType();
// 男女类型
MoveInUserSex();
// 迁入迁出
MoveInUserMoveInOut();
// 住户年龄分布
MoveInPersonAge();
}
init();
function querySelect() {
init();
}
function moveinFun() {
// 入住情况
function MoveInFun() {
user_movein_list({
datetime: date.value
dateTime: date.value
}).then((res) => {
// 获取入住情况
movein.value.totalResident = res.data.occupancyCount;
movein.value.totalHouse = res.data.totalHouse;
MoveIn.value.totalResident = res.data.occupancyCount;
MoveIn.value.totalHouse = res.data.totalHouse;
options.value.series[1].data = [
{ value: res.data.occupiedHouse },
{ value: res.data.totalHouse - res.data.occupiedHouse, itemStyle: { color: 'transparent' } }
{
value: res.data.totalHouse - res.data.occupiedHouse,
itemStyle: { color: 'transparent' },
tooltip: {
show: false
}
}
];
options.value.series[1].label.formatter = () => {
const total = res.data.totalHouse;
@@ -518,17 +600,22 @@ function moveinFun() {
});
}
// 获取住户类型
function moveinUserType() {
function MoveInUserType() {
get_movein_user_type({
datetime: date.value
dateTime: date.value
}).then((res) => {
console.log(res);
options1.value.series[0].data = [
{ value: res.owner, name: '业主', itemStyle: { color: '#0a74fe' } },
{ value: res.tenant, name: '租户', itemStyle: { color: '#fe3d4e' } },
{ value: res.relatives, name: '亲属', itemStyle: { color: '#00cf7f' } },
{ value: res.other, name: '其他', itemStyle: { color: '#f48e3b' } }
];
});
}
// 住户性别
function moveinUserSex() {
function MoveInUserSex() {
get_movein_user_sex({
datetime: date.value
dateTime: date.value
}).then((res) => {
options2.value.series[0].data = [
{ value: res.man, name: '男', itemStyle: { color: '#0a74fe' } },
@@ -537,11 +624,7 @@ function moveinUserSex() {
});
}
// 迁入迁出
function moveinUserMoveinOut() {
// 判断 date.value 是否为今天
if (date.value === '') {
date.value = getLastNDays(7)[0];
}
function MoveInUserMoveInOut() {
get_movein_moveout_list({
date: date.value
}).then((res) => {
@@ -551,6 +634,17 @@ function moveinUserMoveinOut() {
flowLineOption.value = flowLineOptionFun(dayX.value, inData.value, outData.value);
});
}
// 住户年龄分布
function MoveInPersonAge() {
get_person_age({
dateTime: date.value
}).then((res) => {
const values = Object.values(res).slice(0, -1);
maxValue.value = res.total;
agesData.value = values;
options3.value = updateOptions3(values);
});
}
</script>
<style scoped lang="scss">
@@ -571,6 +665,7 @@ function moveinUserMoveinOut() {
}
// 入住清空
.cardbox {
box-sizing: border-box;
background: linear-gradient(180deg, rgba(255, 255, 255, 0.2) 0%, #ffffff 70%);
border-radius: 16px 16px 16px 16px;
border: 2px solid #ffffff;
@@ -580,25 +675,25 @@ function moveinUserMoveinOut() {
@media (max-width: 1200px) {
margin-bottom: 20px;
}
.cardbody {
.cardBody {
padding: 0 30px;
display: flex;
align-items: center;
justify-content: space-between;
.card_leftbox {
.card_LeftBox {
text-align: center;
margin-right: 20px;
.labelbox {
.labelBox {
font-size: 16px;
}
.valuebox {
.valueBox {
font-weight: 600;
font-size: 36px;
color: #222222;
width: 100px;
}
}
.echartsbox {
.echartsBox {
width: 400px;
}
}