|
@@ -50,6 +50,13 @@
|
|
|
<div class="card" style="height: calc((100% - 206px) * 3 / 7)">
|
|
|
<div class="title">
|
|
|
<span class="label">人力供应商项目角色人员分布</span>
|
|
|
+ <t-select
|
|
|
+ v-model="supplierId"
|
|
|
+ :options="supplierOptions"
|
|
|
+ size="small"
|
|
|
+ style="width: 150px"
|
|
|
+ >
|
|
|
+ </t-select>
|
|
|
</div>
|
|
|
<div class="box3 flex">
|
|
|
<div style="width: 40%; height: 100%">
|
|
@@ -81,19 +88,19 @@
|
|
|
<div class="charts-box">
|
|
|
<div class="chart-item">
|
|
|
<div class="chart-wrap">
|
|
|
- <my-chart :options="options4"></my-chart>
|
|
|
+ <my-chart :options="options41"></my-chart>
|
|
|
</div>
|
|
|
<div class="title-wrap">实施工程师</div>
|
|
|
</div>
|
|
|
<div class="chart-item">
|
|
|
<div class="chart-wrap">
|
|
|
- <my-chart :options="options5"></my-chart>
|
|
|
+ <my-chart :options="options42"></my-chart>
|
|
|
</div>
|
|
|
<div class="title-wrap">区域协调人</div>
|
|
|
</div>
|
|
|
<div class="chart-item">
|
|
|
<div class="chart-wrap">
|
|
|
- <my-chart :options="options6"></my-chart>
|
|
|
+ <my-chart :options="options43"></my-chart>
|
|
|
</div>
|
|
|
<div class="title-wrap">助理工程师</div>
|
|
|
</div>
|
|
@@ -160,7 +167,17 @@ import {
|
|
|
createStackingBarOption,
|
|
|
} from '@/utils/chart';
|
|
|
import { useRequest } from 'vue-request';
|
|
|
-import { serviceOverviewAnalysis } from '@/api/report';
|
|
|
+import {
|
|
|
+ serviceOverviewAnalysis,
|
|
|
+ supplierOverviewAnalysis,
|
|
|
+ supplierRoleAnalysis,
|
|
|
+ projectAllocateProcessAnalysis,
|
|
|
+ personAllocateProcessAnalysis,
|
|
|
+ projectRoleAnalysis,
|
|
|
+ getRegionList,
|
|
|
+ deviceUseAnalysis,
|
|
|
+ personNumAnalysis,
|
|
|
+} from '@/api/report';
|
|
|
const curTimeRange = ref([]);
|
|
|
const timeParams = computed(() => {
|
|
|
return {
|
|
@@ -173,10 +190,80 @@ const {
|
|
|
data: result1,
|
|
|
loading: loading1,
|
|
|
run: run1,
|
|
|
-} = useRequest(serviceOverviewAnalysis);
|
|
|
+} = useRequest(serviceOverviewAnalysis); //服务单元概览
|
|
|
+
|
|
|
+const {
|
|
|
+ data: result2,
|
|
|
+ loading: loading2,
|
|
|
+ runAsync: run2,
|
|
|
+} = useRequest(supplierOverviewAnalysis); //人力供应商项目数量分布及占比
|
|
|
+
|
|
|
+const {
|
|
|
+ data: result3,
|
|
|
+ loading: loading3,
|
|
|
+ run: run3,
|
|
|
+} = useRequest(supplierRoleAnalysis); //人力供应商项目角色人员分布
|
|
|
+
|
|
|
+const { data: regionList, runAsync: runGetRegionList } =
|
|
|
+ useRequest(getRegionList); //获取大区列表
|
|
|
+
|
|
|
+const {
|
|
|
+ data: result4,
|
|
|
+ loading: loading4,
|
|
|
+ runAsync: run4,
|
|
|
+} = useRequest(projectRoleAnalysis); //项目角色待调配配额盘点
|
|
|
+
|
|
|
+const {
|
|
|
+ data: result5,
|
|
|
+ loading: loading5,
|
|
|
+ run: run5,
|
|
|
+} = useRequest(projectAllocateProcessAnalysis); //项目调配完成进度
|
|
|
+
|
|
|
+const {
|
|
|
+ data: result6,
|
|
|
+ loading: loading6,
|
|
|
+ run: run6,
|
|
|
+} = useRequest(personAllocateProcessAnalysis); //人员配额完成进度
|
|
|
+
|
|
|
+const {
|
|
|
+ data: result7,
|
|
|
+ loading: loading7,
|
|
|
+ run: run7,
|
|
|
+} = useRequest(deviceUseAnalysis); //设备供应商设备使用占比
|
|
|
+
|
|
|
+const {
|
|
|
+ data: result8,
|
|
|
+ loading: loading8,
|
|
|
+ run: run8,
|
|
|
+} = useRequest(personNumAnalysis); //大区在服务人数分布及对比
|
|
|
|
|
|
watch(serviceId, (serviceUnitId) => {
|
|
|
run1({ serviceUnitId });
|
|
|
+ run2({ serviceUnitId }).then((res) => {
|
|
|
+ if (!supplierId.value) {
|
|
|
+ //赋值,默认选择第一个供应商
|
|
|
+ //todo ...
|
|
|
+ }
|
|
|
+ });
|
|
|
+ run5({ serviceUnitId });
|
|
|
+ run6({ serviceUnitId });
|
|
|
+ run7({ serviceUnitId });
|
|
|
+ run8({ serviceUnitId });
|
|
|
+});
|
|
|
+
|
|
|
+const supplierId = ref('');
|
|
|
+const supplierOptions = computed(() => {
|
|
|
+ //与result2相关,转换数据即可
|
|
|
+ return [];
|
|
|
+});
|
|
|
+const regionId = ref('');
|
|
|
+const regionOptions = computed(() => {
|
|
|
+ //与result4相关,转换数据即可
|
|
|
+ return [];
|
|
|
+});
|
|
|
+watch('supplierId', (supplierId) => {
|
|
|
+ run3({ serviceUnitId: serviceId.value, supplierId });
|
|
|
+ runGetRegionList({ serviceUnitId: serviceId.value, supplierId });
|
|
|
});
|
|
|
|
|
|
const options1 = computed(() => {
|
|
@@ -241,69 +328,81 @@ const options3 = createCakePieOption(
|
|
|
}
|
|
|
);
|
|
|
|
|
|
-const options4 = createWaterBallOption({
|
|
|
+const options41 = createWaterBallOption({
|
|
|
data: 65 / 100,
|
|
|
title: '剩130配额',
|
|
|
radius: '80%',
|
|
|
});
|
|
|
-const options5 = createWaterBallOption({
|
|
|
+const options42 = createWaterBallOption({
|
|
|
data: 35 / 100,
|
|
|
title: '剩34配额',
|
|
|
radius: '80%',
|
|
|
color: '35, 195, 67',
|
|
|
});
|
|
|
-const options6 = createWaterBallOption({
|
|
|
+const options43 = createWaterBallOption({
|
|
|
data: 55 / 100,
|
|
|
title: '剩14配额',
|
|
|
radius: '80%',
|
|
|
color: '255, 154, 46',
|
|
|
});
|
|
|
-const options7 = createCakePieOption(
|
|
|
- {
|
|
|
- data: [
|
|
|
- { name: 'AAAA', value: 32 },
|
|
|
- { name: 'BBBB', value: 39 },
|
|
|
- { name: 'CCCC', value: 69 },
|
|
|
- { name: 'DDDD', value: 19 },
|
|
|
- { name: 'EEEE', value: 69 },
|
|
|
- { name: 'FFFF', value: 9 },
|
|
|
- ],
|
|
|
- radius: [0, 60],
|
|
|
- center: ['50%', '30%'],
|
|
|
- seriesName: '设备使用占比',
|
|
|
- },
|
|
|
- {
|
|
|
- legend: {
|
|
|
- // type: 'scroll',
|
|
|
- orient: 'horizontal',
|
|
|
- top: null,
|
|
|
- right: null,
|
|
|
- bottom: '0%',
|
|
|
- left: 'center',
|
|
|
+const options7 = computed(() => {
|
|
|
+ return createCakePieOption(
|
|
|
+ {
|
|
|
+ data: (result7.value || []).map((item) => ({
|
|
|
+ name: item.nam,
|
|
|
+ value: item.outs,
|
|
|
+ })),
|
|
|
+ radius: [0, 60],
|
|
|
+ center: ['50%', '30%'],
|
|
|
+ seriesName: '设备使用占比',
|
|
|
},
|
|
|
- }
|
|
|
-);
|
|
|
+ {
|
|
|
+ legend: {
|
|
|
+ // type: 'scroll',
|
|
|
+ orient: 'horizontal',
|
|
|
+ top: null,
|
|
|
+ right: null,
|
|
|
+ bottom: '0%',
|
|
|
+ left: 'center',
|
|
|
+ },
|
|
|
+ }
|
|
|
+ );
|
|
|
+});
|
|
|
|
|
|
-const options8 = createStackingBarOption(
|
|
|
- {
|
|
|
- xData: [
|
|
|
- '北京',
|
|
|
- '上海',
|
|
|
- '武汉',
|
|
|
- '天津',
|
|
|
- '广州',
|
|
|
- '南京',
|
|
|
- '长沙',
|
|
|
- '青海',
|
|
|
- '福建',
|
|
|
- ],
|
|
|
- seriesData: [
|
|
|
- { name: '阳光雨露', data: [322.1, 421.4, 100.9, 662, 200.03] },
|
|
|
- { name: '软通智服', data: [990.84, 400, 343.5, 200.3, 552] },
|
|
|
- ],
|
|
|
- },
|
|
|
- {}
|
|
|
-);
|
|
|
+const options8 = computed(() => {
|
|
|
+ let res = result8.value || [];
|
|
|
+ let xData = Array.from(
|
|
|
+ new Set((result8.value || []).map((item) => item.region_name))
|
|
|
+ );
|
|
|
+ let names = Array.from(
|
|
|
+ new Set((result8.value || []).map((item) => item.name))
|
|
|
+ );
|
|
|
+ let sData = [];
|
|
|
+ for (let i = 0; i < names.length; i++) {
|
|
|
+ let data = [];
|
|
|
+ for (let j = 0; j < xData.length; j++) {
|
|
|
+ let find = res.find(
|
|
|
+ (v) => v.name == names[i] && v.region_name == xData[j]
|
|
|
+ );
|
|
|
+ data.push(find?.count || 0);
|
|
|
+ }
|
|
|
+ sData.push({
|
|
|
+ name: names[i],
|
|
|
+ data: data,
|
|
|
+ });
|
|
|
+ }
|
|
|
+ return createStackingBarOption(
|
|
|
+ {
|
|
|
+ xData: xData,
|
|
|
+ // seriesData: [
|
|
|
+ // { name: '阳光雨露', data: [322.1, 421.4, 100.9, 662, 200.03] },
|
|
|
+ // { name: '软通智服', data: [990.84, 400, 343.5, 200.3, 552] },
|
|
|
+ // ],
|
|
|
+ seriesData: sData,
|
|
|
+ },
|
|
|
+ {}
|
|
|
+ );
|
|
|
+});
|
|
|
</script>
|
|
|
|
|
|
<style lang="less" scoped>
|