feat(query-tool): optimize equipment tracking UI and unify column labels

- Equipment selector shows only RESOURCENAME (remove redundant RESOURCEID)
- Equipment lots table: remove CONTAINERID, add WAFER LOT/TYPE/BOP/WORKORDER
- Rename CONTAINERNAME to LOT ID across all tables and CSV exports
- Rename PJ_TYPE/PJ_BOP/PJ_WORKORDER to TYPE/BOP/WORKORDER in history and equipment lots
- Add export formatters for equipment_lots, lot_history, and lot_rejects

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
egg
2026-02-23 20:21:15 +08:00
parent 8694780abb
commit bb58a0e119
5 changed files with 229 additions and 144 deletions

View File

@@ -27,10 +27,21 @@ const props = defineProps({
const emit = defineEmits(['export']);
const COLUMN_LABELS = Object.freeze({
CONTAINERNAME: 'LOT ID',
WAFER_LOT_ID: 'WAFER LOT',
PJ_TYPE: 'TYPE',
PJ_BOP: 'BOP',
PJ_WORKORDER: 'WORKORDER',
});
const columns = Object.freeze([
'CONTAINERID',
'CONTAINERNAME',
'WAFER_LOT_ID',
'PJ_TYPE',
'PJ_BOP',
'SPECNAME',
'PJ_WORKORDER',
'TRACKINTIMESTAMP',
'TRACKOUTTIMESTAMP',
'TRACKINQTY',
@@ -69,7 +80,7 @@ const columns = Object.freeze([
<thead>
<tr>
<th v-for="column in columns" :key="column">
{{ column }}
{{ COLUMN_LABELS[column] || column }}
</th>
</tr>
</thead>

View File

@@ -27,6 +27,13 @@ const emit = defineEmits(['update:workcenterGroups']);
const HIDDEN_COLUMNS = new Set(['CONTAINERID', 'EQUIPMENTID', 'RESOURCEID']);
const COLUMN_LABELS = Object.freeze({
CONTAINERNAME: 'LOT ID',
PJ_TYPE: 'TYPE',
PJ_BOP: 'BOP',
PJ_WORKORDER: 'WORKORDER',
});
const columns = computed(() =>
Object.keys(props.rows[0] || {}).filter((col) => !HIDDEN_COLUMNS.has(col)),
);
@@ -73,7 +80,7 @@ const workcenterOptions = computed(() => {
<thead>
<tr>
<th v-for="column in columns" :key="column">
{{ column }}
{{ COLUMN_LABELS[column] || column }}
</th>
</tr>
</thead>

View File

@@ -109,7 +109,7 @@ const sortedRows = computed(() => {
<table class="query-tool-table">
<thead>
<tr>
<th>LOT</th>
<th>LOT ID</th>
<th>WORKCENTER</th>
<th>Package</th>
<th>FUNCTION</th>

View File

@@ -81,7 +81,7 @@ export function useEquipmentQuery(initial = {}) {
const equipmentOptionItems = computed(() => {
return equipmentOptions.value.map((item) => ({
value: String(item.RESOURCEID),
label: item.RESOURCENAME ? `${item.RESOURCENAME} (${item.RESOURCEID})` : String(item.RESOURCEID),
label: item.RESOURCENAME || String(item.RESOURCEID),
}));
});

View File

@@ -143,6 +143,67 @@ def _format_lot_holds_export_rows(rows):
return normalized_rows
def _format_equipment_lots_export_rows(rows):
"""Normalize equipment lots export columns for UI/CSV consistency."""
normalized_rows = []
for row in rows or []:
normalized_rows.append({
'LOT ID': row.get('CONTAINERNAME') or row.get('CONTAINERID') or '',
'WAFER LOT': row.get('WAFER_LOT_ID', ''),
'TYPE': row.get('PJ_TYPE', ''),
'BOP': row.get('PJ_BOP', ''),
'SPECNAME': row.get('SPECNAME', ''),
'WORKORDER': row.get('PJ_WORKORDER', ''),
'TRACKINTIMESTAMP': row.get('TRACKINTIMESTAMP', ''),
'TRACKOUTTIMESTAMP': row.get('TRACKOUTTIMESTAMP', ''),
'TRACKINQTY': row.get('TRACKINQTY', ''),
'TRACKOUTQTY': row.get('TRACKOUTQTY', ''),
'EQUIPMENTNAME': row.get('EQUIPMENTNAME', ''),
'WORKCENTERNAME': row.get('WORKCENTERNAME', ''),
})
return normalized_rows
_LOT_HISTORY_COLUMN_RENAMES = {
'CONTAINERNAME': 'LOT ID',
'PJ_TYPE': 'TYPE',
'PJ_BOP': 'BOP',
'PJ_WORKORDER': 'WORKORDER',
}
_LOT_HISTORY_HIDDEN = {'CONTAINERID', 'EQUIPMENTID', 'RESOURCEID'}
def _format_lot_history_export_rows(rows):
"""Rename columns in lot history export to match frontend labels."""
normalized_rows = []
for row in rows or []:
out = {}
for key, value in row.items():
if key in _LOT_HISTORY_HIDDEN:
continue
label = _LOT_HISTORY_COLUMN_RENAMES.get(key, key)
out[label] = value if value is not None else ''
normalized_rows.append(out)
return normalized_rows
def _format_lot_rejects_export_rows(rows):
"""Rename CONTAINERNAME to LOT ID in lot rejects export."""
normalized_rows = []
for row in rows or []:
out = {}
for key, value in row.items():
if key == 'CONTAINERID':
continue
if key == 'CONTAINERNAME':
out['LOT ID'] = value or ''
else:
out[key] = value if value is not None else ''
normalized_rows.append(out)
return normalized_rows
# ============================================================
# Page Route
# ============================================================
@@ -657,6 +718,12 @@ def export_csv():
export_data = _format_lot_materials_export_rows(export_data)
elif export_type == 'lot_holds':
export_data = _format_lot_holds_export_rows(export_data)
elif export_type == 'equipment_lots':
export_data = _format_equipment_lots_export_rows(export_data)
elif export_type == 'lot_history':
export_data = _format_lot_history_export_rows(export_data)
elif export_type == 'lot_rejects':
export_data = _format_lot_rejects_export_rows(export_data)
# Stream CSV response
return Response(