feat(resource): migrate resource-status and resource-history from Jinja2 to Vue 3 + Vite

Rewrite both resource pages (1,697 lines vanilla JS + 3,200 lines Jinja2 templates)
as Vue 3 SFC components. Extract resource-shared/ module with shared CSS, E10 status
constants, and HierarchyTable tree component. History page charts use vue-echarts,
Status page reuses useAutoRefresh composable with 5-minute interval.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
egg
2026-02-09 18:19:32 +08:00
parent a2653b8139
commit 720e190bc6
45 changed files with 5099 additions and 4993 deletions

View File

@@ -34,64 +34,31 @@ def client(app):
return app.test_client()
class TestResourceHistoryPageAccess:
"""E2E tests for page access and navigation."""
def test_page_loads_successfully(self, client):
"""Resource history page should load without errors."""
response = client.get('/resource-history')
assert response.status_code == 200
content = response.data.decode('utf-8')
assert '設備歷史績效' in content
def test_page_contains_filter_elements(self, client):
"""Page should contain all filter elements."""
response = client.get('/resource-history')
content = response.data.decode('utf-8')
# Check for filter elements
assert 'startDate' in content
assert 'endDate' in content
# Multi-select dropdowns
assert 'workcenterGroupsDropdown' in content
assert 'familiesDropdown' in content
assert 'isProduction' in content
assert 'isKey' in content
assert 'isMonitor' in content
def test_page_contains_kpi_cards(self, client):
"""Page should contain KPI card elements."""
response = client.get('/resource-history')
content = response.data.decode('utf-8')
assert 'kpiOuPct' in content
assert 'kpiAvailabilityPct' in content
assert 'kpiPrdHours' in content
assert 'kpiUdtHours' in content
assert 'kpiSdtHours' in content
assert 'kpiEgtHours' in content
assert 'kpiMachineCount' in content
def test_page_contains_chart_containers(self, client):
"""Page should contain chart container elements."""
response = client.get('/resource-history')
content = response.data.decode('utf-8')
assert 'trendChart' in content
assert 'stackedChart' in content
assert 'comparisonChart' in content
assert 'heatmapChart' in content
def test_page_contains_table_elements(self, client):
"""Page should contain table elements."""
response = client.get('/resource-history')
content = response.data.decode('utf-8')
assert 'detailTableBody' in content
assert 'expandAllBtn' in content
assert 'collapseAllBtn' in content
assert 'exportBtn' in content
class TestResourceHistoryPageAccess:
"""E2E tests for page access and navigation."""
def test_page_loads_successfully(self, client):
"""Resource history page should load without errors."""
response = client.get('/resource-history')
assert response.status_code == 200
content = response.data.decode('utf-8')
assert '設備歷史績效' in content
def test_page_bootstrap_container_exists(self, client):
"""Resource history page should expose the Vue mount container."""
response = client.get('/resource-history')
content = response.data.decode('utf-8')
assert "id='app'" in content or 'id="app"' in content
def test_page_references_vite_module(self, client):
"""Resource history page should load the Vite module bundle."""
response = client.get('/resource-history')
content = response.data.decode('utf-8')
assert '/static/dist/resource-history.js' in content
assert 'type="module"' in content
class TestResourceHistoryAPIWorkflow:

View File

@@ -63,14 +63,14 @@ class TestTemplateIntegration(unittest.TestCase):
self.assertIn('type="module"', html)
self.assertNotIn('mes-toast-container', html)
def test_resource_page_includes_base_scripts(self):
def test_resource_page_serves_pure_vite_module(self):
response = self.client.get('/resource')
self.assertEqual(response.status_code, 200)
html = response.data.decode('utf-8')
self.assertIn('toast.js', html)
self.assertIn('mes-api.js', html)
self.assertIn('mes-toast-container', html)
self.assertIn('/static/dist/resource-status.js', html)
self.assertIn('type="module"', html)
self.assertNotIn('mes-toast-container', html)
def test_excel_query_page_includes_base_scripts(self):
response = self.client.get('/excel-query')