|
@@ -1,573 +1,310 @@
|
|
|
<template>
|
|
|
<div class="sop-analysis">
|
|
|
- <report-header
|
|
|
- title="SOP预警监控"
|
|
|
- v-model:dateRange="curTimeRange"
|
|
|
- @timeChange="timeChange"
|
|
|
- >
|
|
|
- <t-select
|
|
|
- style="width: 200px"
|
|
|
- :options="serviceOptions"
|
|
|
+ <report-header title="服务单元分析" hideTimePicker>
|
|
|
+ <select-service-unit
|
|
|
v-model="serviceId"
|
|
|
- :keys="{ label: 'name', value: 'id' }"
|
|
|
- filterable
|
|
|
- ></t-select>
|
|
|
+ clearable
|
|
|
+ defaultSelect
|
|
|
+ style="width: 220px"
|
|
|
+ ></select-service-unit>
|
|
|
</report-header>
|
|
|
<div class="page-main">
|
|
|
<div class="scroll-content">
|
|
|
<div class="col1">
|
|
|
- <div class="card">
|
|
|
- <div class="title">
|
|
|
- <t-select
|
|
|
- v-model="sort1"
|
|
|
- style="width: calc(100% - 50px)"
|
|
|
- @change="changeSort('CRM', 1)"
|
|
|
+ <div class="module-title">按大区预警统计</div>
|
|
|
+ <t-table
|
|
|
+ size="small"
|
|
|
+ row-key="leadId"
|
|
|
+ :columns="columns1"
|
|
|
+ :data="tableData1 || []"
|
|
|
+ bordered
|
|
|
+ :loading="loading1"
|
|
|
+ >
|
|
|
+ <template #leadName="{ col, row }">
|
|
|
+ <span v-if="row[col.colKey]">{{ row[col.colKey] }}</span>
|
|
|
+ <span v-else style="font-weight: bold">合计</span>
|
|
|
+ </template>
|
|
|
+ <template #total="{ col, row }">
|
|
|
+ <t-link
|
|
|
+ theme="primary"
|
|
|
+ @click="
|
|
|
+ searchByX({
|
|
|
+ leadId: row.leadId,
|
|
|
+ fieldObj: '',
|
|
|
+ })
|
|
|
+ "
|
|
|
+ >{{ row.total }}</t-link
|
|
|
+ >
|
|
|
+ </template>
|
|
|
+ <template #scanStartTimeNum="{ col, row }">
|
|
|
+ <t-link
|
|
|
+ theme="primary"
|
|
|
+ @click="
|
|
|
+ searchByX({
|
|
|
+ fieldObj: 'scan_start_time',
|
|
|
+ leadId: row.leadId,
|
|
|
+ })
|
|
|
+ "
|
|
|
+ >{{ row.scanStartTimeNum }}({{
|
|
|
+ row.scanStarTimeRatio
|
|
|
+ }})</t-link
|
|
|
+ >
|
|
|
+ </template>
|
|
|
+ <template #scanEndTimeNum="{ col, row }">
|
|
|
+ <t-link
|
|
|
+ theme="primary"
|
|
|
+ @click="
|
|
|
+ searchByX({
|
|
|
+ fieldObj: 'scan_end_time',
|
|
|
+ leadId: row.leadId,
|
|
|
+ })
|
|
|
+ "
|
|
|
+ >{{ row.scanEndTimeNum }}({{ row.scanEndTimeRatio }})</t-link
|
|
|
+ >
|
|
|
+ </template>
|
|
|
+ <template #markStartTimeNum="{ col, row }">
|
|
|
+ <t-link
|
|
|
+ theme="primary"
|
|
|
+ @click="
|
|
|
+ searchByX({
|
|
|
+ fieldObj: 'mark_start_time',
|
|
|
+ leadId: row.leadId,
|
|
|
+ })
|
|
|
+ "
|
|
|
+ >{{ row.markStartTimeNum }}({{
|
|
|
+ row.markStartTimeRatio
|
|
|
+ }})</t-link
|
|
|
>
|
|
|
- <t-option
|
|
|
- value="PENDING"
|
|
|
- label="项目预警待处理TOP10"
|
|
|
- ></t-option>
|
|
|
- <t-option
|
|
|
- value="SLOWEST"
|
|
|
- label="项目预警处理最慢TOP10"
|
|
|
- ></t-option>
|
|
|
- <t-option
|
|
|
- value="FASTEST"
|
|
|
- label="项目预警处理最快TOP10"
|
|
|
- ></t-option>
|
|
|
- </t-select>
|
|
|
- <FullscreenIcon
|
|
|
- class="cursor-pointer"
|
|
|
- @click="chart1?.maximize"
|
|
|
- color="#595959"
|
|
|
- />
|
|
|
- </div>
|
|
|
- <div class="chart-wrap">
|
|
|
- <table-loop
|
|
|
- ref="chart1"
|
|
|
- :data="tableDataHandle(result1)"
|
|
|
- :columns="tableColumns1"
|
|
|
- :title="
|
|
|
- sort1 == 'PENDING'
|
|
|
- ? '项目预警待处理TOP10'
|
|
|
- : sort1 == 'SLOWEST'
|
|
|
- ? '项目预警处理最慢TOP10'
|
|
|
- : '项目预警处理最快TOP10'
|
|
|
+ </template>
|
|
|
+ <template #markEndTimeNum="{ col, row }">
|
|
|
+ <t-link
|
|
|
+ theme="primary"
|
|
|
+ @click="
|
|
|
+ searchByX({
|
|
|
+ fieldObj: 'mark_end_time',
|
|
|
+ leadId: row.leadId,
|
|
|
+ })
|
|
|
"
|
|
|
- ></table-loop>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- <div class="card">
|
|
|
- <div class="title">
|
|
|
- <t-select
|
|
|
- v-model="sort2"
|
|
|
- style="width: calc(100% - 50px)"
|
|
|
- @change="changeSort('REGION', 2)"
|
|
|
+ >{{ row.markEndTimeNum }}({{ row.markEndTimeRatio }})</t-link
|
|
|
>
|
|
|
- <t-option
|
|
|
- value="PENDING"
|
|
|
- label="大区预警待处理TOP10"
|
|
|
- ></t-option>
|
|
|
- <t-option
|
|
|
- value="SLOWEST"
|
|
|
- label="大区预警处理最慢TOP10"
|
|
|
- ></t-option>
|
|
|
- <t-option
|
|
|
- value="FASTEST"
|
|
|
- label="大区预警处理最快TOP10"
|
|
|
- ></t-option>
|
|
|
- </t-select>
|
|
|
- <FullscreenIcon
|
|
|
- class="cursor-pointer"
|
|
|
- @click="chart2?.maximize"
|
|
|
- color="#595959"
|
|
|
- />
|
|
|
- </div>
|
|
|
- <div class="chart-wrap">
|
|
|
- <table-loop
|
|
|
- ref="chart2"
|
|
|
- :data="tableDataHandle(result2)"
|
|
|
- :columns="tableColumns2"
|
|
|
- :title="
|
|
|
- sort2 == 'PENDING'
|
|
|
- ? '大区预警待处理TOP10'
|
|
|
- : sort2 == 'SLOWEST'
|
|
|
- ? '大区预警处理最慢TOP10'
|
|
|
- : '大区预警处理最快TOP10'
|
|
|
+ </template>
|
|
|
+ </t-table>
|
|
|
+ <div class="module-title m-t-15px">按人力商进度统计</div>
|
|
|
+ <t-table
|
|
|
+ size="small"
|
|
|
+ row-key="leadId"
|
|
|
+ :columns="columns2"
|
|
|
+ :data="tableData2 || []"
|
|
|
+ bordered
|
|
|
+ :loading="loading2"
|
|
|
+ >
|
|
|
+ <template #supplierName="{ col, row }">
|
|
|
+ <span v-if="row[col.colKey]">{{ row[col.colKey] }}</span>
|
|
|
+ <span v-else style="font-weight: bold">合计</span>
|
|
|
+ </template>
|
|
|
+ <template #total="{ col, row }">
|
|
|
+ <t-link
|
|
|
+ theme="primary"
|
|
|
+ @click="
|
|
|
+ searchByX({
|
|
|
+ supplierId: row.supplierId,
|
|
|
+ fieldObj: '',
|
|
|
+ })
|
|
|
"
|
|
|
- ></table-loop>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- <div class="card">
|
|
|
- <div class="title">
|
|
|
- <t-select
|
|
|
- v-model="sort3"
|
|
|
- style="width: calc(100% - 50px)"
|
|
|
- @change="changeSort('SUPPLIER', 3)"
|
|
|
+ >{{ row.total }}</t-link
|
|
|
>
|
|
|
- <t-option
|
|
|
- value="PENDING"
|
|
|
- label="供应商预警待处理TOP10"
|
|
|
- ></t-option>
|
|
|
- <t-option
|
|
|
- value="SLOWEST"
|
|
|
- label="供应商预警处理最慢TOP10"
|
|
|
- ></t-option>
|
|
|
- <t-option
|
|
|
- value="FASTEST"
|
|
|
- label="供应商预警处理最快TOP10"
|
|
|
- ></t-option>
|
|
|
- </t-select>
|
|
|
- <FullscreenIcon
|
|
|
- class="cursor-pointer"
|
|
|
- @click="chart3?.maximize"
|
|
|
- color="#595959"
|
|
|
- />
|
|
|
- </div>
|
|
|
- <div class="chart-wrap">
|
|
|
- <table-loop
|
|
|
- ref="chart3"
|
|
|
- :data="tableDataHandle(result3)"
|
|
|
- :columns="tableColumns3"
|
|
|
- :title="
|
|
|
- sort3 == 'PENDING'
|
|
|
- ? '供应商预警待处理TOP10'
|
|
|
- : sort3 == 'SLOWEST'
|
|
|
- ? '供应商预警处理最慢TOP10'
|
|
|
- : '供应商预警处理最快TOP10'
|
|
|
+ </template>
|
|
|
+ <template #scanStartTimeNum="{ col, row }">
|
|
|
+ <t-link
|
|
|
+ theme="primary"
|
|
|
+ @click="
|
|
|
+ searchByX({
|
|
|
+ fieldObj: 'scan_start_time',
|
|
|
+ supplierId: row.supplierId,
|
|
|
+ })
|
|
|
"
|
|
|
- ></table-loop>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
+ >{{ row.scanStartTimeNum }}({{
|
|
|
+ row.scanStarTimeRatio
|
|
|
+ }})</t-link
|
|
|
+ >
|
|
|
+ </template>
|
|
|
+ <template #scanEndTimeNum="{ col, row }">
|
|
|
+ <t-link
|
|
|
+ theme="primary"
|
|
|
+ @click="
|
|
|
+ searchByX({
|
|
|
+ fieldObj: 'scan_end_time',
|
|
|
+ supplierId: row.supplierId,
|
|
|
+ })
|
|
|
+ "
|
|
|
+ >{{ row.scanEndTimeNum }}({{ row.scanEndTimeRatio }})</t-link
|
|
|
+ >
|
|
|
+ </template>
|
|
|
+ <template #markStartTimeNum="{ col, row }">
|
|
|
+ <t-link
|
|
|
+ theme="primary"
|
|
|
+ @click="
|
|
|
+ searchByX({
|
|
|
+ fieldObj: 'mark_start_time',
|
|
|
+ supplierId: row.supplierId,
|
|
|
+ })
|
|
|
+ "
|
|
|
+ >{{ row.markStartTimeNum }}({{
|
|
|
+ row.markStartTimeRatio
|
|
|
+ }})</t-link
|
|
|
+ >
|
|
|
+ </template>
|
|
|
+ <template #markEndTimeNum="{ col, row }">
|
|
|
+ <t-link
|
|
|
+ theme="primary"
|
|
|
+ @click="
|
|
|
+ searchByX({
|
|
|
+ fieldObj: 'mark_end_time',
|
|
|
+ supplierId: row.supplierId,
|
|
|
+ })
|
|
|
+ "
|
|
|
+ >{{ row.markEndTimeNum }}({{ row.markEndTimeRatio }})</t-link
|
|
|
+ >
|
|
|
+ </template>
|
|
|
+ </t-table>
|
|
|
</div>
|
|
|
<div class="col2">
|
|
|
- <div class="card">
|
|
|
- <div class="tab-box">
|
|
|
- <div
|
|
|
- class="tab"
|
|
|
- @click="centerGroup = 'REGION'"
|
|
|
- :class="{ active: centerGroup === 'REGION' }"
|
|
|
- >按大区</div
|
|
|
+ <div class="module-title">按区域协调人预警统计</div>
|
|
|
+
|
|
|
+ <t-table
|
|
|
+ size="small"
|
|
|
+ row-key="leadId"
|
|
|
+ :columns="columns3"
|
|
|
+ :data="tableData3 || []"
|
|
|
+ bordered
|
|
|
+ :loading="loading3"
|
|
|
+ >
|
|
|
+ <template #coordinatorName="{ col, row }">
|
|
|
+ <span v-if="row[col.colKey]">{{ row[col.colKey] }}</span>
|
|
|
+ <span v-else style="font-weight: bold">合计</span>
|
|
|
+ </template>
|
|
|
+ <template #total="{ col, row }">
|
|
|
+ <t-link
|
|
|
+ theme="primary"
|
|
|
+ @click="
|
|
|
+ searchByX({ coordinatorId: row.coordinatorId, fieldObj: '' })
|
|
|
+ "
|
|
|
+ >{{ row.total }}</t-link
|
|
|
>
|
|
|
- <div
|
|
|
- class="tab"
|
|
|
- @click="centerGroup = 'SUPPLIER'"
|
|
|
- :class="{ active: centerGroup === 'SUPPLIER' }"
|
|
|
- >按人力供应商</div
|
|
|
+ </template>
|
|
|
+ <template #scanStartTimeNum="{ col, row }">
|
|
|
+ <t-link
|
|
|
+ theme="primary"
|
|
|
+ @click="
|
|
|
+ searchByX({
|
|
|
+ fieldObj: 'scan_start_time',
|
|
|
+ coordinatorId: row.coordinatorId,
|
|
|
+ })
|
|
|
+ "
|
|
|
+ >{{ row.scanStartTimeNum }}({{
|
|
|
+ row.scanStarTimeRatio
|
|
|
+ }})</t-link
|
|
|
>
|
|
|
- </div>
|
|
|
- <div class="clear-both"></div>
|
|
|
- <div class="list-wrap" v-if="result7?.length">
|
|
|
- <div
|
|
|
- class="list-item"
|
|
|
- v-for="(item, index) in result7"
|
|
|
- :key="index"
|
|
|
+ </template>
|
|
|
+ <template #scanEndTimeNum="{ col, row }">
|
|
|
+ <t-link
|
|
|
+ theme="primary"
|
|
|
+ @click="
|
|
|
+ searchByX({
|
|
|
+ fieldObj: 'scan_end_time',
|
|
|
+ coordinatorId: row.coordinatorId,
|
|
|
+ })
|
|
|
+ "
|
|
|
+ >{{ row.scanEndTimeNum }}({{ row.scanEndTimeRatio }})</t-link
|
|
|
>
|
|
|
- <div class="item-head">
|
|
|
- {{
|
|
|
- centerGroup === 'SUPPLIER'
|
|
|
- ? item.supplierName
|
|
|
- : item.regionName
|
|
|
- }}
|
|
|
- </div>
|
|
|
- <div class="item-body">
|
|
|
- <div class="row1">
|
|
|
- <div class="grid-item">
|
|
|
- <div class="label">派单数</div>
|
|
|
- <p>{{ item.crmNum }}</p>
|
|
|
- </div>
|
|
|
- <div class="grid-item">
|
|
|
- <div class="label">完成进度(%)</div>
|
|
|
- <p>{{ division(item.finishCrmNum, item.crmNum) }}</p>
|
|
|
- </div>
|
|
|
- <div class="grid-item">
|
|
|
- <div class="label">平均处理时限(小时)</div>
|
|
|
- <p class="red">{{ (item.avgMinutes / 60).toFixed(2) }}</p>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- <div class="row2">
|
|
|
- <div class="label">预警处理进度</div>
|
|
|
- <div class="process-box">
|
|
|
- <div class="grid-item">
|
|
|
- <span>总体</span>
|
|
|
- <div class="bar-box">
|
|
|
- <div
|
|
|
- class="bar"
|
|
|
- :style="{
|
|
|
- width:
|
|
|
- division(
|
|
|
- item.finishViolationNum + item.finishDelayNum,
|
|
|
- item.violationNum + item.delayNum
|
|
|
- ) + '%',
|
|
|
- }"
|
|
|
- ></div>
|
|
|
- </div>
|
|
|
- <span>{{ item.violationNum + item.delayNum }}</span>
|
|
|
- </div>
|
|
|
- <div class="grid-item">
|
|
|
- <span>违规</span>
|
|
|
- <div class="bar-box">
|
|
|
- <div
|
|
|
- class="bar"
|
|
|
- :style="{
|
|
|
- width:
|
|
|
- division(
|
|
|
- item.finishViolationNum,
|
|
|
- item.violationNum
|
|
|
- ) + '%',
|
|
|
- }"
|
|
|
- ></div>
|
|
|
- </div>
|
|
|
- <span>{{ item.violationNum }}</span>
|
|
|
- </div>
|
|
|
- <div class="grid-item">
|
|
|
- <span>延期</span>
|
|
|
- <div class="bar-box">
|
|
|
- <div
|
|
|
- class="bar"
|
|
|
- :style="{
|
|
|
- width:
|
|
|
- division(item.finishDelayNum, item.delayNum) +
|
|
|
- '%',
|
|
|
- }"
|
|
|
- ></div>
|
|
|
- </div>
|
|
|
- <span>{{ item.delayNum }}</span>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- <div class="none-data" v-else>暂无数据</div>
|
|
|
- </div>
|
|
|
- <div class="card">
|
|
|
- <div class="title">
|
|
|
- <span class="label">供应商预警均值走势</span>
|
|
|
- </div>
|
|
|
- <div class="chart-wrap">
|
|
|
- <my-chart :options="options8"></my-chart>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- <div class="col3">
|
|
|
- <div class="card">
|
|
|
- <div class="title">
|
|
|
- <span class="label">项目考勤异常TOP10</span>
|
|
|
- <FullscreenIcon
|
|
|
- class="cursor-pointer"
|
|
|
- @click="chart4?.maximize"
|
|
|
- color="#595959"
|
|
|
- />
|
|
|
- </div>
|
|
|
- <div class="chart-wrap">
|
|
|
- <table-loop
|
|
|
- ref="chart4"
|
|
|
- :data="tableDataHandle(result4)"
|
|
|
- :columns="tableColumns4"
|
|
|
- title="项目考勤异常TOP10"
|
|
|
- ></table-loop>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- <div class="card">
|
|
|
- <div class="title">
|
|
|
- <span class="label">大区考勤异常TOP10</span>
|
|
|
- <FullscreenIcon
|
|
|
- class="cursor-pointer"
|
|
|
- @click="chart5?.maximize"
|
|
|
- color="#595959"
|
|
|
- />
|
|
|
- </div>
|
|
|
- <div class="chart-wrap">
|
|
|
- <table-loop
|
|
|
- ref="chart5"
|
|
|
- :data="tableDataHandle(result5)"
|
|
|
- :columns="tableColumns5"
|
|
|
- title="大区考勤异常TOP10"
|
|
|
- ></table-loop>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- <div class="card">
|
|
|
- <div class="title">
|
|
|
- <span class="label">供应商考勤异常TOP5</span>
|
|
|
- <FullscreenIcon
|
|
|
- class="cursor-pointer"
|
|
|
- @click="chart6?.maximize"
|
|
|
- color="#595959"
|
|
|
- />
|
|
|
- </div>
|
|
|
- <div class="chart-wrap">
|
|
|
- <table-loop
|
|
|
- ref="chart6"
|
|
|
- :data="tableDataHandle(result6)"
|
|
|
- :columns="tableColumns6"
|
|
|
- title="供应商考勤异常TOP5"
|
|
|
- ></table-loop>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
+ </template>
|
|
|
+ <template #markStartTimeNum="{ col, row }">
|
|
|
+ <t-link
|
|
|
+ theme="primary"
|
|
|
+ @click="
|
|
|
+ searchByX({
|
|
|
+ fieldObj: 'mark_start_time',
|
|
|
+ coordinatorId: row.coordinatorId,
|
|
|
+ })
|
|
|
+ "
|
|
|
+ >{{ row.markStartTimeNum }}({{
|
|
|
+ row.markStartTimeRatio
|
|
|
+ }})</t-link
|
|
|
+ >
|
|
|
+ </template>
|
|
|
+ <template #markEndTimeNum="{ col, row }">
|
|
|
+ <t-link
|
|
|
+ theme="primary"
|
|
|
+ @click="
|
|
|
+ searchByX({
|
|
|
+ fieldObj: 'mark_end_time',
|
|
|
+ coordinatorId: row.coordinatorId,
|
|
|
+ })
|
|
|
+ "
|
|
|
+ >{{ row.markEndTimeNum }}({{ row.markEndTimeRatio }})</t-link
|
|
|
+ >
|
|
|
+ </template>
|
|
|
+ </t-table>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
+ <DetailDrawer
|
|
|
+ v-model="showDetailDrawer"
|
|
|
+ :process="curProcess"
|
|
|
+ ref="DetailDrawerRef"
|
|
|
+ type="warn"
|
|
|
+ />
|
|
|
</div>
|
|
|
</template>
|
|
|
|
|
|
<script setup name="SopAnalysis">
|
|
|
-import { ref, computed, watch, onMounted } from 'vue';
|
|
|
-import TableLoop from '@/components/common/table-loop/index.vue';
|
|
|
+import { ref, computed, watch } from 'vue';
|
|
|
import { useRequest } from 'vue-request';
|
|
|
-import { division, dateFormat } from '@/utils/tool';
|
|
|
-import {
|
|
|
- sopServiceList,
|
|
|
- warningTop,
|
|
|
- attendanceTop,
|
|
|
- supWarningTrend,
|
|
|
- sopWarningAnalysis,
|
|
|
-} from '@/api/report';
|
|
|
-import { createLineOption } from '@/utils/chart';
|
|
|
import { FullscreenIcon } from 'tdesign-icons-vue-next';
|
|
|
-const chart1 = ref();
|
|
|
-const chart2 = ref();
|
|
|
-const chart3 = ref();
|
|
|
-const chart4 = ref();
|
|
|
-const chart5 = ref();
|
|
|
-const chart6 = ref();
|
|
|
-const curTimeRange = ref([]);
|
|
|
-const serviceOptions = ref([]);
|
|
|
-
|
|
|
-const timeParams = computed(() => {
|
|
|
- return {
|
|
|
- startTime: new Date(curTimeRange.value[0] + ' 00:00:00').getTime(),
|
|
|
- endTime: new Date(curTimeRange.value[1] + ' 23:59:59').getTime(),
|
|
|
- };
|
|
|
-});
|
|
|
-const serviceId = ref('');
|
|
|
-const centerGroup = ref('REGION');
|
|
|
-const timeChange = (time) => {
|
|
|
- sopServiceList(timeParams.value).then((res) => {
|
|
|
- serviceOptions.value = res || [];
|
|
|
- res?.length && (serviceId.value = res[0].id);
|
|
|
- });
|
|
|
-};
|
|
|
-const sort1 = ref('PENDING');
|
|
|
-const sort2 = ref('PENDING');
|
|
|
-const sort3 = ref('PENDING');
|
|
|
-
|
|
|
-const { data: result1, loading: loading1, run: run1 } = useRequest(warningTop);
|
|
|
-const { data: result2, loading: loading2, run: run2 } = useRequest(warningTop);
|
|
|
-const { data: result3, loading: loading3, run: run3 } = useRequest(warningTop);
|
|
|
+import { cloneDeep } from 'lodash-es';
|
|
|
+import DetailDrawer from '../service-analysis/detail-drawer.vue';
|
|
|
+import { warnByRegion, warnBySupplier, warnByCoordinator } from '@/api/report';
|
|
|
+const showDetailDrawer = ref(false);
|
|
|
+const curProcess = ref('');
|
|
|
const {
|
|
|
- data: result4,
|
|
|
- loading: loading4,
|
|
|
- run: run4,
|
|
|
-} = useRequest(attendanceTop);
|
|
|
+ data: tableData1,
|
|
|
+ run: run1,
|
|
|
+ loading: loading1,
|
|
|
+} = useRequest(warnByRegion);
|
|
|
const {
|
|
|
- data: result5,
|
|
|
- loading: loading5,
|
|
|
- run: run5,
|
|
|
-} = useRequest(attendanceTop);
|
|
|
+ data: tableData2,
|
|
|
+ run: run2,
|
|
|
+ loading: loading2,
|
|
|
+} = useRequest(warnBySupplier);
|
|
|
const {
|
|
|
- data: result6,
|
|
|
- loading: loading6,
|
|
|
- run: run6,
|
|
|
-} = useRequest(attendanceTop);
|
|
|
-const {
|
|
|
- data: result7,
|
|
|
- loading: loading7,
|
|
|
- run: run7,
|
|
|
-} = useRequest(sopWarningAnalysis);
|
|
|
-const {
|
|
|
- data: result8,
|
|
|
- loading: loading8,
|
|
|
- run: run8,
|
|
|
-} = useRequest(supWarningTrend);
|
|
|
-
|
|
|
-const options8 = computed(() => {
|
|
|
- let res = result8.value || [];
|
|
|
- let xData = [],
|
|
|
- sData = [];
|
|
|
- if (res.length) {
|
|
|
- xData = res.map((item) => item.timeStr);
|
|
|
- }
|
|
|
- if (res.length && res[0].sopSupplierAvgViewInfo?.length) {
|
|
|
- res = res.map((item) => {
|
|
|
- item.sopSupplierAvgViewInfo = item.sopSupplierAvgViewInfo || [];
|
|
|
- item.sopSupplierAvgViewInfo.sort((a, b) => a.supplierId - b.supplierId);
|
|
|
- return item;
|
|
|
- });
|
|
|
-
|
|
|
- sData = res[0].sopSupplierAvgViewInfo.map((item) => ({
|
|
|
- name: item.supplierName,
|
|
|
- data: res.map((v) => {
|
|
|
- return (
|
|
|
- v.sopSupplierAvgViewInfo.find((x) => x.supplierId == item.supplierId)
|
|
|
- ?.rate || []
|
|
|
- );
|
|
|
- }),
|
|
|
- }));
|
|
|
- }
|
|
|
- return createLineOption({ xData, sData });
|
|
|
-});
|
|
|
+ data: tableData3,
|
|
|
+ run: run3,
|
|
|
+ loading: loading3,
|
|
|
+} = useRequest(warnByCoordinator);
|
|
|
|
|
|
-const tableDataHandle = (data) => {
|
|
|
- return data || [];
|
|
|
+const DetailDrawerRef = ref();
|
|
|
+const searchByX = (obj) => {
|
|
|
+ DetailDrawerRef.value.searchByOther(obj);
|
|
|
};
|
|
|
-const tableColumns1 = [
|
|
|
- {
|
|
|
- prop: 'crmName',
|
|
|
- label: '客户名称',
|
|
|
- style: { width: '60px' },
|
|
|
- },
|
|
|
- {
|
|
|
- prop: 'region_name',
|
|
|
- label: '大区',
|
|
|
- style: { width: '70px' },
|
|
|
- },
|
|
|
- {
|
|
|
- prop: 'real_name',
|
|
|
- label: '区域协调人',
|
|
|
- style: { width: '70px' },
|
|
|
- },
|
|
|
- { prop: 'avgWarn', label: '预警数', style: { width: '60px' } },
|
|
|
-];
|
|
|
-const tableColumns2 = [
|
|
|
- {
|
|
|
- prop: 'region_name',
|
|
|
- label: '大区',
|
|
|
- style: { width: '60px' },
|
|
|
- },
|
|
|
- {
|
|
|
- prop: 'real_name',
|
|
|
- label: '大区经理',
|
|
|
- style: { width: '70px' },
|
|
|
- },
|
|
|
- {
|
|
|
- prop: 'avgWarn',
|
|
|
- label: '预警数',
|
|
|
- style: { width: '70px' },
|
|
|
- },
|
|
|
- { prop: 'avgMinutes', label: '均值', style: { width: '60px' } },
|
|
|
-];
|
|
|
-
|
|
|
-const tableColumns3 = [
|
|
|
- {
|
|
|
- prop: 'supplier',
|
|
|
- label: '供应商',
|
|
|
- style: { width: '60px' },
|
|
|
- },
|
|
|
- {
|
|
|
- prop: 'region_name',
|
|
|
- label: '大区',
|
|
|
- style: { width: '70px' },
|
|
|
- },
|
|
|
- {
|
|
|
- prop: 'real_name',
|
|
|
- label: '区域协调人',
|
|
|
- style: { width: '70px' },
|
|
|
- },
|
|
|
- { prop: 'avgWarn', label: '预警数', style: { width: '70px' } },
|
|
|
- { prop: 'avgMinutes', label: '均值', style: { width: '60px' } },
|
|
|
-];
|
|
|
-
|
|
|
-const tableColumns4 = [
|
|
|
- {
|
|
|
- prop: 'crmName',
|
|
|
- label: '客户名称',
|
|
|
- style: { width: '60px' },
|
|
|
- },
|
|
|
- {
|
|
|
- prop: 'dname',
|
|
|
- label: '考勤对象',
|
|
|
- style: { width: '70px' },
|
|
|
- },
|
|
|
- {
|
|
|
- prop: 'real_name',
|
|
|
- label: '区域协调人',
|
|
|
- style: { width: '70px' },
|
|
|
- },
|
|
|
- { prop: 'total', label: '异常数', style: { width: '60px' } },
|
|
|
-];
|
|
|
-const tableColumns5 = [
|
|
|
- {
|
|
|
- prop: 'region_name',
|
|
|
- label: '大区',
|
|
|
- style: { width: '60px' },
|
|
|
- },
|
|
|
- {
|
|
|
- prop: 'real_name',
|
|
|
- label: '大区经理',
|
|
|
- style: { width: '70px' },
|
|
|
- },
|
|
|
- {
|
|
|
- prop: 'total',
|
|
|
- label: '异常数',
|
|
|
- style: { width: '70px' },
|
|
|
- },
|
|
|
- { prop: 'avg', label: '均值', style: { width: '60px' } },
|
|
|
+const serviceId = ref('');
|
|
|
+watch(serviceId, (serviceUnitId) => {
|
|
|
+ run1({ serviceUnitId });
|
|
|
+ run2({ serviceUnitId });
|
|
|
+ run3({ serviceUnitId });
|
|
|
+});
|
|
|
+const baseColumns = [
|
|
|
+ { colKey: 'total', title: '预警总数' },
|
|
|
+ { colKey: 'scanStartTimeNum', title: '扫描开始时间预警' },
|
|
|
+ { colKey: 'scanEndTimeNum', title: '扫描结束时间预警' },
|
|
|
+ { colKey: 'markStartTimeNum', title: '评卷开始时间预警' },
|
|
|
+ { colKey: 'markEndTimeNum', title: '评卷结束时间预警' },
|
|
|
];
|
|
|
-
|
|
|
-const tableColumns6 = [
|
|
|
- {
|
|
|
- prop: 'supplier',
|
|
|
- label: '供应商',
|
|
|
- style: { width: '80px' },
|
|
|
- },
|
|
|
- { prop: 'total', label: '异常数', style: { width: '70px' } },
|
|
|
- { prop: 'avg', label: '均值', style: { width: '60px' } },
|
|
|
+const columns1 = [{ colKey: 'leadName', title: '大区经理' }, ...baseColumns];
|
|
|
+const columns2 = [{ colKey: 'supplierName', title: '人力商' }, ...baseColumns];
|
|
|
+const columns3 = [
|
|
|
+ { colKey: 'coordinatorName', title: '区域协调人' },
|
|
|
+ ...baseColumns,
|
|
|
];
|
|
|
-watch(serviceId, (serviceId) => {
|
|
|
- sort1.value = sort2.value = sort3.value = 'PENDING';
|
|
|
- run1({
|
|
|
- group: 'CRM',
|
|
|
- serviceId,
|
|
|
- sort: sort1.value,
|
|
|
- });
|
|
|
- run2({
|
|
|
- group: 'REGION',
|
|
|
- serviceId,
|
|
|
- sort: sort2.value,
|
|
|
- });
|
|
|
- run3({
|
|
|
- group: 'SUPPLIER',
|
|
|
- serviceId,
|
|
|
- sort: sort3.value,
|
|
|
- });
|
|
|
- run4({
|
|
|
- group: 'CRM',
|
|
|
- serviceId,
|
|
|
- ...timeParams.value,
|
|
|
- });
|
|
|
- run5({
|
|
|
- group: 'REGION',
|
|
|
- serviceId,
|
|
|
- ...timeParams.value,
|
|
|
- });
|
|
|
- run6({
|
|
|
- group: 'SUPPLIER',
|
|
|
- serviceId,
|
|
|
- ...timeParams.value,
|
|
|
- });
|
|
|
- run7({
|
|
|
- group: centerGroup.value,
|
|
|
- serviceId,
|
|
|
- });
|
|
|
- run8({ serviceId });
|
|
|
-});
|
|
|
-watch(centerGroup, () => {
|
|
|
- run7({
|
|
|
- group: centerGroup.value,
|
|
|
- serviceId,
|
|
|
- });
|
|
|
-});
|
|
|
-const changeSort = (group, index) => {
|
|
|
- const sort =
|
|
|
- index == 1 ? sort1.value : index == 2 ? sort2.value : sort3.value;
|
|
|
- const run = index == 1 ? run1 : index == 2 ? run2 : run3;
|
|
|
- run({
|
|
|
- group,
|
|
|
- serviceId,
|
|
|
- sort,
|
|
|
- });
|
|
|
-};
|
|
|
</script>
|
|
|
|
|
|
<style lang="less" scoped>
|
|
@@ -578,154 +315,24 @@ const changeSort = (group, index) => {
|
|
|
overflow: auto;
|
|
|
.scroll-content {
|
|
|
height: 100%;
|
|
|
- min-height: 600px;
|
|
|
min-width: 1000px;
|
|
|
display: flex;
|
|
|
-
|
|
|
- .chart-wrap {
|
|
|
- height: calc(100% - 36px);
|
|
|
- }
|
|
|
+ justify-content: space-between;
|
|
|
.col1,
|
|
|
- .col3 {
|
|
|
- width: 268px;
|
|
|
- height: 100%;
|
|
|
- .card {
|
|
|
- height: calc((100% - 30px) / 3);
|
|
|
- &:not(:first-child) {
|
|
|
- margin-top: 15px;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
.col2 {
|
|
|
- width: calc(100% - 566px);
|
|
|
- margin-left: 15px;
|
|
|
- margin-right: 15px;
|
|
|
- .card {
|
|
|
- &:first-child {
|
|
|
- height: calc((100% - 30px) * 2 / 3 + 15px);
|
|
|
- .none-data {
|
|
|
- height: calc(100% - 42px);
|
|
|
- margin-top: 10px;
|
|
|
- display: flex;
|
|
|
- justify-content: center;
|
|
|
- align-items: center;
|
|
|
- color: #ccc;
|
|
|
- font-size: 14px;
|
|
|
- }
|
|
|
- .list-wrap {
|
|
|
- height: calc(100% - 42px);
|
|
|
- overflow: auto;
|
|
|
- margin-top: 10px;
|
|
|
- .list-item {
|
|
|
- .item-head {
|
|
|
- height: 32px;
|
|
|
- background: #f7f7f7;
|
|
|
- padding: 0 10px;
|
|
|
- line-height: 32px;
|
|
|
- color: #262626;
|
|
|
- }
|
|
|
- .item-body {
|
|
|
- padding: 4px 8px;
|
|
|
- .label {
|
|
|
- color: #8c8c8c;
|
|
|
- font-size: 15px;
|
|
|
- }
|
|
|
- .row2 {
|
|
|
- margin-top: 5px;
|
|
|
- .process-box {
|
|
|
- display: flex;
|
|
|
- .grid-item {
|
|
|
- width: 33.33%;
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- span {
|
|
|
- font-size: 11px;
|
|
|
- color: #262626;
|
|
|
- &:last-child {
|
|
|
- padding-right: 20px;
|
|
|
- }
|
|
|
- }
|
|
|
- .bar-box {
|
|
|
- flex: 1;
|
|
|
- max-width: 100px;
|
|
|
- margin: 0 10px;
|
|
|
- height: 6px;
|
|
|
- border-radius: 3px;
|
|
|
- background: #d9d9d9;
|
|
|
- .bar {
|
|
|
- background: #4080ff;
|
|
|
- height: 100%;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- .row1 {
|
|
|
- display: flex;
|
|
|
- .grid-item {
|
|
|
- width: 33.33%;
|
|
|
- p {
|
|
|
- font-size: 18px;
|
|
|
- font-weight: bold;
|
|
|
- color: #165dff;
|
|
|
- &.red {
|
|
|
- color: #f53f3f;
|
|
|
- }
|
|
|
- &.green {
|
|
|
- color: #00b42a;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- .tab-box {
|
|
|
- height: 32px;
|
|
|
- padding: 5px 8px;
|
|
|
- background: #f0f0f0;
|
|
|
- border-radius: 3px;
|
|
|
- float: left;
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- .tab {
|
|
|
- height: 22px;
|
|
|
- padding: 0 6px;
|
|
|
- line-height: 22px;
|
|
|
- color: #8c8c8c;
|
|
|
- cursor: pointer;
|
|
|
- &.active {
|
|
|
- background-color: #fff;
|
|
|
- border-radius: 2px;
|
|
|
- }
|
|
|
- &:last-child {
|
|
|
- margin-left: 5px;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- &:last-child {
|
|
|
- height: calc((100% - 30px) / 3);
|
|
|
- margin-top: 15px;
|
|
|
+ width: calc(50% - 8px);
|
|
|
+ :deep(.t-table__body) {
|
|
|
+ font-size: 12px !important;
|
|
|
+ .t-link {
|
|
|
+ font-size: 12px !important;
|
|
|
}
|
|
|
}
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- .card {
|
|
|
- padding: 4px 10px 10px 10px;
|
|
|
- background-color: #fff;
|
|
|
- border: 1px solid #e5e5e5;
|
|
|
- border-radius: 4px;
|
|
|
- .title {
|
|
|
- height: 36px;
|
|
|
- display: flex;
|
|
|
- justify-content: space-between;
|
|
|
- align-items: center;
|
|
|
- .label {
|
|
|
- color: #262626;
|
|
|
- font-size: 14px;
|
|
|
- // font-weight: bold;
|
|
|
+ .module-title {
|
|
|
+ height: 30px;
|
|
|
+ font-size: 16px;
|
|
|
+ font-weight: bold;
|
|
|
+ color: #000;
|
|
|
+ text-align: center;
|
|
|
}
|
|
|
}
|
|
|
}
|