|
|
@@ -181,17 +181,28 @@
|
|
|
class="dispatch-state-checkbox"
|
|
|
:value="isCurrentPageDispatchChecked"
|
|
|
:indeterminate="isCurrentPageDispatchIndeterminate"
|
|
|
- :disabled="readonlyMode"
|
|
|
+ :disabled="
|
|
|
+ readonlyMode || !currentPageSelectableDispatchRows.length
|
|
|
+ "
|
|
|
@change="handleCurrentPageDispatchCheckChange"
|
|
|
/>
|
|
|
</template>
|
|
|
<template slot-scope="{ row }">
|
|
|
- <el-checkbox
|
|
|
- class="dispatch-state-checkbox"
|
|
|
- :value="isSelectedDispatchObject(row)"
|
|
|
- :disabled="readonlyMode"
|
|
|
- @change="handleDispatchObjectCheckChange(row, $event)"
|
|
|
- />
|
|
|
+ <el-tooltip
|
|
|
+ :disabled="!isDeviceSnapshotLocked(row)"
|
|
|
+ content="该工序已制定设备类型"
|
|
|
+ placement="top"
|
|
|
+ popper-class="dispatch-device-lock-tooltip"
|
|
|
+ >
|
|
|
+ <span class="dispatch-checkbox-wrap">
|
|
|
+ <el-checkbox
|
|
|
+ class="dispatch-state-checkbox"
|
|
|
+ :value="isSelectedDispatchObject(row)"
|
|
|
+ :disabled="isDispatchRowControlDisabled(row)"
|
|
|
+ @change="handleDispatchObjectCheckChange(row, $event)"
|
|
|
+ />
|
|
|
+ </span>
|
|
|
+ </el-tooltip>
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
<el-table-column
|
|
|
@@ -200,8 +211,28 @@
|
|
|
label="工位名称"
|
|
|
align="center"
|
|
|
min-width="180"
|
|
|
- show-overflow-tooltip
|
|
|
- />
|
|
|
+ >
|
|
|
+ <template slot-scope="{ row }">
|
|
|
+ <el-tooltip
|
|
|
+ :disabled="!isDeviceSnapshotLocked(row) && !row.displayName"
|
|
|
+ :content="
|
|
|
+ isDeviceSnapshotLocked(row)
|
|
|
+ ? '该工序已制定设备类型'
|
|
|
+ : row.displayName || ''
|
|
|
+ "
|
|
|
+ placement="top"
|
|
|
+ :popper-class="
|
|
|
+ isDeviceSnapshotLocked(row)
|
|
|
+ ? 'dispatch-device-lock-tooltip'
|
|
|
+ : 'dispatch-workstation-tooltip'
|
|
|
+ "
|
|
|
+ >
|
|
|
+ <span class="dispatch-workstation-name">
|
|
|
+ {{ row.displayName }}
|
|
|
+ </span>
|
|
|
+ </el-tooltip>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
<el-table-column
|
|
|
v-if="isDispatchColumnVisible('code')"
|
|
|
prop="code"
|
|
|
@@ -268,13 +299,22 @@
|
|
|
width="140"
|
|
|
>
|
|
|
<template slot-scope="{ row }">
|
|
|
- <el-input
|
|
|
- :value="row.quantity"
|
|
|
- placeholder="请输入数量"
|
|
|
- class="config-table-control"
|
|
|
- :disabled="isDispatchRowControlDisabled(row)"
|
|
|
- @input="handleDispatchRowQuantityInput(row, $event)"
|
|
|
- />
|
|
|
+ <el-tooltip
|
|
|
+ :disabled="!isDeviceSnapshotLocked(row)"
|
|
|
+ content="该工序已制定设备类型"
|
|
|
+ placement="top"
|
|
|
+ popper-class="dispatch-device-lock-tooltip"
|
|
|
+ >
|
|
|
+ <span class="dispatch-disabled-field">
|
|
|
+ <el-input
|
|
|
+ :value="row.quantity"
|
|
|
+ placeholder="请输入数量"
|
|
|
+ class="config-table-control"
|
|
|
+ :disabled="isDispatchRowControlDisabled(row)"
|
|
|
+ @input="handleDispatchRowQuantityInput(row, $event)"
|
|
|
+ />
|
|
|
+ </span>
|
|
|
+ </el-tooltip>
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
<el-table-column
|
|
|
@@ -284,16 +324,25 @@
|
|
|
min-width="220"
|
|
|
>
|
|
|
<template slot-scope="{ row }">
|
|
|
- <el-date-picker
|
|
|
- v-model="row.executionStartTime"
|
|
|
- type="datetime"
|
|
|
- value-format="yyyy-MM-dd HH:mm:ss"
|
|
|
- placeholder="开始时间"
|
|
|
- clearable
|
|
|
- class="config-table-control"
|
|
|
- :disabled="isDispatchRowControlDisabled(row)"
|
|
|
- @change="handleDispatchRowStartTimeChange(row)"
|
|
|
- />
|
|
|
+ <el-tooltip
|
|
|
+ :disabled="!isDeviceSnapshotLocked(row)"
|
|
|
+ content="该工序已制定设备类型"
|
|
|
+ placement="top"
|
|
|
+ popper-class="dispatch-device-lock-tooltip"
|
|
|
+ >
|
|
|
+ <span class="dispatch-disabled-field">
|
|
|
+ <el-date-picker
|
|
|
+ v-model="row.executionStartTime"
|
|
|
+ type="datetime"
|
|
|
+ value-format="yyyy-MM-dd HH:mm:ss"
|
|
|
+ placeholder="开始时间"
|
|
|
+ clearable
|
|
|
+ class="config-table-control"
|
|
|
+ :disabled="isDispatchRowControlDisabled(row)"
|
|
|
+ @change="handleDispatchRowStartTimeChange(row)"
|
|
|
+ />
|
|
|
+ </span>
|
|
|
+ </el-tooltip>
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
<el-table-column
|
|
|
@@ -313,16 +362,25 @@
|
|
|
)
|
|
|
}"
|
|
|
>
|
|
|
- <el-date-picker
|
|
|
- v-model="row.executionEndTime"
|
|
|
- type="datetime"
|
|
|
- value-format="yyyy-MM-dd HH:mm:ss"
|
|
|
- placeholder="完成时间"
|
|
|
- clearable
|
|
|
- class="config-table-control"
|
|
|
- :disabled="isDispatchRowControlDisabled(row)"
|
|
|
- @change="handleDispatchRowEndTimeChange(row)"
|
|
|
- />
|
|
|
+ <el-tooltip
|
|
|
+ :disabled="!isDeviceSnapshotLocked(row)"
|
|
|
+ content="该工序已制定设备类型"
|
|
|
+ placement="top"
|
|
|
+ popper-class="dispatch-device-lock-tooltip"
|
|
|
+ >
|
|
|
+ <span class="dispatch-disabled-field">
|
|
|
+ <el-date-picker
|
|
|
+ v-model="row.executionEndTime"
|
|
|
+ type="datetime"
|
|
|
+ value-format="yyyy-MM-dd HH:mm:ss"
|
|
|
+ placeholder="完成时间"
|
|
|
+ clearable
|
|
|
+ class="config-table-control"
|
|
|
+ :disabled="isDispatchRowControlDisabled(row)"
|
|
|
+ @change="handleDispatchRowEndTimeChange(row)"
|
|
|
+ />
|
|
|
+ </span>
|
|
|
+ </el-tooltip>
|
|
|
</div>
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
@@ -590,6 +648,7 @@
|
|
|
import {
|
|
|
checkAssignConfirm,
|
|
|
listAssign,
|
|
|
+ listByPlanIdAndTaskId,
|
|
|
parameterGetByCode,
|
|
|
resetAssignee,
|
|
|
taskAssignment,
|
|
|
@@ -724,6 +783,9 @@
|
|
|
dispatchPageSize: 20,
|
|
|
dispatchRowDraftMap: {},
|
|
|
dispatchAssignmentMap: {},
|
|
|
+ dispatchDeviceSnapshotMap: {},
|
|
|
+ dispatchDeviceSnapshotLoading: false,
|
|
|
+ dispatchDeviceSnapshotRequestKey: '',
|
|
|
dispatchToolbarLoading: false,
|
|
|
dispatchRefreshLoading: false,
|
|
|
dispatchReportType: 1,
|
|
|
@@ -919,27 +981,34 @@
|
|
|
);
|
|
|
},
|
|
|
selectedDispatchObjectRows() {
|
|
|
- return this.dispatchObjectRows.filter((row) =>
|
|
|
- this.isSelectedDispatchObject(row)
|
|
|
+ return this.dispatchObjectRows.filter(
|
|
|
+ (row) =>
|
|
|
+ !this.isDeviceSnapshotLocked(row) &&
|
|
|
+ this.isSelectedDispatchObject(row)
|
|
|
+ );
|
|
|
+ },
|
|
|
+ currentPageSelectableDispatchRows() {
|
|
|
+ return this.pagedDispatchObjectRows.filter(
|
|
|
+ (row) => !this.isDeviceSnapshotLocked(row)
|
|
|
);
|
|
|
},
|
|
|
currentPageSelectedDispatchRows() {
|
|
|
- return this.pagedDispatchObjectRows.filter((row) =>
|
|
|
+ return this.currentPageSelectableDispatchRows.filter((row) =>
|
|
|
this.isSelectedDispatchObject(row)
|
|
|
);
|
|
|
},
|
|
|
isCurrentPageDispatchChecked() {
|
|
|
return (
|
|
|
- this.pagedDispatchObjectRows.length > 0 &&
|
|
|
+ this.currentPageSelectableDispatchRows.length > 0 &&
|
|
|
this.currentPageSelectedDispatchRows.length ===
|
|
|
- this.pagedDispatchObjectRows.length
|
|
|
+ this.currentPageSelectableDispatchRows.length
|
|
|
);
|
|
|
},
|
|
|
isCurrentPageDispatchIndeterminate() {
|
|
|
return (
|
|
|
this.currentPageSelectedDispatchRows.length > 0 &&
|
|
|
this.currentPageSelectedDispatchRows.length <
|
|
|
- this.pagedDispatchObjectRows.length
|
|
|
+ this.currentPageSelectableDispatchRows.length
|
|
|
);
|
|
|
},
|
|
|
normalTableHeight() {
|
|
|
@@ -954,6 +1023,7 @@
|
|
|
this.clearDispatchSelectionsByTaskKey(oldKey);
|
|
|
this.dispatchPage = 1;
|
|
|
this.loadDispatchAssignData();
|
|
|
+ this.loadDispatchDeviceSnapshots();
|
|
|
},
|
|
|
currentPlan: {
|
|
|
immediate: true,
|
|
|
@@ -961,8 +1031,10 @@
|
|
|
this.dispatchReportType = this.getDefaultDispatchReportType();
|
|
|
this.dispatchRowDraftMap = {};
|
|
|
this.dispatchAssignmentMap = {};
|
|
|
+ this.dispatchDeviceSnapshotMap = {};
|
|
|
this.dispatchPage = 1;
|
|
|
this.loadDispatchAssignData();
|
|
|
+ this.loadDispatchDeviceSnapshots();
|
|
|
}
|
|
|
},
|
|
|
dispatchObjectRows() {
|
|
|
@@ -980,6 +1052,7 @@
|
|
|
if (!Array.isArray(list) || list.length === 0) {
|
|
|
this.activeTaskKey = '';
|
|
|
this.dispatchRowDraftMap = {};
|
|
|
+ this.dispatchDeviceSnapshotMap = {};
|
|
|
this.dispatchPage = 1;
|
|
|
return;
|
|
|
}
|
|
|
@@ -994,6 +1067,7 @@
|
|
|
}
|
|
|
this.$nextTick(() => {
|
|
|
this.loadDispatchAssignData();
|
|
|
+ this.loadDispatchDeviceSnapshots();
|
|
|
});
|
|
|
}
|
|
|
}
|
|
|
@@ -1153,6 +1227,102 @@
|
|
|
const plan = this.currentPlan || {};
|
|
|
return plan.workOrderId || plan.orderId || plan.sourceWorkOrderId || '';
|
|
|
},
|
|
|
+ getDispatchPlanId() {
|
|
|
+ const plan = this.currentPlan || {};
|
|
|
+ return plan.productionPlanId || plan.planId || plan.id || '';
|
|
|
+ },
|
|
|
+ getDeviceSnapshotRequestKey(row = this.activeTask) {
|
|
|
+ const planId = this.getDispatchPlanId();
|
|
|
+ const taskId = this.getDispatchSourceTaskId(row);
|
|
|
+ return planId && taskId ? `${planId}::${taskId}` : '';
|
|
|
+ },
|
|
|
+ normalizeDeviceSnapshotCode(value) {
|
|
|
+ if (value === null || value === undefined || value === '') {
|
|
|
+ return '';
|
|
|
+ }
|
|
|
+ return String(value).trim();
|
|
|
+ },
|
|
|
+ getDispatchDeviceSnapshotCandidateCodes(row) {
|
|
|
+ return [
|
|
|
+ row?.assetCode,
|
|
|
+ row?.deviceCode,
|
|
|
+ row?.extInfo?.assetCode,
|
|
|
+ row?.extInfo?.deviceCode
|
|
|
+ ]
|
|
|
+ .map((item) => this.normalizeDeviceSnapshotCode(item))
|
|
|
+ .filter(Boolean);
|
|
|
+ },
|
|
|
+ isDeviceSnapshotLocked(row) {
|
|
|
+ if (!this.orderDispatchStyle || !row) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ const requestKey = this.getDeviceSnapshotRequestKey();
|
|
|
+ if (
|
|
|
+ !requestKey ||
|
|
|
+ !Object.prototype.hasOwnProperty.call(
|
|
|
+ this.dispatchDeviceSnapshotMap,
|
|
|
+ requestKey
|
|
|
+ )
|
|
|
+ ) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ const snapshotCodes = this.dispatchDeviceSnapshotMap[requestKey] || {};
|
|
|
+ return !this.getDispatchDeviceSnapshotCandidateCodes(row).some(
|
|
|
+ (code) => snapshotCodes[code]
|
|
|
+ );
|
|
|
+ },
|
|
|
+ clearDeviceSnapshotLockedSelections() {
|
|
|
+ this.dispatchObjectRows.forEach((row) => {
|
|
|
+ if (
|
|
|
+ this.isDeviceSnapshotLocked(row) &&
|
|
|
+ this.isSelectedDispatchObject(row)
|
|
|
+ ) {
|
|
|
+ this.clearDispatchObject(row);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ },
|
|
|
+ async loadDispatchDeviceSnapshots() {
|
|
|
+ if (
|
|
|
+ !this.orderDispatchStyle ||
|
|
|
+ this.readonlyMode ||
|
|
|
+ !this.activeTask ||
|
|
|
+ !this.currentPlan
|
|
|
+ ) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ const planId = this.getDispatchPlanId();
|
|
|
+ const taskId = this.getDispatchSourceTaskId(this.activeTask);
|
|
|
+ const requestKey = this.getDeviceSnapshotRequestKey(this.activeTask);
|
|
|
+ if (!planId || !taskId || !requestKey) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ this.dispatchDeviceSnapshotLoading = true;
|
|
|
+ this.dispatchDeviceSnapshotRequestKey = requestKey;
|
|
|
+ try {
|
|
|
+ const res = await listByPlanIdAndTaskId({ planId, taskId });
|
|
|
+ if (this.dispatchDeviceSnapshotRequestKey !== requestKey) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ const snapshotCodes = {};
|
|
|
+ (Array.isArray(res) ? res : []).forEach((item) => {
|
|
|
+ const code = this.normalizeDeviceSnapshotCode(item?.deviceCode);
|
|
|
+ if (code) {
|
|
|
+ snapshotCodes[code] = true;
|
|
|
+ }
|
|
|
+ });
|
|
|
+ this.$set(this.dispatchDeviceSnapshotMap, requestKey, snapshotCodes);
|
|
|
+ this.clearDeviceSnapshotLockedSelections();
|
|
|
+ } catch (e) {
|
|
|
+ if (this.dispatchDeviceSnapshotRequestKey === requestKey) {
|
|
|
+ this.$delete(this.dispatchDeviceSnapshotMap, requestKey);
|
|
|
+ }
|
|
|
+ this.$message.warning(e.message || '获取工序设备快照失败');
|
|
|
+ } finally {
|
|
|
+ if (this.dispatchDeviceSnapshotRequestKey === requestKey) {
|
|
|
+ this.dispatchDeviceSnapshotLoading = false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
getDispatchWorkCenterId(row = this.activeTask) {
|
|
|
const plan = this.currentPlan || {};
|
|
|
return (
|
|
|
@@ -1408,10 +1578,13 @@
|
|
|
const statusText = this.getDispatchStatusText(data?.status);
|
|
|
return statusText === '已派单' || statusText === '派单';
|
|
|
},
|
|
|
- isDispatchRowControlDisabled() {
|
|
|
- return this.readonlyMode;
|
|
|
+ isDispatchRowControlDisabled(row) {
|
|
|
+ return this.readonlyMode || this.isDeviceSnapshotLocked(row);
|
|
|
},
|
|
|
getDispatchTableRowClassName({ row }) {
|
|
|
+ if (this.isDeviceSnapshotLocked(row)) {
|
|
|
+ return 'dispatch-row-device-locked';
|
|
|
+ }
|
|
|
return this.readonlyMode && this.isDispatchRowAssigned(row)
|
|
|
? 'dispatch-row-assigned'
|
|
|
: '';
|
|
|
@@ -1688,7 +1861,7 @@
|
|
|
});
|
|
|
},
|
|
|
ensureDispatchObjectSelected(row) {
|
|
|
- if (!this.activeTask || !row) {
|
|
|
+ if (!this.activeTask || !row || this.isDeviceSnapshotLocked(row)) {
|
|
|
return null;
|
|
|
}
|
|
|
const existed = this.getDispatchRowTask(row);
|
|
|
@@ -1738,7 +1911,7 @@
|
|
|
row.quantity = this.formatDispatchRowQuantity(task.quantity);
|
|
|
},
|
|
|
handleDispatchObjectCheckChange(row, checked) {
|
|
|
- if (this.readonlyMode) {
|
|
|
+ if (this.isDispatchRowControlDisabled(row)) {
|
|
|
return;
|
|
|
}
|
|
|
if (checked) {
|
|
|
@@ -1907,7 +2080,7 @@
|
|
|
if (this.readonlyMode) {
|
|
|
return;
|
|
|
}
|
|
|
- this.pagedDispatchObjectRows.forEach((row) => {
|
|
|
+ this.currentPageSelectableDispatchRows.forEach((row) => {
|
|
|
this.handleDispatchObjectCheckChange(row, checked);
|
|
|
});
|
|
|
},
|
|
|
@@ -2906,6 +3079,16 @@
|
|
|
content: '';
|
|
|
}
|
|
|
|
|
|
+ .el-table__body tr.dispatch-row-device-locked > td.el-table__cell {
|
|
|
+ color: #8a96a3;
|
|
|
+ background: #f4f6f8;
|
|
|
+ cursor: not-allowed;
|
|
|
+ }
|
|
|
+
|
|
|
+ .el-table__body tr.dispatch-row-device-locked:hover > td.el-table__cell {
|
|
|
+ background: #eef2f6;
|
|
|
+ }
|
|
|
+
|
|
|
.el-table__body-wrapper::-webkit-scrollbar {
|
|
|
width: 8px;
|
|
|
height: 8px;
|
|
|
@@ -2972,6 +3155,19 @@
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ .dispatch-checkbox-wrap,
|
|
|
+ .dispatch-workstation-name,
|
|
|
+ .dispatch-disabled-field {
|
|
|
+ display: inline-block;
|
|
|
+ width: 100%;
|
|
|
+ }
|
|
|
+
|
|
|
+ .dispatch-workstation-name {
|
|
|
+ overflow: hidden;
|
|
|
+ text-overflow: ellipsis;
|
|
|
+ white-space: nowrap;
|
|
|
+ }
|
|
|
+
|
|
|
@media (max-width: 576px) {
|
|
|
.config-panel {
|
|
|
padding: 8px;
|
|
|
@@ -3040,4 +3236,60 @@
|
|
|
font-size: 13px;
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ .dispatch-workstation-tooltip {
|
|
|
+ max-width: 260px;
|
|
|
+ z-index: 4000 !important;
|
|
|
+ line-height: 1.5;
|
|
|
+ word-break: break-all;
|
|
|
+ }
|
|
|
+
|
|
|
+ .dispatch-device-lock-tooltip {
|
|
|
+ min-width: 190px;
|
|
|
+ max-width: 320px;
|
|
|
+ z-index: 7000 !important;
|
|
|
+ padding: 10px 14px 10px 18px;
|
|
|
+ border: 1px solid #ff8a00;
|
|
|
+ border-left: 4px solid #ff5f00;
|
|
|
+ border-radius: 6px;
|
|
|
+ color: #7a2d00 !important;
|
|
|
+ background: linear-gradient(180deg, #fff7dc 0%, #ffe8bd 100%) !important;
|
|
|
+ box-shadow: 0 10px 24px rgba(180, 83, 9, 0.28),
|
|
|
+ inset 0 0 0 1px rgba(255, 255, 255, 0.65);
|
|
|
+ font-size: 14px;
|
|
|
+ font-weight: 700;
|
|
|
+ line-height: 1.45;
|
|
|
+ }
|
|
|
+
|
|
|
+ .dispatch-device-lock-tooltip[x-placement^='top'] .popper__arrow {
|
|
|
+ border-top-color: #ff9f1a !important;
|
|
|
+ }
|
|
|
+
|
|
|
+ .dispatch-device-lock-tooltip[x-placement^='top'] .popper__arrow::after {
|
|
|
+ border-top-color: #fff3dc !important;
|
|
|
+ }
|
|
|
+
|
|
|
+ .dispatch-device-lock-tooltip[x-placement^='bottom'] .popper__arrow {
|
|
|
+ border-bottom-color: #ff9f1a !important;
|
|
|
+ }
|
|
|
+
|
|
|
+ .dispatch-device-lock-tooltip[x-placement^='bottom'] .popper__arrow::after {
|
|
|
+ border-bottom-color: #fff3dc !important;
|
|
|
+ }
|
|
|
+
|
|
|
+ .dispatch-device-lock-tooltip[x-placement^='left'] .popper__arrow {
|
|
|
+ border-left-color: #ff9f1a !important;
|
|
|
+ }
|
|
|
+
|
|
|
+ .dispatch-device-lock-tooltip[x-placement^='left'] .popper__arrow::after {
|
|
|
+ border-left-color: #fff3dc !important;
|
|
|
+ }
|
|
|
+
|
|
|
+ .dispatch-device-lock-tooltip[x-placement^='right'] .popper__arrow {
|
|
|
+ border-right-color: #ff9f1a !important;
|
|
|
+ }
|
|
|
+
|
|
|
+ .dispatch-device-lock-tooltip[x-placement^='right'] .popper__arrow::after {
|
|
|
+ border-right-color: #fff3dc !important;
|
|
|
+ }
|
|
|
</style>
|