fix(resource-status): sort machine names, fix LOT click, support multi-select matrix filter
- Sort level-2 resource nodes alphabetically in status matrix hierarchy - Fix LOT_COUNT using raw row count when no valid RUNCARDLOTID exists, causing LOT badge to render but click to silently fail - Change matrix cell filter from single-select to multi-select (OR logic) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -40,7 +40,7 @@ const filterState = reactive({
|
|||||||
isMonitor: false,
|
isMonitor: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
const matrixFilter = ref(null);
|
const matrixFilter = ref([]);
|
||||||
const summaryStatusFilter = ref(null);
|
const summaryStatusFilter = ref(null);
|
||||||
const hierarchyState = reactive({});
|
const hierarchyState = reactive({});
|
||||||
|
|
||||||
@@ -146,7 +146,7 @@ async function loadEquipment() {
|
|||||||
const data = unwrapApiResult(result, '載入設備資料失敗');
|
const data = unwrapApiResult(result, '載入設備資料失敗');
|
||||||
|
|
||||||
allEquipment.value = Array.isArray(data) ? data : [];
|
allEquipment.value = Array.isArray(data) ? data : [];
|
||||||
matrixFilter.value = null;
|
matrixFilter.value = [];
|
||||||
summaryStatusFilter.value = null;
|
summaryStatusFilter.value = null;
|
||||||
resetHierarchyState();
|
resetHierarchyState();
|
||||||
}
|
}
|
||||||
@@ -185,11 +185,7 @@ async function checkCacheStatus() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildMatrixFilterLabel(filter) {
|
function buildSingleFilterLabel(filter) {
|
||||||
if (!filter) {
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
|
|
||||||
const parts = [filter.workcenter_group];
|
const parts = [filter.workcenter_group];
|
||||||
if (filter.family) {
|
if (filter.family) {
|
||||||
parts.push(filter.family);
|
parts.push(filter.family);
|
||||||
@@ -198,28 +194,15 @@ function buildMatrixFilterLabel(filter) {
|
|||||||
const resource = allEquipment.value.find((item) => item.RESOURCEID === filter.resource);
|
const resource = allEquipment.value.find((item) => item.RESOURCEID === filter.resource);
|
||||||
parts.push(resource?.RESOURCENAME || filter.resource);
|
parts.push(resource?.RESOURCENAME || filter.resource);
|
||||||
}
|
}
|
||||||
|
|
||||||
parts.push(STATUS_DISPLAY_MAP[filter.status] || filter.status);
|
parts.push(STATUS_DISPLAY_MAP[filter.status] || filter.status);
|
||||||
return `矩陣篩選: ${parts.join(' / ')}`;
|
return parts.join(' / ');
|
||||||
}
|
}
|
||||||
|
|
||||||
function isSameMatrixFilter(left, right) {
|
function filterKey(f) {
|
||||||
if (!left || !right) {
|
return `${f.workcenter_group}|${f.status}|${f.family || ''}|${f.resource || ''}`;
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
(left.workcenter_group || null) === (right.workcenter_group || null) &&
|
|
||||||
(left.status || null) === (right.status || null) &&
|
|
||||||
(left.family || null) === (right.family || null) &&
|
|
||||||
(left.resource || null) === (right.resource || null)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function matchMatrixFilter(eq, filter) {
|
function matchSingleFilter(eq, filter) {
|
||||||
if (!filter) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((eq.WORKCENTER_GROUP || 'UNKNOWN') !== filter.workcenter_group) {
|
if ((eq.WORKCENTER_GROUP || 'UNKNOWN') !== filter.workcenter_group) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -229,13 +212,13 @@ function matchMatrixFilter(eq, filter) {
|
|||||||
if (filter.resource && (eq.RESOURCEID || null) !== filter.resource) {
|
if (filter.resource && (eq.RESOURCEID || null) !== filter.resource) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return normalizeStatus(eq.EQUIPMENTASSETSSTATUS) === filter.status;
|
return normalizeStatus(eq.EQUIPMENTASSETSSTATUS) === filter.status;
|
||||||
}
|
}
|
||||||
|
|
||||||
const displayedEquipment = computed(() => {
|
const displayedEquipment = computed(() => {
|
||||||
|
const filters = matrixFilter.value;
|
||||||
return allEquipment.value.filter((eq) => {
|
return allEquipment.value.filter((eq) => {
|
||||||
if (matrixFilter.value && !matchMatrixFilter(eq, matrixFilter.value)) {
|
if (filters.length > 0 && !filters.some((f) => matchSingleFilter(eq, f))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (summaryStatusFilter.value && normalizeStatus(eq.EQUIPMENTASSETSSTATUS) !== summaryStatusFilter.value) {
|
if (summaryStatusFilter.value && normalizeStatus(eq.EQUIPMENTASSETSSTATUS) !== summaryStatusFilter.value) {
|
||||||
@@ -248,9 +231,9 @@ const displayedEquipment = computed(() => {
|
|||||||
const activeFilterText = computed(() => {
|
const activeFilterText = computed(() => {
|
||||||
const labels = [];
|
const labels = [];
|
||||||
|
|
||||||
const matrixLabel = buildMatrixFilterLabel(matrixFilter.value);
|
if (matrixFilter.value.length > 0) {
|
||||||
if (matrixLabel) {
|
const parts = matrixFilter.value.map(buildSingleFilterLabel);
|
||||||
labels.push(matrixLabel);
|
labels.push(`矩陣篩選: ${parts.join(' + ')}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (summaryStatusFilter.value) {
|
if (summaryStatusFilter.value) {
|
||||||
@@ -261,20 +244,23 @@ const activeFilterText = computed(() => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
function applyMatrixFilter(nextFilter) {
|
function applyMatrixFilter(nextFilter) {
|
||||||
if (isSameMatrixFilter(matrixFilter.value, nextFilter)) {
|
const entry = {
|
||||||
matrixFilter.value = null;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
matrixFilter.value = {
|
|
||||||
workcenter_group: nextFilter.workcenter_group,
|
workcenter_group: nextFilter.workcenter_group,
|
||||||
status: nextFilter.status,
|
status: nextFilter.status,
|
||||||
family: nextFilter.family || null,
|
family: nextFilter.family || null,
|
||||||
resource: nextFilter.resource || null,
|
resource: nextFilter.resource || null,
|
||||||
};
|
};
|
||||||
|
const key = filterKey(entry);
|
||||||
|
const idx = matrixFilter.value.findIndex((f) => filterKey(f) === key);
|
||||||
|
if (idx >= 0) {
|
||||||
|
matrixFilter.value = matrixFilter.value.filter((_, i) => i !== idx);
|
||||||
|
} else {
|
||||||
|
matrixFilter.value = [...matrixFilter.value, entry];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function clearAllEquipmentFilters() {
|
function clearAllEquipmentFilters() {
|
||||||
matrixFilter.value = null;
|
matrixFilter.value = [];
|
||||||
summaryStatusFilter.value = null;
|
summaryStatusFilter.value = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,8 +19,8 @@ const props = defineProps({
|
|||||||
default: () => ({}),
|
default: () => ({}),
|
||||||
},
|
},
|
||||||
matrixFilter: {
|
matrixFilter: {
|
||||||
type: Object,
|
type: Array,
|
||||||
default: null,
|
default: () => [],
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -84,17 +84,19 @@ function calcOuPct(counts) {
|
|||||||
return (Number(counts.PRD || 0) / denominator) * 100;
|
return (Number(counts.PRD || 0) / denominator) * 100;
|
||||||
}
|
}
|
||||||
|
|
||||||
function isMatrixFilterMatch(filter, { group, status, family = null, resource = null }) {
|
function isMatrixFilterMatch(filters, { group, status, family = null, resource = null }) {
|
||||||
if (!filter) {
|
if (!filters || filters.length === 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const sameGroup = filter.workcenter_group === group;
|
return filters.some((f) => {
|
||||||
const sameStatus = filter.status === status;
|
return (
|
||||||
const sameFamily = (filter.family || null) === (family || null);
|
f.workcenter_group === group &&
|
||||||
const sameResource = (filter.resource || null) === (resource || null);
|
f.status === status &&
|
||||||
|
(f.family || null) === (family || null) &&
|
||||||
return sameGroup && sameStatus && sameFamily && sameResource;
|
(f.resource || null) === (resource || null)
|
||||||
|
);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildMatrixHierarchy(equipment) {
|
function buildMatrixHierarchy(equipment) {
|
||||||
@@ -155,6 +157,10 @@ function buildMatrixHierarchy(equipment) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
groupNode.children.forEach((familyNode) => {
|
groupNode.children.forEach((familyNode) => {
|
||||||
|
familyNode.children.sort((left, right) =>
|
||||||
|
String(left.name).localeCompare(String(right.name), 'zh-Hant')
|
||||||
|
);
|
||||||
|
|
||||||
familyNode.selectedColumns = Object.fromEntries(
|
familyNode.selectedColumns = Object.fromEntries(
|
||||||
MATRIX_STATUS_COLUMNS.map((status) => [
|
MATRIX_STATUS_COLUMNS.map((status) => [
|
||||||
status,
|
status,
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user