feat: 完成空间管理模块
This commit is contained in:
@@ -7,20 +7,70 @@
|
||||
unmount-on-close
|
||||
@cancel="handleCancel"
|
||||
>
|
||||
项目详情
|
||||
<div class="flex items-center justify-between">
|
||||
<div>
|
||||
<p>{{ detailInfo?.name }}</p>
|
||||
<p class="mt-[10px]">
|
||||
<a-tag :color="getTypeColor(detailInfo?.type)">{{
|
||||
detailInfo?.typeName
|
||||
}}</a-tag>
|
||||
</p>
|
||||
</div>
|
||||
<div class="flex items-center gap-[10px]">
|
||||
<p>{{ detailInfo?.updatedAt }}</p>
|
||||
<div>
|
||||
<a-button @click="handleEdit">
|
||||
<template #icon>
|
||||
<icon-edit />
|
||||
</template>
|
||||
{{ $t('edit') }}
|
||||
</a-button>
|
||||
</div>
|
||||
<!-- <a-button type="primary" @click="handleDelete">删除</a-button> -->
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-[10px] grid grid-cols-3 gap-[10px]">
|
||||
<a-card title="面积信息">
|
||||
<div class="ring-chart-container">
|
||||
<Chart :options="ringChartOption" height="200px" />
|
||||
</div>
|
||||
</a-card>
|
||||
<a-card title="房源统计">
|
||||
<div class="grid grid-cols-3 gap-[10px] text-center">
|
||||
<div>
|
||||
<p class="text-[18px] font-bold">{{ detailInfo?.roomNum }}</p>
|
||||
<p>房源总数</p>
|
||||
</div>
|
||||
<div>
|
||||
<p class="text-[18px] font-bold">{{ detailInfo?.roomsRentNum }}</p>
|
||||
<p>已出租</p>
|
||||
</div>
|
||||
<div>
|
||||
<p class="text-[18px] font-bold">{{
|
||||
detailInfo?.roomsUnRentNum
|
||||
}}</p>
|
||||
<p>空置</p>
|
||||
</div>
|
||||
</div>
|
||||
</a-card>
|
||||
<a-card title="租客信息"></a-card>
|
||||
</div>
|
||||
</a-drawer>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { watch, onMounted } from 'vue';
|
||||
import { watch, onMounted, computed } from 'vue';
|
||||
// import { Message } from '@arco-design/web-vue';
|
||||
// import { projectTypeList } from '@/utils/constant';
|
||||
import { ProjectItem } from '@/types/business';
|
||||
import Chart from '@/components/chart/index.vue';
|
||||
import type { EChartsOption } from 'echarts';
|
||||
|
||||
const props = defineProps<{
|
||||
visible: boolean;
|
||||
projectId: number | null;
|
||||
detailInfo: ProjectItem | null;
|
||||
projectTypeList: any[];
|
||||
}>();
|
||||
const emit = defineEmits<{
|
||||
(e: 'update:visible', val: boolean): void;
|
||||
@@ -36,6 +86,158 @@
|
||||
const handleCancel = () => {
|
||||
emit('update:visible', false);
|
||||
};
|
||||
const handleEdit = () => {
|
||||
emit('update:visible', false);
|
||||
};
|
||||
const getTypeColor = (type: number | undefined) => {
|
||||
if (!type) return '';
|
||||
const color = props.projectTypeList.find((item) => item.id === type)?.color;
|
||||
return color || '';
|
||||
};
|
||||
|
||||
// 格式化面积数值,保留2位小数
|
||||
const formatArea = (value: number): number => {
|
||||
return Math.round(value * 100) / 100;
|
||||
};
|
||||
|
||||
// 格式化面积显示,添加千分位分隔符
|
||||
const formatAreaDisplay = (value: number): string => {
|
||||
if (!value && value !== 0) return '0';
|
||||
return formatArea(value).toLocaleString('zh-CN', {
|
||||
minimumFractionDigits: 2,
|
||||
maximumFractionDigits: 2,
|
||||
});
|
||||
};
|
||||
|
||||
// 计算环形图数据
|
||||
const ringChartData = computed(() => {
|
||||
if (!props.detailInfo) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const { roomArea = 0, rentArea = 0, keepArea = 0 } = props.detailInfo;
|
||||
|
||||
// 确保数值有效
|
||||
const totalArea = Number(roomArea) || 0;
|
||||
const rentedArea = Number(rentArea) || 0;
|
||||
const reservedArea = Number(keepArea) || 0;
|
||||
|
||||
// 可租面积 = 计租面积 - 在租面积 - 保留面积
|
||||
const availableArea = Math.max(0, totalArea - rentedArea - reservedArea);
|
||||
|
||||
// 构建图表数据,如果总面积大于0,显示所有三个部分(即使某些为0)
|
||||
const data: Array<{ name: string; value: number }> = [];
|
||||
|
||||
// 如果总面积大于0,显示所有分类
|
||||
if (totalArea > 0) {
|
||||
// 在租面积
|
||||
data.push({
|
||||
name: '在租面积',
|
||||
value: formatArea(rentedArea),
|
||||
});
|
||||
|
||||
// 保留面积
|
||||
data.push({
|
||||
name: '保留面积',
|
||||
value: formatArea(reservedArea),
|
||||
});
|
||||
|
||||
// 可租面积
|
||||
data.push({
|
||||
name: '可租面积',
|
||||
value: formatArea(availableArea),
|
||||
});
|
||||
} else {
|
||||
// 如果所有数据都为0,显示占位数据
|
||||
data.push({
|
||||
name: '计租面积',
|
||||
value: 0,
|
||||
});
|
||||
}
|
||||
|
||||
// 调试信息(开发时使用)
|
||||
console.log('环形图数据:', {
|
||||
roomArea: totalArea,
|
||||
rentArea: rentedArea,
|
||||
keepArea: reservedArea,
|
||||
availableArea,
|
||||
chartData: data,
|
||||
});
|
||||
|
||||
return data;
|
||||
});
|
||||
|
||||
// 环形图配置
|
||||
const ringChartOption = computed<EChartsOption>(() => {
|
||||
const data = ringChartData.value;
|
||||
|
||||
if (data.length === 0) {
|
||||
return {
|
||||
title: {
|
||||
text: '暂无数据',
|
||||
left: 'center',
|
||||
top: 'middle',
|
||||
textStyle: {
|
||||
color: '#999',
|
||||
fontSize: 14,
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
tooltip: {
|
||||
trigger: 'item',
|
||||
formatter: (params: any) => {
|
||||
const { name, value, percent } = params;
|
||||
return `${name}<br/>${formatAreaDisplay(value)}㎡ (${percent}%)`;
|
||||
},
|
||||
},
|
||||
legend: {
|
||||
orient: 'vertical',
|
||||
left: 'left',
|
||||
top: 'middle',
|
||||
itemWidth: 12,
|
||||
itemHeight: 12,
|
||||
textStyle: {
|
||||
fontSize: 12,
|
||||
},
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: '面积信息',
|
||||
type: 'pie',
|
||||
radius: ['40%', '70%'], // 环形图:内半径40%,外半径70%
|
||||
center: ['60%', '50%'],
|
||||
avoidLabelOverlap: false,
|
||||
itemStyle: {
|
||||
borderRadius: 4,
|
||||
borderColor: '#fff',
|
||||
borderWidth: 2,
|
||||
},
|
||||
label: {
|
||||
show: true,
|
||||
formatter: '{b}\n{d}%',
|
||||
fontSize: 12,
|
||||
},
|
||||
emphasis: {
|
||||
label: {
|
||||
show: true,
|
||||
fontSize: 14,
|
||||
fontWeight: 'bold',
|
||||
},
|
||||
itemStyle: {
|
||||
shadowBlur: 10,
|
||||
shadowOffsetX: 0,
|
||||
shadowColor: 'rgba(0, 0, 0, 0.5)',
|
||||
},
|
||||
},
|
||||
data: data,
|
||||
},
|
||||
],
|
||||
};
|
||||
});
|
||||
|
||||
onMounted(() => {});
|
||||
</script>
|
||||
|
||||
@@ -43,4 +245,33 @@
|
||||
:deep(label.arco-form-item-label) {
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
.ring-chart-container {
|
||||
position: relative;
|
||||
min-height: 300px;
|
||||
|
||||
.area-summary {
|
||||
margin-top: 16px;
|
||||
padding-top: 16px;
|
||||
border-top: 1px solid var(--color-border-2);
|
||||
|
||||
.summary-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 8px;
|
||||
|
||||
.summary-label {
|
||||
color: var(--color-text-2);
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.summary-value {
|
||||
color: var(--color-text-1);
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user