278 lines
6.9 KiB
Vue
278 lines
6.9 KiB
Vue
<template>
|
|
<a-drawer
|
|
:width="1000"
|
|
:visible="visible"
|
|
title="项目详情"
|
|
:footer="false"
|
|
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, 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;
|
|
}>();
|
|
|
|
watch(
|
|
() => props.visible,
|
|
async (val) => {
|
|
console.log(val, 'val');
|
|
},
|
|
{ immediate: true }
|
|
);
|
|
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>
|
|
|
|
<style lang="less" scoped>
|
|
: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>
|