diff --git a/frontend/index.html b/frontend/index.html index f6bc449..b87e23f 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -7,8 +7,8 @@ - - MiroFish Offline - Predict Everything + + The Pin Factory - Predict Everything diff --git a/frontend/public/home-styles.css b/frontend/public/home-styles.css index c1590c1..4096a11 100644 --- a/frontend/public/home-styles.css +++ b/frontend/public/home-styles.css @@ -80,7 +80,7 @@ } .orange-tag { - background: #FF4500; + background: #5BA4F5; color: #FFFFFF; padding: 4px 10px; font-weight: 700; @@ -104,7 +104,7 @@ } .gradient-text { - background: linear-gradient(90deg, #000000 0%, #444444 100%); + background: linear-gradient(90deg, #1565C0 0%, #5BA4F5 100%); -webkit-background-clip: text; -webkit-text-fill-color: transparent; display: inline-block; @@ -130,7 +130,7 @@ } .highlight-orange { - color: #FF4500; + color: #5BA4F5; font-weight: 700; font-family: 'JetBrains Mono', monospace; } @@ -150,13 +150,13 @@ font-weight: 520; color: #000000; letter-spacing: 1px; - border-left: 3px solid #FF4500; + border-left: 3px solid #5BA4F5; padding-left: 15px; margin-top: 20px; } .blinking-cursor { - color: #FF4500; + color: #5BA4F5; animation: blink 1s step-end infinite; font-weight: 700; } @@ -169,7 +169,7 @@ .decoration-square { width: 16px; height: 16px; - background: #FF4500; + background: #5BA4F5; } .hero-right { @@ -201,13 +201,13 @@ align-items: center; justify-content: center; cursor: pointer; - color: #FF4500; + color: #5BA4F5; font-size: 1.2rem; transition: all 0.2s; } .scroll-down-btn:hover { - border-color: #FF4500; + border-color: #5BA4F5; } /* Dashboard Two-Column Layout */ @@ -241,7 +241,7 @@ } .status-dot { - color: #FF4500; + color: #5BA4F5; font-size: 0.8rem; } @@ -520,8 +520,8 @@ } .start-engine-btn:hover:not(:disabled) { - background: #FF4500; - border-color: #FF4500; + background: #5BA4F5; + border-color: #5BA4F5; transform: translateY(-2px); } @@ -539,9 +539,9 @@ /* Pulse animation for border */ @keyframes pulse-border { - 0% { box-shadow: 0 0 0 0 rgba(0, 0, 0, 0.2); } - 70% { box-shadow: 0 0 0 6px rgba(0, 0, 0, 0); } - 100% { box-shadow: 0 0 0 0 rgba(0, 0, 0, 0); } + 0% { box-shadow: 0 0 0 0 rgba(91, 164, 245, 0.4); } + 70% { box-shadow: 0 0 0 6px rgba(91, 164, 245, 0); } + 100% { box-shadow: 0 0 0 0 rgba(91, 164, 245, 0); } } /* Responsive */ diff --git a/frontend/src/App.vue b/frontend/src/App.vue index 702be81..2df1814 100644 --- a/frontend/src/App.vue +++ b/frontend/src/App.vue @@ -122,7 +122,7 @@ button { } .orange-tag { - background: #FF4500; + background: #5BA4F5; color: #FFFFFF; padding: 4px 10px; font-weight: 700; @@ -146,7 +146,7 @@ button { } .gradient-text { - background: linear-gradient(90deg, #000000 0%, #444444 100%); + background: linear-gradient(90deg, #1565C0 0%, #5BA4F5 100%); -webkit-background-clip: text; -webkit-text-fill-color: transparent; display: inline-block; @@ -172,7 +172,7 @@ button { } .highlight-orange { - color: #FF4500; + color: #5BA4F5; font-weight: 700; font-family: 'JetBrains Mono', monospace; } @@ -192,13 +192,13 @@ button { font-weight: 520; color: #000000; letter-spacing: 1px; - border-left: 3px solid #FF4500; + border-left: 3px solid #5BA4F5; padding-left: 15px; margin-top: 20px; } .blinking-cursor { - color: #FF4500; + color: #5BA4F5; animation: blink 1s step-end infinite; font-weight: 700; } @@ -211,7 +211,7 @@ button { .decoration-square { width: 16px; height: 16px; - background: #FF4500; + background: #5BA4F5; } .hero-right { @@ -243,13 +243,13 @@ button { align-items: center; justify-content: center; cursor: pointer; - color: #FF4500; + color: #5BA4F5; font-size: 1.2rem; transition: all 0.2s; } .scroll-down-btn:hover { - border-color: #FF4500; + border-color: #5BA4F5; } .dashboard-section { @@ -281,7 +281,7 @@ button { } .status-dot { - color: #FF4500; + color: #5BA4F5; font-size: 0.8rem; } @@ -557,8 +557,8 @@ button { } .start-engine-btn:hover:not(:disabled) { - background: #FF4500; - border-color: #FF4500; + background: #5BA4F5; + border-color: #5BA4F5; transform: translateY(-2px); } @@ -575,9 +575,9 @@ button { } @keyframes pulse-border { - 0% { box-shadow: 0 0 0 0 rgba(0, 0, 0, 0.2); } - 70% { box-shadow: 0 0 0 6px rgba(0, 0, 0, 0); } - 100% { box-shadow: 0 0 0 0 rgba(0, 0, 0, 0); } + 0% { box-shadow: 0 0 0 0 rgba(91, 164, 245, 0.4); } + 70% { box-shadow: 0 0 0 6px rgba(91, 164, 245, 0); } + 100% { box-shadow: 0 0 0 0 rgba(91, 164, 245, 0); } } @media (max-width: 1024px) { diff --git a/frontend/src/api/index.js b/frontend/src/api/index.js index fe51e53..4baa13c 100644 --- a/frontend/src/api/index.js +++ b/frontend/src/api/index.js @@ -33,9 +33,11 @@ service.interceptors.response.use( return res }, - error => { + async error => { console.error('Response error:', error) + const config = error.config + // Handle timeout if (error.code === 'ECONNABORTED' && error.message.includes('timeout')) { console.error('Request timeout') @@ -46,6 +48,25 @@ service.interceptors.response.use( console.error('Network error - please check your connection') } + // Retry logic for transient failures (network errors, timeouts, 5xx server errors) + if (config) { + config.__retryCount = config.__retryCount || 0 + const maxRetries = config.__maxRetries !== undefined ? config.__maxRetries : 3 + const retryDelay = config.__retryDelay || 1000 + + const isTimeout = error.code === 'ECONNABORTED' && error.message.includes('timeout') + const isNetworkError = error.message === 'Network Error' + const isServerError = error.response && error.response.status >= 500 + + if ((isTimeout || isNetworkError || isServerError) && config.__retryCount < maxRetries) { + config.__retryCount += 1 + const delay = retryDelay * Math.pow(2, config.__retryCount - 1) + console.warn(`Request failed, retrying (${config.__retryCount}/${maxRetries}) after ${delay}ms...`) + await new Promise(resolve => setTimeout(resolve, delay)) + return service(config) + } + } + return Promise.reject(error) } ) diff --git a/frontend/src/components/Step2EnvSetup.vue b/frontend/src/components/Step2EnvSetup.vue index 67a4f1d..66cc7ff 100644 --- a/frontend/src/components/Step2EnvSetup.vue +++ b/frontend/src/components/Step2EnvSetup.vue @@ -440,7 +440,7 @@
Simulation Rounds Setting - MiroFish Automatically plan and infer reality {{ simulationConfig?.time_config?.total_simulation_hours || '-' }} hours,Each round represents reality {{ simulationConfig?.time_config?.minutes_per_round || '-' }} minutes time elapsed + The Pin Factory automatically plans and infers reality {{ simulationConfig?.time_config?.total_simulation_hours || '-' }} hours,Each round represents reality {{ simulationConfig?.time_config?.minutes_per_round || '-' }} minutes time elapsed
@@ -160,26 +160,26 @@ const s = reactive({ heroSection: { display: 'flex', justifyContent: 'space-between', marginBottom: '80px', position: 'relative' }, heroLeft: { flex: '1', paddingRight: '60px' }, tagRow: { display: 'flex', alignItems: 'center', gap: '15px', marginBottom: '25px', fontFamily: mono, fontSize: '0.8rem' }, - orangeTag: { background: '#FF4500', color: '#fff', padding: '4px 10px', fontWeight: '700', letterSpacing: '1px', fontSize: '0.75rem' }, + orangeTag: { background: '#5BA4F5', color: '#fff', padding: '4px 10px', fontWeight: '700', letterSpacing: '1px', fontSize: '0.75rem' }, versionText: { color: '#999', fontWeight: '500', letterSpacing: '0.5px' }, mainTitle: { fontSize: '4.5rem', lineHeight: '1.2', fontWeight: '500', margin: '0 0 40px 0', letterSpacing: '-2px', color: '#000' }, - gradientText: { background: 'linear-gradient(90deg, #000 0%, #444 100%)', WebkitBackgroundClip: 'text', WebkitTextFillColor: 'transparent', display: 'inline-block' }, + gradientText: { background: 'linear-gradient(90deg, #1565C0 0%, #5BA4F5 100%)', WebkitBackgroundClip: 'text', WebkitTextFillColor: 'transparent', display: 'inline-block' }, heroDesc: { fontSize: '1.05rem', lineHeight: '1.8', color: '#666', maxWidth: '640px', marginBottom: '50px', fontWeight: '400', textAlign: 'justify' }, heroDescP: { marginBottom: '1.5rem' }, highlightBold: { color: '#000', fontWeight: '700' }, - highlightOrange: { color: '#FF4500', fontWeight: '700', fontFamily: mono }, + highlightOrange: { color: '#5BA4F5', fontWeight: '700', fontFamily: mono }, highlightCode: { background: 'rgba(0,0,0,0.05)', padding: '2px 6px', borderRadius: '2px', fontFamily: mono, fontSize: '0.9em', color: '#000', fontWeight: '600' }, - sloganText: { fontSize: '1.2rem', fontWeight: '520', color: '#000', letterSpacing: '1px', borderLeft: '3px solid #FF4500', paddingLeft: '15px', marginTop: '20px' }, - blinkingCursor: { color: '#FF4500', fontWeight: '700' }, - decorationSquare: { width: '16px', height: '16px', background: '#FF4500' }, + sloganText: { fontSize: '1.2rem', fontWeight: '520', color: '#000', letterSpacing: '1px', borderLeft: '3px solid #5BA4F5', paddingLeft: '15px', marginTop: '20px' }, + blinkingCursor: { color: '#5BA4F5', fontWeight: '700' }, + decorationSquare: { width: '16px', height: '16px', background: '#5BA4F5' }, heroRight: { flex: '0.8', display: 'flex', flexDirection: 'column', justifyContent: 'space-between', alignItems: 'flex-end' }, logoContainer: { width: '100%', display: 'flex', justifyContent: 'flex-end', paddingRight: '40px' }, heroLogo: { maxWidth: '500px', width: '100%' }, - scrollDownBtn: { width: '40px', height: '40px', border: '1px solid #E5E5E5', background: 'transparent', display: 'flex', alignItems: 'center', justifyContent: 'center', cursor: 'pointer', color: '#FF4500', fontSize: '1.2rem' }, + scrollDownBtn: { width: '40px', height: '40px', border: '1px solid #E5E5E5', background: 'transparent', display: 'flex', alignItems: 'center', justifyContent: 'center', cursor: 'pointer', color: '#5BA4F5', fontSize: '1.2rem' }, dashboardSection: { display: 'flex', gap: '60px', borderTop: '1px solid #E5E5E5', paddingTop: '60px', alignItems: 'flex-start' }, leftPanel: { flex: '0.8', display: 'flex', flexDirection: 'column' }, panelHeader: { fontFamily: mono, fontSize: '0.8rem', color: '#999', display: 'flex', alignItems: 'center', gap: '8px', marginBottom: '20px' }, - statusDot: { color: '#FF4500', fontSize: '0.8rem' }, + statusDot: { color: '#5BA4F5', fontSize: '0.8rem' }, sectionTitle: { fontSize: '2rem', fontWeight: '520', margin: '0 0 15px 0' }, sectionDesc: { color: '#666', marginBottom: '25px', lineHeight: '1.6' }, metricsRow: { display: 'flex', gap: '20px', marginBottom: '15px' }, diff --git a/frontend/src/views/InteractionView.vue b/frontend/src/views/InteractionView.vue index b2eae1e..5142c50 100644 --- a/frontend/src/views/InteractionView.vue +++ b/frontend/src/views/InteractionView.vue @@ -3,7 +3,7 @@
-
MIROFISH OFFLINE
+
THE PIN FACTORY
diff --git a/frontend/src/views/MainView.vue b/frontend/src/views/MainView.vue index 8c6a120..e8a4feb 100644 --- a/frontend/src/views/MainView.vue +++ b/frontend/src/views/MainView.vue @@ -3,7 +3,7 @@
-
MIROFISH OFFLINE
+
THE PIN FACTORY
diff --git a/frontend/src/views/Process.vue b/frontend/src/views/Process.vue index 6bb930d..f2d5d44 100644 --- a/frontend/src/views/Process.vue +++ b/frontend/src/views/Process.vue @@ -2,7 +2,7 @@