|
|
@@ -3,14 +3,16 @@
|
|
|
<div class="main">
|
|
|
<QueryFilter />
|
|
|
<div class="top-wrapper">
|
|
|
- <MetricCard v-for="item in metricCardList" :key="item.id"
|
|
|
- :title="item.title"
|
|
|
- :text="item.text"
|
|
|
- :showTrendIcon="item.showTrendIcon"
|
|
|
- :trend="item.trend"
|
|
|
- :percent="item.percent"
|
|
|
- :value="item.value"
|
|
|
- :showUnit="item.showUnit"
|
|
|
+ <MetricCard
|
|
|
+ v-for="item in metricCardList"
|
|
|
+ :key="item.id"
|
|
|
+ :title="item.title"
|
|
|
+ :text="item.text"
|
|
|
+ :showTrendIcon="item.showTrendIcon"
|
|
|
+ :trend="item.trend"
|
|
|
+ :percent="item.percent"
|
|
|
+ :value="item.value"
|
|
|
+ :showUnit="item.showUnit"
|
|
|
/>
|
|
|
</div>
|
|
|
<ChartSpecial />
|
|
|
@@ -24,61 +26,132 @@ import QueryFilter from '@/components/stats/QueryFilter.vue';
|
|
|
import ChartSpecial from '@/components/stats/ChartSpecial.vue';
|
|
|
import MonthlyReport from '@/components/stats/MonthlyReport.vue';
|
|
|
import MetricCard from '@/components/stats/MetricCard.vue';
|
|
|
-import { ref, onMounted,computed } from 'vue';
|
|
|
+import { computed, onMounted } from 'vue';
|
|
|
import { useEnterpriseStore } from '@/store/enterprise';
|
|
|
import { useFilterStore } from '@/store/filter';
|
|
|
import { sumFieldToWan, sumFieldsToWan } from '@/utils/areaMath';
|
|
|
import { formatPercent2 } from '@/utils/calculatePercentage';
|
|
|
+import {
|
|
|
+ buildHistoricalSnapshots,
|
|
|
+ computeCertifiedRateFromSnapshots,
|
|
|
+ computeIdleRateFromSnapshots,
|
|
|
+ emptyComparison,
|
|
|
+ formatRatePointChange,
|
|
|
+ formatRelativeChange,
|
|
|
+ getPreviousMonthPeriod,
|
|
|
+ getYearAgoPeriod,
|
|
|
+ sumSnapshotsToWan,
|
|
|
+} from '@/utils/statsComparison';
|
|
|
|
|
|
const filterStore = useFilterStore();
|
|
|
const enterpriseStore = useEnterpriseStore();
|
|
|
|
|
|
-const filteredList = computed(() => {
|
|
|
- return enterpriseStore.filteredByGroup(filterStore.selectGroup)
|
|
|
-})
|
|
|
+const filteredList = computed(() =>
|
|
|
+ enterpriseStore.filteredByGroup(filterStore.selectGroup, filterStore.selectDate)
|
|
|
+);
|
|
|
|
|
|
-//总建筑面积
|
|
|
-const TotalBuildingArea= computed(()=>{
|
|
|
- return sumFieldToWan(filteredList.value, 'c_sjjzmj')
|
|
|
-})
|
|
|
+const previousMonth = computed(() => getPreviousMonthPeriod(filterStore.selectDate));
|
|
|
+const previousYear = computed(() => getYearAgoPeriod(filterStore.selectDate));
|
|
|
|
|
|
-//已出租/在用建筑面积
|
|
|
-const TotalRentedArea = computed(() =>
|
|
|
+const momSnapshots = computed(() =>
|
|
|
+ buildHistoricalSnapshots(filteredList.value, previousMonth.value)
|
|
|
+);
|
|
|
+const yoySnapshots = computed(() =>
|
|
|
+ buildHistoricalSnapshots(filteredList.value, previousYear.value)
|
|
|
+);
|
|
|
+
|
|
|
+const totalBuildingArea = computed(() => sumFieldToWan(filteredList.value, 'c_sjjzmj'));
|
|
|
+
|
|
|
+const totalRentedArea = computed(() =>
|
|
|
sumFieldsToWan(filteredList.value, ['c_zymj', 'c_cjmj', 'c_czmj'])
|
|
|
-)
|
|
|
-
|
|
|
-//已出租/在用建筑面积占比
|
|
|
-const rentPercent = computed(()=>{
|
|
|
- return formatPercent2(TotalRentedArea.value, TotalBuildingArea.value)
|
|
|
-})
|
|
|
-
|
|
|
-//闲置面积
|
|
|
-const idleArea = computed(()=>{
|
|
|
- return sumFieldToWan(filteredList.value, 'c_xzmj')
|
|
|
-})
|
|
|
-
|
|
|
-//闲置率
|
|
|
-const idleRate = computed(()=>{
|
|
|
- return formatPercent2(idleArea.value, TotalBuildingArea.value)
|
|
|
-})
|
|
|
-
|
|
|
-//已办证资产占比
|
|
|
-const certifiedAssetPercent = computed(()=>{
|
|
|
- const sum = filteredList.value.filter(item => item.c_sfblcz === '是').length
|
|
|
- return formatPercent2(sum, filteredList.value.length)
|
|
|
-})
|
|
|
-
|
|
|
-const metricCardList=ref([
|
|
|
- { id:1,title:"建筑总面积",text:"同比去年",percent:"+1.2%",value:TotalBuildingArea},
|
|
|
- { id:2,title:"已出租/在用建筑面积",text:"占总建筑面积",showTrendIcon:false,percent:rentPercent,value:TotalRentedArea},
|
|
|
- { id:3,title:"闲置率", text:"环比上月",trend:"down",percent:"-1.2%",value:idleRate,showUnit:false},
|
|
|
- { id:4,title:"已办证资产占比",text:"环比上月",percent:"+0.5%",value:certifiedAssetPercent,showUnit:false}
|
|
|
-])
|
|
|
-
|
|
|
-onMounted(async() => {
|
|
|
- await enterpriseStore.fetchStatisticsList()
|
|
|
+);
|
|
|
+
|
|
|
+const rentPercent = computed(() =>
|
|
|
+ formatPercent2(totalRentedArea.value, totalBuildingArea.value)
|
|
|
+);
|
|
|
+
|
|
|
+const idleArea = computed(() => sumFieldToWan(filteredList.value, 'c_xzmj'));
|
|
|
+
|
|
|
+const idleRate = computed(() => formatPercent2(idleArea.value, totalBuildingArea.value));
|
|
|
+
|
|
|
+const idleRateNum = computed(() => {
|
|
|
+ const { rateNum } = computeIdleRateFromSnapshots(filteredList.value);
|
|
|
+ return rateNum;
|
|
|
+});
|
|
|
+
|
|
|
+const certifiedAssetPercent = computed(() => {
|
|
|
+ const sum = filteredList.value.filter((item) => item.c_sfblcz === '是').length;
|
|
|
+ return formatPercent2(sum, filteredList.value.length);
|
|
|
});
|
|
|
|
|
|
+const certifiedRateNum = computed(() => {
|
|
|
+ const { rateNum } = computeCertifiedRateFromSnapshots(filteredList.value);
|
|
|
+ return rateNum;
|
|
|
+});
|
|
|
+
|
|
|
+const buildingAreaYoY = computed(() => {
|
|
|
+ if (!filterStore.selectDate) return emptyComparison();
|
|
|
+ const previous = sumSnapshotsToWan(yoySnapshots.value, 'c_sjjzmj');
|
|
|
+ return formatRelativeChange(totalBuildingArea.value, previous);
|
|
|
+});
|
|
|
+
|
|
|
+const idleRateMoM = computed(() => {
|
|
|
+ if (!filterStore.selectDate) return emptyComparison();
|
|
|
+ const { rateNum: previous } = computeIdleRateFromSnapshots(momSnapshots.value);
|
|
|
+ return formatRatePointChange(idleRateNum.value, previous);
|
|
|
+});
|
|
|
+
|
|
|
+const certifiedRateMoM = computed(() => {
|
|
|
+ if (!filterStore.selectDate) return emptyComparison();
|
|
|
+ const { rateNum: previous } = computeCertifiedRateFromSnapshots(momSnapshots.value);
|
|
|
+ return formatRatePointChange(certifiedRateNum.value, previous);
|
|
|
+});
|
|
|
+
|
|
|
+const metricCardList = computed(() => [
|
|
|
+ {
|
|
|
+ id: 1,
|
|
|
+ title: '建筑总面积',
|
|
|
+ text: '同比去年',
|
|
|
+ percent: buildingAreaYoY.value.text,
|
|
|
+ trend: buildingAreaYoY.value.trend,
|
|
|
+ value: totalBuildingArea.value,
|
|
|
+ showTrendIcon: true,
|
|
|
+ showUnit: true,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ id: 2,
|
|
|
+ title: '已出租/在用建筑面积',
|
|
|
+ text: '占总建筑面积',
|
|
|
+ showTrendIcon: false,
|
|
|
+ percent: rentPercent.value,
|
|
|
+ value: totalRentedArea.value,
|
|
|
+ showUnit: true,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ id: 3,
|
|
|
+ title: '闲置率',
|
|
|
+ text: '环比上月',
|
|
|
+ trend: idleRateMoM.value.trend,
|
|
|
+ percent: idleRateMoM.value.text,
|
|
|
+ value: idleRate.value,
|
|
|
+ showTrendIcon: true,
|
|
|
+ showUnit: false,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ id: 4,
|
|
|
+ title: '已办证资产占比',
|
|
|
+ text: '环比上月',
|
|
|
+ trend: certifiedRateMoM.value.trend,
|
|
|
+ percent: certifiedRateMoM.value.text,
|
|
|
+ value: certifiedAssetPercent.value,
|
|
|
+ showTrendIcon: true,
|
|
|
+ showUnit: false,
|
|
|
+ },
|
|
|
+]);
|
|
|
+
|
|
|
+onMounted(async () => {
|
|
|
+ await enterpriseStore.fetchStatisticsList();
|
|
|
+});
|
|
|
</script>
|
|
|
|
|
|
<style scoped>
|