- Correct h5-app DEV_API_TARGET example from 3000 to 3201, matching
h5-app/.env and vite.config.ts (which both use 3201 as the dev proxy
target for the backend API)
- Update h5-app dev server inline comment to show :3201 consistently
- Clarify that admin-web `npm test` (vitest) runs in watch/interactive
mode by default; show `-- --run` flag for one-shot CI-style execution
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Cover repository overview, directory structure, tech stack, environment
prerequisites, local development workflow, build commands, production
deployment suggestions, Nginx reverse proxy examples, database/env var
notes, and FAQ.
Clearly distinguish the current runnable implementation (server /
h5-app / admin-web) from the target production architecture described
in SPEC.md and docs/ (Aliyun OSS, Henan Sannong device push, full
multi-tenant isolation).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Add EditProjectModal, EditProjectUserModal, ResetProjectUserPasswordModal
to the redesign worktree (ported from main workspace)
- Update ProjectDetailPage to integrate all three modals while preserving
the admin-panel/admin-kpi-grid redesigned visual language
- Add 编辑项目信息 button (with aria-label) in the hero section alongside
新增项目账号 button
- Add per-row 编辑/重置密码 action buttons (with aria-label) to the users table
- Refactor useEffect fetch into async inner function to satisfy
react-hooks/set-state-in-effect lint rule
- Fix no-explicit-any in request.ts (any → unknown for generic defaults)
- Fix no-explicit-any in tests/setup.ts (globalThis cast)
- Fix no-explicit-any in tests/project-detail-page.test.tsx (options type)
- Add TDD tests for edit-project, edit-user, and reset-password flows;
all 25 tests pass, lint clean, build succeeds
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Gate admin-detail-grid and accounts table on project existence;
renders a fallback panel instead of zero-count workspace panels when
project data is unavailable (prevents misleading partial-success UI)
- Correct '管理员与普通成员' to '项目管理员与项目经理' - the system only
supports these two roles; also fix '管理员' to '项目管理员' in the
账号概览 copy
- Replace brittle DOM-order test (findAllByText + last index) with
findByTitle, which matches the title attribute Ant Design sets on
each visual option element in the Select dropdown - unambiguous and
not order-dependent
- Add test case for empty-project fallback to cover the new guard
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Clear searchQuery after project creation so newly created projects
are visible even when a search filter is active
- Disable refresh button while loading to prevent overlapping fetches
- Fix loadProjects referenced-before-declaration lint error by moving
it to useCallback declared before useEffect; suppress
react-hooks/set-state-in-effect for the intentional async data-fetch
pattern (same pattern used in ProjectDetailPage)
- Add TDD tests first: 'clears search filter after creation' and
'disables refresh button while loading'; verified failing before impl,
passing after; all 13 tests pass with no lint errors on this file
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Add KPI overview section (项目总览) with project count, account total, and latest project cards
- Add toolbar with search input and refresh button above the project table
- Extract 'new project' button into the overview heading for better hierarchy
- Add admin-overview, admin-kpi-grid, admin-kpi-card, admin-table-section, admin-toolbar CSS classes
- Extend Project type with optional user_count field
- Convert it.fails placeholder to passing overview test
- Fix modal test to use role-based selector (avoids duplicate text in KPI card + table)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Replace placeholder AppLayout with dark sidebar nav, semantic header/content zones
- Add CSS design tokens and shell utility classes to global.css
- Add shell-aware test expectation for 项目总览 (fails until Task 2 implements it)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Add user repository functions for project user CRUD
- Create platform-user-service for project user management
- Add GET /v1/platform/projects/:id/users endpoint
- Add POST /v1/platform/projects/:id/users endpoint
- Support project_admin and manager roles
- Validate username uniqueness and project existence
- Normalize real_name and phone inputs
- Add comprehensive test coverage (13 tests)
- Fix test isolation issue in platform-projects cleanup
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Add timing-attack mitigation by always verifying passwords against real or dummy hash
- Add comprehensive negative-path tests for platform login (wrong password, non-existent user, project user rejection, invalid body)
- Add focused middleware tests for requirePlatformAuth covering auth header validation and user type enforcement
- All 60 tests passing
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
After Task 1 changed AuthUser.project_id from number to number | null, getProjectId now explicitly checks for null values and throws an error for platform users attempting to access project resources.
This fix:
- Adds null check to reject platform users (project_id === null)
- Maintains type safety by ensuring return type is always number
- Includes comprehensive unit tests for all scenarios
- Preserves existing project-side behavior for valid project users
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The old static HTML/CSS/JS prototype in h5/ is superseded by the
React + Ant Design Mobile app in h5-app/. Removing to avoid confusion.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The feature/h5-design-polish branch brings in a complete React + Ant Design
Mobile rebuild of the H5 client (in h5-app/), replacing the old static
prototype in h5/.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Add MOCK_ACCOUNTS with admin/123456 and worker/123456 as fallback
when real backend is unavailable
- apiLogin tries real backend first; falls through to mock only on failure
- Supports real JWT token flow when backend (port 3201) is available
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- apiGetReports: use mock data instead of real API (no backend available)
- reports.html: add mock.js script include
- Fix date display: was concatenating dateStr+timeStr causing duplication
- Fix severity badge: map Chinese mock values to backend enum keys
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Add LogsPage.tsx re-export alias pointing to LogListPage
- Add src/tests/log-ui-model.test.ts with 26 targeted tests for log
UI-model and helper semantics (getLogStatusMeta, findTodayLog
integration, format helpers, equipment labels, truncate,
getTodayDateString, WEATHER_OPTIONS)
- Refactor LogFormPage to use ADM Form/Form.Item/Form.Header for
section layout, ADM Input for text fields, ADM Stepper for worker
count; remove hand-rolled FieldLabel and RequiredMark helpers
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Make date field editable (initialized to today)
- Rename remark → note to match legacy h5/log.html semantics
- Add photo upload field to LogFormPage
- Move weather to optional (was incorrectly required)
- LogDetailPage: render note, photo gallery, author+created_at footer
- Weather block is now conditional (not forced)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Fix upload-token API: backend returns { uploadUrl, objectKey } directly
(camelCase, no ApiResponse wrapper); update UploadTokenResult interface
and remove incorrect res.data access
- Fix confirm API: backend returns { fileId, objectKey } directly (no url,
no ApiResponse wrapper); update ConfirmResult interface accordingly
- uploadPhoto now returns { url: blobUrl, extra: { objectKey } } so the
ImageUploader can show a local preview while HazardReportPage submits
the confirmed objectKey (via extra) rather than the ephemeral blob URL
- Fix geolocation: getCurrentPosition returns void, not a watch ID;
remove the incorrect cast and clearWatch cleanup call; drop unused gpsWatchId ref
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>