diff --git a/frontend/src/excel-query/composables/useExcelQueryData.js b/frontend/src/excel-query/composables/useExcelQueryData.js
index 2542fb9..c7cd752 100644
--- a/frontend/src/excel-query/composables/useExcelQueryData.js
+++ b/frontend/src/excel-query/composables/useExcelQueryData.js
@@ -132,7 +132,7 @@ export function useExcelQueryData() {
try {
const formData = new FormData();
formData.append('file', file);
- const payload = await apiUpload('/api/excel-query/upload', formData, { timeout: 120000, silent: true });
+ const payload = await apiUpload('/api/excel-query/upload', formData, { timeout: 360000, silent: true });
excelColumns.value = Array.isArray(payload?.columns) ? payload.columns : [];
excelPreview.value = Array.isArray(payload?.preview) ? payload.preview : [];
uploadState.fileName = String(file.name || '');
@@ -252,7 +252,7 @@ export function useExcelQueryData() {
date_from: filters.dateFrom || undefined,
date_to: filters.dateTo || undefined,
},
- { timeout: 120000, silent: true },
+ { timeout: 360000, silent: true },
);
queryResult.rows = Array.isArray(payload?.data) ? payload.data : [];
queryResult.columns = Array.isArray(payload?.columns) ? payload.columns : filters.returnColumns;
diff --git a/frontend/src/hold-history/App.vue b/frontend/src/hold-history/App.vue
index 2fb6ef9..6b14458 100644
--- a/frontend/src/hold-history/App.vue
+++ b/frontend/src/hold-history/App.vue
@@ -1,7 +1,7 @@
diff --git a/frontend/src/job-query/composables/useJobQueryData.js b/frontend/src/job-query/composables/useJobQueryData.js
index 8aa45b5..0acea9f 100644
--- a/frontend/src/job-query/composables/useJobQueryData.js
+++ b/frontend/src/job-query/composables/useJobQueryData.js
@@ -174,7 +174,7 @@ export function useJobQueryData() {
loadingResources.value = true;
errorMessage.value = '';
try {
- const payload = await apiGet('/api/job-query/resources', { timeout: 60000, silent: true });
+ const payload = await apiGet('/api/job-query/resources', { timeout: 360000, silent: true });
resources.value = Array.isArray(payload?.data) ? payload.data : [];
} catch (error) {
errorMessage.value = error?.message || '載入設備清單失敗';
@@ -206,7 +206,7 @@ export function useJobQueryData() {
start_date: filters.startDate,
end_date: filters.endDate,
},
- { timeout: 60000, silent: true },
+ { timeout: 360000, silent: true },
);
jobs.value = Array.isArray(payload?.data) ? payload.data : [];
return true;
@@ -229,7 +229,7 @@ export function useJobQueryData() {
errorMessage.value = '';
try {
const payload = await apiGet(`/api/job-query/txn/${encodeURIComponent(id)}`, {
- timeout: 60000,
+ timeout: 360000,
silent: true,
});
txnRows.value = Array.isArray(payload?.data) ? payload.data : [];
diff --git a/frontend/src/mid-section-defect/App.vue b/frontend/src/mid-section-defect/App.vue
index 1c0eeb7..1d7592a 100644
--- a/frontend/src/mid-section-defect/App.vue
+++ b/frontend/src/mid-section-defect/App.vue
@@ -16,7 +16,7 @@ import SuspectContextPanel from './components/SuspectContextPanel.vue';
ensureMesApiAvailable();
-const API_TIMEOUT = 120000;
+const API_TIMEOUT = 360000;
const PAGE_SIZE = 200;
const SESSION_CACHE_KEY = 'msd:cache';
const SESSION_CACHE_TTL = 5 * 60 * 1000; // 5 min, matches backend Redis TTL
diff --git a/frontend/src/query-tool/components/LotJobsTable.vue b/frontend/src/query-tool/components/LotJobsTable.vue
index 134b0d1..a55a893 100644
--- a/frontend/src/query-tool/components/LotJobsTable.vue
+++ b/frontend/src/query-tool/components/LotJobsTable.vue
@@ -135,7 +135,7 @@ async function loadTxn(jobId) {
try {
const payload = await apiGet(`/api/job-query/txn/${encodeURIComponent(id)}`, {
- timeout: 60000,
+ timeout: 360000,
silent: true,
});
txnRows.value = Array.isArray(payload?.data) ? payload.data : [];
diff --git a/frontend/src/query-tool/composables/useEquipmentQuery.js b/frontend/src/query-tool/composables/useEquipmentQuery.js
index a6d50a9..5338093 100644
--- a/frontend/src/query-tool/composables/useEquipmentQuery.js
+++ b/frontend/src/query-tool/composables/useEquipmentQuery.js
@@ -120,7 +120,7 @@ export function useEquipmentQuery(initial = {}) {
const payload = await apiPost(
'/api/query-tool/equipment-period',
buildQueryPayload(queryType),
- { timeout: 120000, silent: true },
+ { timeout: 360000, silent: true },
);
return Array.isArray(payload?.data) ? payload.data : [];
@@ -132,7 +132,7 @@ export function useEquipmentQuery(initial = {}) {
try {
const payload = await apiGet('/api/query-tool/equipment-list', {
- timeout: 60000,
+ timeout: 360000,
silent: true,
});
equipmentOptions.value = Array.isArray(payload?.data) ? payload.data : [];
diff --git a/frontend/src/query-tool/composables/useLotDetail.js b/frontend/src/query-tool/composables/useLotDetail.js
index 734d10f..8ad3a63 100644
--- a/frontend/src/query-tool/composables/useLotDetail.js
+++ b/frontend/src/query-tool/composables/useLotDetail.js
@@ -164,7 +164,7 @@ export function useLotDetail(initial = {}) {
try {
const payload = await apiGet('/api/query-tool/workcenter-groups', {
- timeout: 60000,
+ timeout: 360000,
silent: true,
});
@@ -205,7 +205,7 @@ export function useLotDetail(initial = {}) {
}
const payload = await apiGet(`/api/query-tool/lot-history?${params.toString()}`, {
- timeout: 120000,
+ timeout: 360000,
silent: true,
});
@@ -263,7 +263,7 @@ export function useLotDetail(initial = {}) {
params.set('time_end', timeRange.time_end);
const payload = await apiGet(`/api/query-tool/lot-associations?${params.toString()}`, {
- timeout: 120000,
+ timeout: 360000,
silent: true,
});
@@ -279,7 +279,7 @@ export function useLotDetail(initial = {}) {
params.set('type', associationType);
const payload = await apiGet(`/api/query-tool/lot-associations?${params.toString()}`, {
- timeout: 120000,
+ timeout: 360000,
silent: true,
});
diff --git a/frontend/src/query-tool/composables/useLotLineage.js b/frontend/src/query-tool/composables/useLotLineage.js
index 276bcae..859ec59 100644
--- a/frontend/src/query-tool/composables/useLotLineage.js
+++ b/frontend/src/query-tool/composables/useLotLineage.js
@@ -205,7 +205,7 @@ export function useLotLineage(initial = {}) {
profile: 'query_tool',
container_ids: containerIds,
},
- { timeout: 60000, silent: true },
+ { timeout: 360000, silent: true },
);
} catch (error) {
const status = Number(error?.status || 0);
diff --git a/frontend/src/query-tool/composables/useLotResolve.js b/frontend/src/query-tool/composables/useLotResolve.js
index 279336a..0cc46ae 100644
--- a/frontend/src/query-tool/composables/useLotResolve.js
+++ b/frontend/src/query-tool/composables/useLotResolve.js
@@ -134,7 +134,7 @@ export function useLotResolve(initial = {}) {
input_type: inputType.value,
values,
},
- { timeout: 60000, silent: true },
+ { timeout: 360000, silent: true },
);
resolvedLots.value = Array.isArray(payload?.data) ? payload.data : [];
diff --git a/frontend/src/query-tool/composables/useReverseLineage.js b/frontend/src/query-tool/composables/useReverseLineage.js
index 588db38..44ae418 100644
--- a/frontend/src/query-tool/composables/useReverseLineage.js
+++ b/frontend/src/query-tool/composables/useReverseLineage.js
@@ -216,7 +216,7 @@ export function useReverseLineage(initial = {}) {
profile: 'query_tool_reverse',
container_ids: containerIds,
},
- { timeout: 60000, silent: true },
+ { timeout: 360000, silent: true },
);
} catch (error) {
const status = Number(error?.status || 0);
diff --git a/frontend/src/reject-history/App.vue b/frontend/src/reject-history/App.vue
index b3bd626..f888155 100644
--- a/frontend/src/reject-history/App.vue
+++ b/frontend/src/reject-history/App.vue
@@ -15,7 +15,7 @@ import ParetoSection from './components/ParetoSection.vue';
import SummaryCards from './components/SummaryCards.vue';
import TrendChart from './components/TrendChart.vue';
-const API_TIMEOUT = 60000;
+const API_TIMEOUT = 360000;
const DEFAULT_PER_PAGE = 50;
// ---- Primary query form state ----
@@ -214,7 +214,11 @@ async function executePrimaryQuery() {
updateUrlState();
} catch (error) {
if (isStaleRequest(requestId)) return;
- errorMessage.value = error?.message || '主查詢執行失敗';
+ if (error?.name === 'AbortError') {
+ errorMessage.value = '查詢逾時,請縮短日期範圍後重試';
+ } else {
+ errorMessage.value = error?.message || '主查詢執行失敗';
+ }
} finally {
if (isStaleRequest(requestId)) return;
loading.querying = false;
@@ -264,7 +268,11 @@ async function refreshView() {
updateUrlState();
} catch (error) {
if (isStaleRequest(requestId)) return;
- errorMessage.value = error?.message || '視圖查詢失敗';
+ if (error?.name === 'AbortError') {
+ errorMessage.value = '查詢逾時,請縮短日期範圍後重試';
+ } else {
+ errorMessage.value = error?.message || '視圖查詢失敗';
+ }
} finally {
if (isStaleRequest(requestId)) return;
loading.list = false;
@@ -360,7 +368,9 @@ async function fetchDimensionPareto(dim) {
} catch (err) {
if (myId !== activeDimRequestId) return;
dimensionParetoItems.value = [];
- errorMessage.value = err.message || '查詢維度 Pareto 失敗';
+ if (err?.name !== 'AbortError') {
+ errorMessage.value = err.message || '查詢維度 Pareto 失敗';
+ }
} finally {
if (myId === activeDimRequestId) {
dimensionParetoLoading.value = false;
diff --git a/frontend/src/resource-history/App.vue b/frontend/src/resource-history/App.vue
index 52f10da..ff27090 100644
--- a/frontend/src/resource-history/App.vue
+++ b/frontend/src/resource-history/App.vue
@@ -1,7 +1,7 @@