|
@@ -17,21 +17,27 @@
|
|
|
<div class="row1 flex items-center">
|
|
|
<div class="card">
|
|
|
<div class="title">
|
|
|
- <span class="label">大区在服务人数分布及对比</span>
|
|
|
+ <span class="label">大区项目阶段分布及对比</span>
|
|
|
+ </div>
|
|
|
+ <div class="chart-wrap">
|
|
|
+ <my-chart :options="options1"></my-chart>
|
|
|
</div>
|
|
|
- <div class="chart-wrap"> </div>
|
|
|
</div>
|
|
|
<div class="card">
|
|
|
<div class="title">
|
|
|
- <span class="label">设备供应商设备使用占比</span>
|
|
|
+ <span class="label">项目进度阶段总体分布占比</span>
|
|
|
+ </div>
|
|
|
+ <div class="chart-wrap">
|
|
|
+ <my-chart :options="options2"></my-chart>
|
|
|
</div>
|
|
|
- <div class="chart-wrap"> </div>
|
|
|
</div>
|
|
|
<div class="card">
|
|
|
<div class="title">
|
|
|
<span class="label">供应商项目阶段分布及对比</span>
|
|
|
</div>
|
|
|
- <div class="chart-wrap"> </div>
|
|
|
+ <div class="chart-wrap">
|
|
|
+ <my-chart :options="options3"></my-chart>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
</div>
|
|
|
<div class="row2">
|
|
@@ -43,10 +49,10 @@
|
|
|
</template>
|
|
|
|
|
|
<script setup name="DispatchAnalysis">
|
|
|
-import { ref, computed, onMounted } from 'vue';
|
|
|
+import { ref, computed, onMounted, watch } from 'vue';
|
|
|
import { useRequest } from 'vue-request';
|
|
|
-import { createCakePieOption } from '@/utils/chart';
|
|
|
-import { serviceServiceList } from '@/api/report';
|
|
|
+import { createCakePieOption, createPercentBarOption } from '@/utils/chart';
|
|
|
+import { serviceServiceList, projectStageAnalysis } from '@/api/report';
|
|
|
const curTimeRange = ref([]);
|
|
|
const timeParams = computed(() => {
|
|
|
return {
|
|
@@ -62,6 +68,78 @@ const timeChange = (time) => {
|
|
|
res?.length && (serviceId.value = res[0].id);
|
|
|
});
|
|
|
};
|
|
|
+const sortKeys = ['prepare', 'scan', 'evaluation', 'summary', 'finish'];
|
|
|
+const legendData = ['准备', '扫描', '评卷', '收尾', '已完结'];
|
|
|
+const {
|
|
|
+ data: result1,
|
|
|
+ loading: loading1,
|
|
|
+ run: run1,
|
|
|
+} = useRequest(projectStageAnalysis);
|
|
|
+const {
|
|
|
+ data: result2,
|
|
|
+ loading: loading2,
|
|
|
+ run: run2,
|
|
|
+} = useRequest(projectStageAnalysis);
|
|
|
+const {
|
|
|
+ data: result3,
|
|
|
+ loading: loading3,
|
|
|
+ run: run3,
|
|
|
+} = useRequest(projectStageAnalysis);
|
|
|
+watch(serviceId, (serviceId) => {
|
|
|
+ run1({ serviceId, group: 'REGION' });
|
|
|
+ run2({ serviceId, group: 'POPULATION' });
|
|
|
+ run3({ serviceId, group: 'SUPPLIER' });
|
|
|
+});
|
|
|
+const options1 = computed(() => {
|
|
|
+ let res = result1.value || {};
|
|
|
+ let xData = Object.keys(res);
|
|
|
+ let originData = Object.values(res).map((item) => {
|
|
|
+ return sortKeys.map((v) => item[v] || 0);
|
|
|
+ });
|
|
|
+ return createPercentBarOption({
|
|
|
+ xData: xData,
|
|
|
+ originData: originData,
|
|
|
+ legendData: legendData,
|
|
|
+ });
|
|
|
+});
|
|
|
+const options2 = computed(() => {
|
|
|
+ let obj = result2.value?.POPULATION || {};
|
|
|
+ let data = sortKeys.map((prop, index) => {
|
|
|
+ return {
|
|
|
+ name: legendData[index],
|
|
|
+ value: obj[prop] || 0,
|
|
|
+ };
|
|
|
+ });
|
|
|
+ return createCakePieOption(
|
|
|
+ {
|
|
|
+ data: data,
|
|
|
+ radius: [0, 70],
|
|
|
+ center: ['50%', '40%'],
|
|
|
+ seriesName: '总体分布占比',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ legend: {
|
|
|
+ orient: 'horizontal',
|
|
|
+ top: null,
|
|
|
+ right: null,
|
|
|
+ bottom: '0%',
|
|
|
+ left: 'center',
|
|
|
+ },
|
|
|
+ }
|
|
|
+ );
|
|
|
+});
|
|
|
+const options3 = computed(() => {
|
|
|
+ let res = result3.value || {};
|
|
|
+ let xData = Object.keys(res);
|
|
|
+ let originData = Object.values(res).map((item) => {
|
|
|
+ return sortKeys.map((v) => item[v] || 0);
|
|
|
+ });
|
|
|
+ return createPercentBarOption({
|
|
|
+ xData: xData,
|
|
|
+ originData: originData,
|
|
|
+ legendData: legendData,
|
|
|
+ });
|
|
|
+});
|
|
|
</script>
|
|
|
|
|
|
<style lang="less" scoped>
|
|
@@ -109,6 +187,9 @@ const timeChange = (time) => {
|
|
|
// font-weight: bold;
|
|
|
}
|
|
|
}
|
|
|
+ .chart-wrap {
|
|
|
+ height: calc(100% - 36px);
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
}
|