# Agent Instructions for Trace Frontend ## Build & Development Commands ### Development ```bash pnpm dev # Start dev server at http://localhost:5173 ``` ### Build ```bash pnpm build # Build for production (outputs to dist/) pnpm preview # Preview production build ``` ### Testing & Linting No test or lint commands are currently configured. When adding tests, use Vitest or Jest. ## Project Overview This is a React 19 + TypeScript frontend for the Zhejiang Beifan Trace Coding Platform (溯源赋码平台). It provides: - Public query interface for employee permission-code verification - Admin dashboard for work-order statistics - Permission issuance with automatic employee serial generation - Product traceability management and public scan pages - Project work-order management for on-site implementation records - Aftersales work-order management for admins and technicians - User authentication and profile management **Tech Stack**: React 19, TypeScript, Vite 7, Ant Design 6, React Router v7, Axios ## Code Style Guidelines ### File Organization ``` src/ ├── components/ # Reusable UI components (AdminLayout, etc.) ├── pages/ # Page components (Login, Dashboard, etc.) ├── services/ # API service layer (api.ts with domain-specific APIs) ├── types/ # TypeScript type definitions (index.ts) ├── hooks/ # Custom React hooks ├── utils/ # Utility functions ├── styles/ # Global CSS files ├── assets/ # Static assets (images, etc.) ├── App.tsx # Main app with routes └── main.tsx # Application entry point ``` ### Imports - Use `@/` alias for src directory (configured in vite.config.ts and tsconfig.json) - Group imports: React/hooks first, then third-party libraries, then internal imports - Example: ```tsx import { useState } from 'react'; import { Form, Input, Button } from 'antd'; import { UserOutlined } from '@ant-design/icons'; import { useNavigate } from 'react-router-dom'; import { authApi } from '@/services/api'; import type { User } from '@/types'; ``` ### Naming Conventions - **Components**: PascalCase (e.g., `LoginPage`, `AdminLayout`) - **Functions/Methods**: camelCase (e.g., `handleLogin`, `loadStats`) - **Constants**: UPPER_SNAKE_CASE (e.g., `API_BASE_URL`) - **Types/Interfaces**: PascalCase (e.g., `User`, `ProductTrace`, `ApiResponse`) - **Files**: PascalCase for components/pages, lowercase for services/utils ### TypeScript - All new code must be TypeScript - Use `interface` for object shapes, `type` for unions/aliases - Explicit return types for API functions and handlers - Use `any` only as last resort - prefer `unknown` with type guards - Strict mode enabled: no unused locals, no unused parameters ### Component Patterns - Use functional components with hooks - For pages: use `function PageName()` (not arrow functions) - For layout/reusable components: use `function ComponentName()` - Export with `export default ComponentName;` - Use Ant Design components via destructuring: `const { Button, Form } = antd;` ### Error Handling - Use try-catch blocks for async operations - Display errors with Ant Design `message.error()` - API services throw errors with descriptive messages - Global axios interceptor handles 401 (auth) and 404 (not found) automatically ### API Services - API calls organized by domain in `src/services/api.ts`: - `authApi` - Authentication (login, logout, profile) - `dashboardApi` - Dashboard statistics - `employeeSerialApi` - Employee permission-code management - `productTracesApi` - Product traceability - `aftersalesApi` - Aftersales work orders (admin + public) - `projectOrdersApi` - Project work orders (admin + public) - `employeesApi` - Employee management (admin only): create/list/update/delete/reset password - `usersApi` - Assignable technician/admin picker via `assignable` - Auth token automatically added via axios interceptor - All API calls return typed responses based on `src/types/index.ts` ### Routing - Use React Router v7 with `` and `` components - Protected routes wrapped with `` component - Admin pages wrapped with `` layout component - Use `useNavigate()` for programmatic navigation - Use `useLocation()` to get current path - Public routes (no auth): `/login`, `/query`, `/aftersales/:serialNumber`, `/project-orders/:serialNumber`, `/product-traces/:serialNumber` - `PublicQuery` auto-redirects scanned `zjbf-sh-*` serials to `/aftersales/:serialNumber`. - `PublicQuery` auto-redirects scanned `zjbf-xm-*` serials to `/project-orders/:serialNumber`. - Product trace QR codes use `/product-traces/:serialNumber` directly. - Shared public-page chrome (logo + 备案 footer) lives in `components/PublicLayout.tsx` - `/admin/employee-serials` is the 权限管理 page despite the legacy route name. - Technicians should only see/use the aftersales and project work-order modules; admins see all admin menu items. ### Roles and Permission Issuance - `UserRole` is limited to `admin` / `technician` / `employee`. - `admin`: full backend access. - `technician`: work-order module access only. - `employee`: no backend login access. - Employee creation fields are name, phone, employee number, position, and role. - Password field is shown and required only for `admin` and `technician`. - Employee creation uses `employeesApi.create`, and the backend automatically creates the employee permission code; do not implement a separate "create then assign code" primary flow. - Employee rows should display generated `employeeSerials` from the employee list response. - Employee rows should provide a QR-code view for the active employee serial, using `/query?serial=...` as the scan target. - Public employee serial queries should show employee name, phone, employee number, and position. - Do not reintroduce enterprise/company-code management APIs or UI. The old `companyApi`, `serialApi`, `/admin/manage`, `/api/companies`, and `/api/serials` surfaces were removed. ### Aftersales Conventions - Aftersales serial format is `zjbf-sh-YYMMDDNN` (daily sequence), e.g. `zjbf-sh-26052801`. - Service type values must use `software` / `hardware` / `maintenance`: - `software`: 软件故障 - `hardware`: 硬件故障 - `maintenance`: 售后维保 - Aftersales `companyName` is a customer-company text field only. Do not call or recreate company-management APIs from aftersales create/update flows. - Use label text `现场情况说明` for `issueDescription` in create/detail/public-confirm views. - In admin detail page, use `工单分配` as the UI label for reassign action. - Signature display text should be `客户确认签名`. ### Product Traceability - Admin route: `/admin/product-traces`. - Public route: `/product-traces/:serialNumber`. - Manual product serial numbers are required. - Form field order must remain: 企业名称、地址、电话、设备信息、质保期、出厂日期、产品序列号、官网链接(可选)、公众号二维码(可选). - Official-account QR code images are uploaded to OSS and stored as backend-managed URLs/keys, not inline base64 in regular form payloads. ### Project Work Orders - Project order serial format is `zjbf-xm-YYMMDDNN`. - Project orders are for on-site investigation/implementation records. - Completion requires site images and engineer signature, without customer signature. - Site image limit is 18. - Completed project orders use status text `已完成`. ### State Management - Use React hooks (`useState`, `useEffect`) for local component state - Authentication state persisted in localStorage via authApi - No global state management library currently used ### Styling - Global styles in `src/styles/global.css` - Component-specific CSS in co-located styles directory (e.g., `pages/styles/Login.css`) - Import component styles with relative path: `import './styles/PageName.css';` - Use Ant Design components for primary UI, custom CSS for layout specifics ### Locale & Internationalization - Chinese (zh_CN) locale configured globally via `ConfigProvider` in main.tsx - All UI text should be in Chinese - Ant Design components automatically use Chinese locale ## Key Patterns & Conventions ### Page Component Structure ```tsx function PageName() { const [loading, setLoading] = useState(false); const [data, setData] = useState(null); useEffect(() => { loadData(); }, []); const loadData = async () => { setLoading(true); try { const result = await apiMethod(); setData(result); } catch (error: any) { message.error(error.message || '加载数据失败'); } finally { setLoading(false); } }; if (loading) { return ; } return
{/* JSX content */}
; } export default PageName; ``` ### Route Guards - `` - Redirects to /login if not authenticated - `` - Redirects to /admin/dashboard if authenticated - Use `` for nested routes ### Environment Variables - Use Vite's `import.meta.env.VITE_*` pattern - Example: `const API_BASE_URL = import.meta.env.VITE_API_BASE_URL || '/api';` - Define in `.env` file (not committed to git) ## Notes for Agents 1. **No tests configured**: When adding test frameworks, update AGENTS.md accordingly 2. **No linter configured**: Consider adding ESLint and Prettier 3. **Authentication flow**: Tokens stored in localStorage, added to requests via interceptor 4. **API proxy**: /api requests proxied to http://localhost:3000 during dev (see vite.config.ts) 5. **QR Code generation**: Uses `qrcode` library for generating QR codes for serial numbers 6. **Admin Layout**: Uses Ant Design Layout with Sider navigation and Header 7. **Type safety**: Always add types for new props, state, and API responses ## Common Tasks ### Add a new API endpoint 1. Add interface to `src/types/index.ts` 2. Add method to appropriate API object in `src/services/api.ts` 3. Handle errors appropriately with descriptive messages ### Add a new page 1. Create component in `src/pages/PageName.tsx` 2. Add CSS file in `src/pages/styles/PageName.css` 3. Add route in `src/App.tsx` 4. If admin page, wrap in `` and add menu item in `AdminLayout.tsx` ### Add a new component 1. Create in `src/components/ComponentName.tsx` 2. Add styles in `src/components/styles/ComponentName.css` if needed 3. Import using `@/components/ComponentName`