同步6/16
This commit is contained in:
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user