diff --git a/CLAUDE.md b/CLAUDE.md deleted file mode 100644 index 514f5a6..0000000 --- a/CLAUDE.md +++ /dev/null @@ -1,201 +0,0 @@ -# CLAUDE.md - -This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. - -## Project Overview - -This is a multi-tenant service management platform ("百业到家") built with Ant Design Pro, React 19, TypeScript, and UmiJS Max framework. The application uses dynamic routing loaded from a backend API and implements a comprehensive permission system. - -## Development Commands - -```bash -# Start development server (with mocks) -pnpm dev -# or -pnpm start - -# Start development server (without mocks, connects to backend) -pnpm start:dev - -# Build for production -pnpm build - -# Lint (Biome + TypeScript check) -pnpm lint - -# Run tests -pnpm test - -# Run tests with coverage -pnpm test:coverage - -# Type check only -pnpm tsc -``` - -**Important**: This project uses **pnpm** as the package manager, not npm or yarn. - -## Architecture - -### Dynamic Routing System - -Routes are **not** statically defined in `config/routes.ts` (most routes are commented out). Instead, routes are dynamically loaded from the backend API: - -1. On app initialization, `getInfo()` fetches user permissions and menu structure -2. `patchClientRoutes()` in `src/app.tsx` transforms backend menu data into UmiJS routes -3. `loopMenuItem()` in `src/utils/menuUtils.tsx` recursively converts menu items to route objects -4. Routes are lazy-loaded using `React.lazy(() => import('@/pages/${component}'))` - -**When adding new pages**: Create the page component in `src/pages/`, then configure the route in the backend system (not in code). - -### Multi-Tenant Architecture - -Every API request includes a `tenant-id` header. Tenant information is: -- Stored in web-storage-cache with key `CACHE_KEY.TenantId` -- Set during login via `setTenantId()` -- Automatically added to all requests by the request interceptor in `src/app.tsx` - -### Authentication Flow - -1. User logs in with tenant name, username, and password (password is RSA encrypted via JSEncrypt) -2. Backend returns `accessToken` and `refreshToken` -3. Tokens stored in web-storage-cache (see `src/utils/auth.ts`) -4. All requests include `Authorization: Bearer ${accessToken}` header -5. On 401 response, automatically attempts token refresh using `refreshToken` -6. If refresh fails, redirects to login page - -**Token refresh logic** is in `src/requestErrorConfig.ts` with request queuing to prevent duplicate refresh attempts. - -### Request Interceptors - -All API requests are automatically modified (see `src/app.tsx`): -- **API prefix**: `/admin-api` is prepended to all URLs (unless already present) -- **Headers**: `Authorization`, `tenant-id`, and `Accept` headers are added -- **Parameter serialization**: Arrays are serialized specially: - - `createTime` arrays become `createTime[0]` and `createTime[1]` - - Other arrays become `key[]` format - -### Caching Strategy - -Uses `web-storage-cache` library (see `src/hooks/web/useCache.ts`): -- `CACHE_KEY.USER`: Current user info -- `CACHE_KEY.ROLE_ROUTERS`: Dynamic menu/route data -- `CACHE_KEY.ACCESS_TOKEN` / `CACHE_KEY.REFRESH_TOKEN`: Auth tokens -- `CACHE_KEY.DICT_CACHE`: Dictionary/enum data loaded on app init -- `CACHE_KEY.LoginForm`: Remember me functionality (password encrypted) - -### State Management - -- **UmiJS Model Plugin**: For global state (see `src/app.tsx` - `initialState`) -- **Custom Hooks**: In `src/hooks/stores/` (e.g., `useDictStore` for dictionary management) -- **Web Storage Cache**: For persistent data across sessions - -## Project Structure - -``` -src/ -├── pages/ # Feature pages organized by domain -│ ├── ai/ # AI model and sample management -│ ├── prod/ # Product and category management -│ ├── system/ # System admin (users, roles, menus, tenants, logs, messages) -│ ├── trade/ # Order and sales management -│ └── user/ # Login page -├── services/ # API service layer (mirrors page structure) -├── components/ # Reusable components -│ ├── Draggable/ # Drag-and-drop components using @dnd-kit -│ ├── Upload/ # File/image/video upload components -│ ├── GroupTag/ # Tag management components -│ └── Tinymce/ # Rich text editor wrapper -├── hooks/ # Custom React hooks -│ ├── antd/ # Ant Design related hooks -│ ├── stores/ # State management hooks -│ └── web/ # Web utilities (cache, etc.) -├── utils/ # Utility functions -│ ├── auth.ts # Token and tenant management -│ ├── menuUtils.tsx # Dynamic route conversion -│ ├── dict.ts # Dictionary/enum utilities -│ └── tree.ts # Tree data structure helpers -├── constants/ # Shared constants and enums -├── locales/ # i18n translations (zh-CN default) -└── app.tsx # App initialization and runtime config -``` - -## Environment Configuration - -Multiple environment files: -- `.env.local` - Local overrides (gitignored) -- `.env.dev` - Development environment -- `.env.prod` - Production environment - -**Proxy configuration** in `config/proxy.ts`: -- `dev`: Points to local backend (currently `http://192.168.1.89:48080`) -- `test`: Points to test environment -- `pre`: Points to pre-production environment - -Switch environments using `UMI_ENV`: -```bash -cross-env UMI_ENV=dev pnpm start # Development -cross-env UMI_ENV=test pnpm start # Test -cross-env UMI_ENV=pre pnpm start # Pre-production -``` - -## Code Conventions - -### Linting -- Uses **Biome** (not ESLint) for linting and formatting -- Configured in `biome.json` -- Pre-commit hook runs Biome via lint-staged - -### Commit Messages -- Uses commitlint with conventional commits -- Enforced via Husky pre-commit hook -- Format: `type(scope): subject` (e.g., `feat: add user management`) - -### Component Patterns -- **ProTable**: Use `EnhancedProTable` wrapper for common table functionality -- **Forms**: Use `DrawerForm` or `ModalForm` from `@ant-design/pro-components` -- **File Uploads**: Use custom `UploadImages` or `UploadVideo` components in `src/components/Upload/` -- **Rich Text**: Use `Tinymce` component wrapper (TinyMCE is in `public/tinymce/`) - -### Service Layer -- All API calls go through `src/services/` -- Use UmiJS `request` from `@umijs/max` (configured in `src/app.tsx`) -- Response format: `{ code: number, data: any, msg: string }` -- Success when `code === 0` - -## Common Patterns - -### Adding a New Page - -1. Create page component in `src/pages/{domain}/{feature}/index.tsx` -2. Create corresponding service in `src/services/{domain}/{feature}/index.ts` -3. Configure the menu/route in the backend system (not in code) -4. The route will automatically appear after backend configuration - -### Working with Dictionaries/Enums - -Dictionaries are loaded on app init and cached: -```typescript -import { useDictStore } from '@/hooks/stores/dict'; - -const dictStore = useDictStore(); -const dictData = dictStore.getDictByType('dict_type_key'); -``` - -### File Uploads - -Media files are uploaded via `src/services/infra/file/index.ts` or `src/services/infra/media/index.ts`. Use the Upload components which handle the API integration. - -## Testing - -- Jest configured with `jest.config.ts` -- Test files should be colocated with components or in `__tests__` directories -- Run single test: `pnpm test -- path/to/test.spec.ts` - -## Important Notes - -- **Node version**: Requires Node.js >= 20.0.0 (see `package.json` engines) -- **React 19**: Uses React 19 with `@ant-design/v5-patch-for-react-19` compatibility patch -- **Mako bundler**: Uses UmiJS Mako for faster builds (configured in `config/config.ts`) -- **Mock data**: Located in `mock/` directory, enabled by default in dev mode -- **TinyMCE**: Static files in `public/tinymce/`, Chinese language pack included diff --git a/auto-deploy.ps1 b/auto-deploy.ps1 deleted file mode 100644 index f0879d1..0000000 --- a/auto-deploy.ps1 +++ /dev/null @@ -1,30 +0,0 @@ -# Auto Deploy Script for PowerShell -$SERVER = "43.139.42.137" -$USER = "root" -$REMOTE_PATH = "/home/1panel/www/sites/admin.petshy.tashowz.com/index" - -Write-Host "=== Auto Deploy ===" -ForegroundColor Cyan -Write-Host "" - -# 1. Build project -Write-Host "Building project..." -ForegroundColor Yellow -pnpm build -if ($LASTEXITCODE -ne 0) { - Write-Host "Build failed" -ForegroundColor Red - exit 1 -} -Write-Host "Build complete" -ForegroundColor Green -Write-Host "" - -# 2. Upload files -Write-Host "Uploading files to server..." -ForegroundColor Yellow -scp -r dist/* ${USER}@${SERVER}:${REMOTE_PATH}/ - -if ($LASTEXITCODE -eq 0) { - Write-Host "" - Write-Host "Deploy complete!" -ForegroundColor Green - Write-Host "Visit: http://admin.petshy.tashowz.com" -ForegroundColor Cyan -} else { - Write-Host "Upload failed" -ForegroundColor Red - exit 1 -} diff --git a/src/pages/user/login/index.tsx b/src/pages/user/login/index.tsx index 837fd53..ae2927e 100644 --- a/src/pages/user/login/index.tsx +++ b/src/pages/user/login/index.tsx @@ -143,7 +143,7 @@ const Page = () => { fontSize: 14, }} > - 其他登录方式111 + 其他登录方式