同步6/16

This commit is contained in:
Zy
2026-06-01 18:12:58 +08:00
parent 38274ab612
commit 50e7b14fd6
183 changed files with 8956 additions and 4803 deletions

View File

@@ -6,19 +6,20 @@
v-model="date"
type="date"
placeholder="选择日期"
value-format="yyyy-MM-dd"
value-format="YYYY-MM-DD"
style="width: 400px; margin-right: 10px"
></el-date-picker>
<el-button type="primary">查询</el-button>
<el-button>重置</el-button>
<el-button type="primary" @click="querySelect">查询</el-button>
<el-button @click="reset">重置</el-button>
</div>
<el-row :gutter="20">
<el-col :lg="7" :xl="8">
<el-row :gutter="20" style="position: relative; z-index: 2">
<el-col :lg="8" :xl="8">
<div class="cardbox">
<div>入住情况</div>
<div class="cardbody" style="height: 200px">
<div class="card_leftbox">
<div class="valuebox">4889</div>
<div class="valuebox">{{ movein.totalResident }}</div>
<div class="labelbox">入住人数</div>
</div>
<div class="echartsbox h-full">
@@ -27,15 +28,15 @@
</div>
</div>
</el-col>
<el-col :lg="9" :xl="8">
<el-col :lg="10" :xl="8">
<div class="cardbox">
<div>住户分析情况</div>
<div>住户类型情况</div>
<div class="cardbody w-full" style="height: 150px">
<Echarts :options="options1"></Echarts>
</div>
</div>
</el-col>
<el-col :lg="8" :xl="8">
<el-col :lg="6" :xl="8">
<div class="cardbox">
<div>男女比例</div>
<div class="cardbody w-full" style="height: 150px">
@@ -45,39 +46,51 @@
</el-col>
</el-row>
<el-row style="margin-top: 20px" :gutter="20">
<el-col :lg="16" :xl="16">
<el-row style="margin-top: 20px; position: relative; z-index: 2" :gutter="20">
<el-col :lg="24" :xl="24">
<div class="cardbox w-full" style="height: 400px">
<Echarts :options="options3"></Echarts>
</div>
</el-col>
<el-col :lg="8" :xl="8">
<div class="cardbox w-full" style="height: 400px">
<Echarts :options="options4"></Echarts>
</div>
</el-col>
</el-row>
<el-row style="margin-top: 20px">
<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>
</div>
</el-col>
</el-row>
<Teleport to="body">
<i v-if="open" class="bgColor"></i>
</Teleport>
</div>
</template>
<script setup lang="ts">
// TODO 人员分析
import { ref } from 'vue';
import Echarts from '@/components/Echarts/index.vue';
import { EChartsOption } from 'echarts';
import { getLast7Days, getLastNDays } from '@/utils/time';
import { get_movein_moveout_list, get_movein_user_sex, get_movein_user_type, user_movein_list } from '@/api/system/Personnel';
const date = ref('');
const open = ref(true);
onMounted(() => {
open.value = true;
});
onUnmounted(() => {
open.value = false;
});
function reset() {
date.value = '';
}
/** 入住情况 */
const options = shallowRef<EChartsOption>({
const options = ref<EChartsOption>({
tooltip: { show: false },
series: [
// 1. 底层细圆环(灰色底色)
@@ -97,7 +110,7 @@ const options = shallowRef<EChartsOption>({
clockwise: true,
itemStyle: {
color: '#409eff',
borderRadius: 10
borderRadius: 2
},
emphasis: { disabled: true },
label: {
@@ -105,44 +118,27 @@ const options = shallowRef<EChartsOption>({
position: 'center',
fontSize: 18,
fontWeight: 'bold',
formatter: ' 85% \n 入住率'
color: '#333',
// 【新增】富文本样式配置,可以分别控制两行的样式
rich: {
rate: {
color: 'rgba(63, 223, 149, 1)',
fontSize: 20, // 百分比用主题色
padding: [0, 0, 10, 0] // 下边距,拉开与文字的距离
},
title: {
fontSize: 14,
color: 'rgba(0, 0, 0, 1)' // 文字用灰色
}
}
},
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>({
const options1 = ref<EChartsOption>({
legend: {
top: 'center',
left: '0',
@@ -184,7 +180,7 @@ const options1 = shallowRef<EChartsOption>({
});
/** 男女比例 */
const options2 = shallowRef<EChartsOption>({
const options2 = ref<EChartsOption>({
legend: {
top: 'center',
left: '0',
@@ -296,54 +292,18 @@ const options3 = shallowRef<EChartsOption>({
]
});
// ! 年龄分布 -------------------------------------------------------------------------------------
// ! 职业分布比例 -------------------------------------------------------------------------------------
// 真实小区职业分布数据(上班族最多,依次递减)
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 dayX = ref([]);
// 小区真实规模:人员流入 / 流出 数据
// 【全新打乱随机数据】小区人员流入 / 流出
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 inData = ref([]);
const outData = ref([]);
/** 近十天人员流入流出 - 平滑折线图 */
const flowLineOption = shallowRef<EChartsOption>({
const flowLineOption = ref<EChartsOption>({
title: {
text: '近十日人员流动趋势',
left: 0,
@@ -368,7 +328,7 @@ const flowLineOption = shallowRef<EChartsOption>({
},
xAxis: {
type: 'category',
data: dayX,
data: dayX.value,
boundaryGap: false,
axisLine: { lineStyle: { color: '#eee' } }
},
@@ -384,7 +344,7 @@ const flowLineOption = shallowRef<EChartsOption>({
name: '人员流入',
type: 'line',
smooth: true, // 平滑折线 核心
data: inData,
data: inData.value,
symbol: 'circle',
symbolSize: 6,
itemStyle: { color: '#f94144' },
@@ -407,7 +367,7 @@ const flowLineOption = shallowRef<EChartsOption>({
name: '人员流出',
type: 'line',
smooth: true, // 平滑折线 核心
data: outData,
data: outData.value,
symbol: 'circle',
symbolSize: 6,
itemStyle: { color: '#f9c74f' },
@@ -428,11 +388,174 @@ const flowLineOption = shallowRef<EChartsOption>({
}
]
});
function flowLineOptionFun(days: string[], indata: number[], outdata: number[]): EChartsOption {
return {
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: days,
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' }
]
}
}
}
]
};
}
// ! 人员流动情况 -------------------------------------------------------------------------------------
const movein = ref({
totalResident: 0,
totalHouse: 0
});
function init() {
// 获取入住情况
moveinFun();
// 入住类型
moveinUserType();
moveinUserSex();
moveinUserMoveinOut();
}
init();
function querySelect() {
init();
}
function moveinFun() {
user_movein_list({
datetime: date.value
}).then((res) => {
// 获取入住情况
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' } }
];
options.value.series[1].label.formatter = () => {
const total = res.data.totalHouse;
const occupied = res.data.occupiedHouse || 0; // 确保有值
// 计算入住率,防止除以0
const rate = total > 0 ? ((occupied / total) * 100).toFixed(1) : '0.0';
// 返回带换行符的字符串:第一行是百分比,第二行是文字
return `{rate|${rate}%}\n{title|入住率}`;
};
options.value = { ...options.value };
});
}
// 获取住户类型
function moveinUserType() {
get_movein_user_type({
datetime: date.value
}).then((res) => {
console.log(res);
});
}
// 住户性别
function moveinUserSex() {
get_movein_user_sex({
datetime: date.value
}).then((res) => {
options2.value.series[0].data = [
{ value: res.man, name: '男', itemStyle: { color: '#0a74fe' } },
{ value: res.woman, name: '女', itemStyle: { color: '#f74043' } }
];
});
}
// 迁入迁出
function moveinUserMoveinOut() {
// 判断 date.value 是否为今天
if (date.value === '') {
date.value = getLastNDays(7)[0];
}
get_movein_moveout_list({
date: date.value
}).then((res) => {
dayX.value = res.data.map((item) => item.date);
inData.value = res.data.map((item) => item.moveInCount);
outData.value = res.data.map((item) => item.moveOutCount);
flowLineOption.value = flowLineOptionFun(dayX.value, inData.value, outData.value);
});
}
</script>
<style scoped lang="scss">
.personnel {
position: relative;
background: linear-gradient(180deg, #deedff 0%, #f8f9fe 50%);
.el-button {
width: 80px;
@@ -454,6 +577,9 @@ const flowLineOption = shallowRef<EChartsOption>({
font-size: 20px;
padding: 20px;
min-height: 275px;
@media (max-width: 1200px) {
margin-bottom: 20px;
}
.cardbody {
padding: 0 30px;
display: flex;
@@ -469,6 +595,7 @@ const flowLineOption = shallowRef<EChartsOption>({
font-weight: 600;
font-size: 36px;
color: #222222;
width: 100px;
}
}
.echartsbox {