|
|
@@ -36,9 +36,9 @@
|
|
|
<span>启用日历</span>
|
|
|
<strong>{{ enabledCalendarCount }}/{{ totalCalendarCount }}</strong>
|
|
|
</div>
|
|
|
- <div :class="{ danger: conflictDayCount }">
|
|
|
- <span>冲突天数</span>
|
|
|
- <strong>{{ conflictDayCount }}</strong>
|
|
|
+ <div>
|
|
|
+ <span>排班完成率</span>
|
|
|
+ <strong>{{ vm.scheduleRate }}%</strong>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
@@ -46,7 +46,7 @@
|
|
|
|
|
|
<section class="industrial-kpi-strip">
|
|
|
<div
|
|
|
- v-for="item in vm.visualKpis"
|
|
|
+ v-for="item in displayVisualKpis"
|
|
|
:key="item.key"
|
|
|
class="industrial-kpi"
|
|
|
:style="{ '--accent-color': getKpiColor(item.key) }"
|
|
|
@@ -63,104 +63,66 @@
|
|
|
</section>
|
|
|
|
|
|
<section class="industrial-main-grid">
|
|
|
- <div class="industrial-column industrial-column-main">
|
|
|
- <div class="industrial-panel schedule-analysis">
|
|
|
- <div class="industrial-panel-head">
|
|
|
- <div>
|
|
|
- <span>Schedule Ratio</span>
|
|
|
- <strong>排班状态占比</strong>
|
|
|
- <p>工作日、空闲日与节假日构成</p>
|
|
|
- </div>
|
|
|
- <el-tag
|
|
|
- size="mini"
|
|
|
- :type="vm.scheduleRate >= 90 ? 'success' : 'warning'"
|
|
|
- >
|
|
|
- {{ vm.scheduleRate >= 90 ? '状态良好' : '需关注' }}
|
|
|
- </el-tag>
|
|
|
+ <div class="industrial-panel schedule-analysis">
|
|
|
+ <div class="industrial-panel-head">
|
|
|
+ <div>
|
|
|
+ <span>Schedule Ratio</span>
|
|
|
+ <strong>排班状态占比</strong>
|
|
|
+ <p>工作日、空闲日与节假日构成</p>
|
|
|
</div>
|
|
|
+ <el-tag
|
|
|
+ size="mini"
|
|
|
+ :type="vm.scheduleRate >= 90 ? 'success' : 'warning'"
|
|
|
+ >
|
|
|
+ {{ vm.scheduleRate >= 90 ? '状态良好' : '需关注' }}
|
|
|
+ </el-tag>
|
|
|
+ </div>
|
|
|
|
|
|
- <div class="schedule-analysis-body">
|
|
|
- <el-tooltip
|
|
|
- placement="top"
|
|
|
- effect="light"
|
|
|
- :content="vm.scheduleTooltip"
|
|
|
- :disabled="isScrolling"
|
|
|
- :enterable="false"
|
|
|
- popper-class="factory-calendar-stat-tooltip"
|
|
|
- >
|
|
|
- <div class="schedule-radar">
|
|
|
- <div
|
|
|
- class="schedule-donut"
|
|
|
- :style="{ background: vm.scheduleDonutBackground }"
|
|
|
- >
|
|
|
- <div class="schedule-donut-center">
|
|
|
- <strong>{{ vm.scheduleRate }}%</strong>
|
|
|
- <span>已排班率</span>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </el-tooltip>
|
|
|
-
|
|
|
- <div class="schedule-segments">
|
|
|
- <el-tooltip
|
|
|
- v-for="item in vm.scheduleSegments"
|
|
|
- :key="item.key"
|
|
|
- placement="top"
|
|
|
- effect="light"
|
|
|
- :content="vm.getScheduleSegmentTooltip(item)"
|
|
|
- :disabled="isScrolling"
|
|
|
- :enterable="false"
|
|
|
- popper-class="factory-calendar-stat-tooltip"
|
|
|
+ <div class="schedule-analysis-body">
|
|
|
+ <el-tooltip
|
|
|
+ placement="top"
|
|
|
+ effect="light"
|
|
|
+ :content="vm.scheduleTooltip"
|
|
|
+ :disabled="isScrolling"
|
|
|
+ :enterable="false"
|
|
|
+ popper-class="factory-calendar-stat-tooltip"
|
|
|
+ >
|
|
|
+ <div class="schedule-radar">
|
|
|
+ <div
|
|
|
+ class="schedule-donut"
|
|
|
+ :style="{ background: vm.scheduleDonutBackground }"
|
|
|
>
|
|
|
- <div
|
|
|
- class="schedule-segment-row"
|
|
|
- :style="{ '--segment-color': item.color }"
|
|
|
- >
|
|
|
- <div class="segment-meta">
|
|
|
- <span>{{ item.label }}</span>
|
|
|
- <strong>{{ item.value }}</strong>
|
|
|
- </div>
|
|
|
- <div class="segment-track">
|
|
|
- <i
|
|
|
- :style="{ width: getScheduleSegmentPercent(item) + '%' }"
|
|
|
- />
|
|
|
- </div>
|
|
|
+ <div class="schedule-donut-center">
|
|
|
+ <strong>{{ vm.scheduleRate }}%</strong>
|
|
|
+ <span>已排班率</span>
|
|
|
</div>
|
|
|
- </el-tooltip>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
+ </el-tooltip>
|
|
|
|
|
|
- <div class="industrial-panel month-analysis">
|
|
|
- <div class="industrial-panel-head">
|
|
|
- <div>
|
|
|
- <span>Monthly Status</span>
|
|
|
- <strong>月度状态分布</strong>
|
|
|
- <p>按当前年月统计各类日期数量</p>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
-
|
|
|
- <div class="month-telemetry-list">
|
|
|
+ <div class="schedule-segments">
|
|
|
<el-tooltip
|
|
|
- v-for="item in vm.visualMonthBars"
|
|
|
+ v-for="item in vm.scheduleSegments"
|
|
|
:key="item.key"
|
|
|
placement="top"
|
|
|
effect="light"
|
|
|
- :content="vm.getMonthBarTooltip(item)"
|
|
|
+ :content="vm.getScheduleSegmentTooltip(item)"
|
|
|
:disabled="isScrolling"
|
|
|
:enterable="false"
|
|
|
popper-class="factory-calendar-stat-tooltip"
|
|
|
>
|
|
|
<div
|
|
|
- class="month-telemetry-row"
|
|
|
- :style="{ '--month-color': item.color }"
|
|
|
+ class="schedule-segment-row"
|
|
|
+ :style="{ '--segment-color': item.color }"
|
|
|
>
|
|
|
- <div class="month-row-head">
|
|
|
+ <div class="segment-meta">
|
|
|
<span>{{ item.label }}</span>
|
|
|
- <strong>{{ item.value }} 天</strong>
|
|
|
+ <strong>{{ item.value }}</strong>
|
|
|
</div>
|
|
|
- <div class="month-track">
|
|
|
- <i :style="{ width: item.percent + '%' }" />
|
|
|
+ <div class="segment-track">
|
|
|
+ <i
|
|
|
+ :style="{ width: getScheduleSegmentPercent(item) + '%' }"
|
|
|
+ />
|
|
|
</div>
|
|
|
</div>
|
|
|
</el-tooltip>
|
|
|
@@ -168,89 +130,80 @@
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
- <div class="industrial-column industrial-column-side">
|
|
|
- <div class="industrial-panel type-analysis">
|
|
|
- <div class="industrial-panel-head">
|
|
|
- <div>
|
|
|
- <span>Calendar Type</span>
|
|
|
- <strong>日历类型分布</strong>
|
|
|
- <p>生产、设备、人员日历启停情况</p>
|
|
|
- </div>
|
|
|
+ <div class="industrial-panel type-analysis">
|
|
|
+ <div class="industrial-panel-head">
|
|
|
+ <div>
|
|
|
+ <span>Calendar Type</span>
|
|
|
+ <strong>日历类型分布</strong>
|
|
|
+ <p>生产、设备、人员日历启停情况</p>
|
|
|
</div>
|
|
|
+ </div>
|
|
|
|
|
|
- <div class="type-distribution">
|
|
|
- <el-tooltip
|
|
|
- v-for="item in vm.calendarTypeStats"
|
|
|
- :key="item.value"
|
|
|
- placement="top"
|
|
|
- effect="light"
|
|
|
- :content="vm.getCalendarTypeTooltip(item)"
|
|
|
- :disabled="isScrolling"
|
|
|
- :enterable="false"
|
|
|
- popper-class="factory-calendar-stat-tooltip"
|
|
|
+ <div class="type-distribution">
|
|
|
+ <el-tooltip
|
|
|
+ v-for="item in vm.calendarTypeStats"
|
|
|
+ :key="item.value"
|
|
|
+ placement="top"
|
|
|
+ effect="light"
|
|
|
+ :content="vm.getCalendarTypeTooltip(item)"
|
|
|
+ :disabled="isScrolling"
|
|
|
+ :enterable="false"
|
|
|
+ popper-class="factory-calendar-stat-tooltip"
|
|
|
+ >
|
|
|
+ <div
|
|
|
+ class="type-distribution-row"
|
|
|
+ :style="{
|
|
|
+ '--type-color': item.color,
|
|
|
+ '--type-percent': getCalendarTypePercent(item) + '%'
|
|
|
+ }"
|
|
|
>
|
|
|
- <div
|
|
|
- class="type-distribution-row"
|
|
|
- :style="{
|
|
|
- '--type-color': item.color,
|
|
|
- '--type-percent': getCalendarTypePercent(item) + '%'
|
|
|
- }"
|
|
|
- >
|
|
|
- <div class="type-orbit">
|
|
|
- <strong>{{ item.count }}</strong>
|
|
|
- </div>
|
|
|
- <div class="type-copy">
|
|
|
- <strong>{{ item.label }}</strong>
|
|
|
- <span
|
|
|
- >{{ item.enabled }} 个启用 /
|
|
|
- {{ item.disabled }} 个禁用</span
|
|
|
- >
|
|
|
- </div>
|
|
|
+ <div class="type-orbit">
|
|
|
+ <strong>{{ item.count }}</strong>
|
|
|
</div>
|
|
|
- </el-tooltip>
|
|
|
- </div>
|
|
|
+ <div class="type-copy">
|
|
|
+ <strong>{{ item.label }}</strong>
|
|
|
+ <span
|
|
|
+ >{{ item.enabled }} 个启用 / {{ item.disabled }} 个禁用</span
|
|
|
+ >
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </el-tooltip>
|
|
|
</div>
|
|
|
+ </div>
|
|
|
|
|
|
- <div class="industrial-panel conflict-analysis">
|
|
|
- <div class="industrial-panel-head">
|
|
|
- <div>
|
|
|
- <span>Conflict Trend</span>
|
|
|
- <strong>冲突趋势</strong>
|
|
|
- <p>近 6 个时间点所在周冲突数量</p>
|
|
|
- </div>
|
|
|
- <el-tag size="mini" :type="conflictDayCount ? 'danger' : 'success'">
|
|
|
- {{ conflictDayCount ? '存在冲突' : '无冲突' }}
|
|
|
- </el-tag>
|
|
|
+ <div class="industrial-panel month-analysis">
|
|
|
+ <div class="industrial-panel-head">
|
|
|
+ <div>
|
|
|
+ <span>Monthly Status</span>
|
|
|
+ <strong>月度状态分布</strong>
|
|
|
+ <p>按当前年月统计各类日期数量</p>
|
|
|
</div>
|
|
|
+ </div>
|
|
|
|
|
|
- <div class="conflict-analysis-body">
|
|
|
- <div class="conflict-total" :class="{ danger: conflictDayCount }">
|
|
|
- <span>当前月冲突天数</span>
|
|
|
- <strong>{{ conflictDayCount }}</strong>
|
|
|
- </div>
|
|
|
- <div class="conflict-bars">
|
|
|
- <el-tooltip
|
|
|
- v-for="item in vm.conflictTrend"
|
|
|
- :key="item.label"
|
|
|
- placement="top"
|
|
|
- effect="light"
|
|
|
- :content="vm.getConflictTrendTooltip(item)"
|
|
|
- :disabled="isScrolling"
|
|
|
- :enterable="false"
|
|
|
- popper-class="factory-calendar-stat-tooltip"
|
|
|
- >
|
|
|
- <div
|
|
|
- class="conflict-bar"
|
|
|
- :class="{ 'is-zero': !Number(item.count || 0) }"
|
|
|
- >
|
|
|
- <span :style="{ height: item.height + '%' }">
|
|
|
- <b>{{ item.count }}</b>
|
|
|
- </span>
|
|
|
- <em>{{ item.label }}</em>
|
|
|
- </div>
|
|
|
- </el-tooltip>
|
|
|
+ <div class="month-telemetry-list">
|
|
|
+ <el-tooltip
|
|
|
+ v-for="item in displayMonthBars"
|
|
|
+ :key="item.key"
|
|
|
+ placement="top"
|
|
|
+ effect="light"
|
|
|
+ :content="vm.getMonthBarTooltip(item)"
|
|
|
+ :disabled="isScrolling"
|
|
|
+ :enterable="false"
|
|
|
+ popper-class="factory-calendar-stat-tooltip"
|
|
|
+ >
|
|
|
+ <div
|
|
|
+ class="month-telemetry-row"
|
|
|
+ :style="{ '--month-color': item.color }"
|
|
|
+ >
|
|
|
+ <div class="month-row-head">
|
|
|
+ <span>{{ item.label }}</span>
|
|
|
+ <strong>{{ item.value }} 天</strong>
|
|
|
+ </div>
|
|
|
+ <div class="month-track">
|
|
|
+ <i :style="{ width: item.percent + '%' }" />
|
|
|
+ </div>
|
|
|
</div>
|
|
|
- </div>
|
|
|
+ </el-tooltip>
|
|
|
</div>
|
|
|
</div>
|
|
|
</section>
|
|
|
@@ -284,15 +237,21 @@
|
|
|
return (this.vm.calendars || []).filter((item) => item.status === 1)
|
|
|
.length;
|
|
|
},
|
|
|
+ displayVisualKpis() {
|
|
|
+ return (this.vm.visualKpis || []).filter(
|
|
|
+ (item) => item.key !== 'conflict'
|
|
|
+ );
|
|
|
+ },
|
|
|
+ displayMonthBars() {
|
|
|
+ return (this.vm.visualMonthBars || []).filter(
|
|
|
+ (item) => item.key !== 'conflict'
|
|
|
+ );
|
|
|
+ },
|
|
|
healthScore() {
|
|
|
const scheduleScore = Number(this.vm.scheduleRate) || 0;
|
|
|
- const conflictPenalty = Math.min(this.conflictDayCount * 8, 40);
|
|
|
- return Math.max(scheduleScore - conflictPenalty, 0);
|
|
|
+ return Math.max(scheduleScore, 0);
|
|
|
},
|
|
|
healthText() {
|
|
|
- if (this.conflictDayCount) {
|
|
|
- return '冲突待处理';
|
|
|
- }
|
|
|
if (this.healthScore >= 90) {
|
|
|
return '稳定运行';
|
|
|
}
|
|
|
@@ -300,12 +259,6 @@
|
|
|
return '基本可控';
|
|
|
}
|
|
|
return '需要排查';
|
|
|
- },
|
|
|
- conflictDayCount() {
|
|
|
- const stat = (this.vm.monthStats || []).find(
|
|
|
- (item) => item.key === 'conflict'
|
|
|
- );
|
|
|
- return Number(stat?.value || 0);
|
|
|
}
|
|
|
},
|
|
|
mounted() {
|