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 @@