Files
zyt/REGION_API_PRODUCTION_FIX.md
2026-04-17 09:47:17 +08:00

244 lines
6.9 KiB
Markdown

# Region API Production URL Fix (省市区API生产环境URL修复)
## Issue
The region data API was using a proxy path (`/api-proxy/area/ChinaCitys.json`) which only works in development mode. After building for production, the proxy is not available, causing the region selector to fail.
## Root Cause
Vite's proxy configuration (`vite.config.ts`) only works during development (`npm run dev`). When the application is built for production (`npm run build`), the proxy is not included in the build output, and the relative path `/api-proxy/...` becomes invalid.
## Solution
Use environment detection to switch between proxy URL (development) and full URL (production).
## Changes Made
### 1. Updated prescription/index.vue
**File**: `admin/src/views/consumer/prescription/index.vue`
Changed from:
```typescript
const response = await fetch('/api-proxy/area/ChinaCitys.json')
```
To:
```typescript
// 开发环境使用代理,生产环境使用完整URL
const apiUrl = import.meta.env.DEV
? '/api-proxy/area/ChinaCitys.json'
: 'https://admin.zhenyangtang.com.cn/area/ChinaCitys.json'
const response = await fetch(apiUrl)
```
### 2. Updated prescription/order_list.vue
**File**: `admin/src/views/consumer/prescription/order_list.vue`
Applied the same change to the order list view.
## How It Works
### Environment Detection
Uses Vite's built-in environment variable `import.meta.env.DEV`:
- **Development** (`npm run dev`): `import.meta.env.DEV = true`
- **Production** (`npm run build`): `import.meta.env.DEV = false`
### URL Selection Logic
```typescript
const apiUrl = import.meta.env.DEV
? '/api-proxy/area/ChinaCitys.json' // Development: Use proxy
: 'https://admin.zhenyangtang.com.cn/area/ChinaCitys.json' // Production: Use full URL
```
### Development Mode
- Uses proxy path: `/api-proxy/area/ChinaCitys.json`
- Vite proxy rewrites to: `https://admin.zhenyangtang.com.cn/area/ChinaCitys.json`
- Avoids CORS issues during development
### Production Mode
- Uses full URL: `https://admin.zhenyangtang.com.cn/area/ChinaCitys.json`
- Direct fetch from the actual server
- No proxy needed
## Benefits
### 1. Works in Both Environments
- ✅ Development: Uses proxy for CORS-free development
- ✅ Production: Uses direct URL for deployed application
### 2. No Build Configuration Changes
- No need to modify build scripts
- No environment-specific builds
- Single codebase for all environments
### 3. Automatic Detection
- Automatically switches based on environment
- No manual configuration needed
- No risk of using wrong URL
### 4. Maintains CORS Handling
- Development: Proxy handles CORS
- Production: Server should have proper CORS headers
## Testing Steps
### 1. Test Development Mode
1. Run development server:
```bash
cd admin
npm run dev
```
2. Open browser console
3. Check for log: `开始加载省市区数据...`
4. Verify it uses proxy URL
5. Check region selector loads data
### 2. Test Production Build
1. Build for production:
```bash
cd admin
npm run build
```
2. Serve the built files:
```bash
npm run preview
# or deploy to production server
```
3. Open browser console
4. Check for log: `开始加载省市区数据...`
5. Verify it uses full URL
6. Check region selector loads data
### 3. Verify URL in Network Tab
**Development:**
- Request URL: `http://localhost:5173/api-proxy/area/ChinaCitys.json`
- Proxied to: `https://admin.zhenyangtang.com.cn/area/ChinaCitys.json`
**Production:**
- Request URL: `https://admin.zhenyangtang.com.cn/area/ChinaCitys.json`
- Direct request (no proxy)
### 4. Test Fallback Data
If API fails in either environment, verify fallback data is used:
```typescript
regionOptions.value = [
{
name: '四川省',
children: [...]
},
...
]
```
## Alternative Solutions Considered
### Option 1: Environment Variables (Not Chosen)
```typescript
const apiUrl = import.meta.env.VITE_REGION_API_URL || '/api-proxy/area/ChinaCitys.json'
```
**Pros**: More flexible for different environments
**Cons**: Requires environment-specific configuration files
### Option 2: Relative Path (Not Chosen)
```typescript
const apiUrl = '/area/ChinaCitys.json'
```
**Pros**: Simple
**Cons**: Requires copying file to public folder, increases bundle size
### Option 3: Backend API Endpoint (Not Chosen)
Create a backend endpoint to serve region data
**Pros**: More control, can cache, can update without frontend deploy
**Cons**: Requires backend changes, adds server load
### Option 4: Current Solution (Chosen) ✅
Use environment detection with conditional URL
**Pros**:
- Simple implementation
- No additional configuration
- Works in both environments
- No backend changes needed
**Cons**:
- Hardcoded production URL (acceptable for this use case)
## Production Server Requirements
### CORS Headers
The production server hosting `ChinaCitys.json` should have proper CORS headers:
```
Access-Control-Allow-Origin: *
# or specific domain:
Access-Control-Allow-Origin: https://your-admin-domain.com
```
### File Availability
Ensure the file is accessible at:
```
https://admin.zhenyangtang.com.cn/area/ChinaCitys.json
```
### Alternative: Use Backend Proxy
If CORS is an issue in production, consider creating a backend endpoint:
```php
// server/app/adminapi/controller/RegionController.php
public function getChinaCitys()
{
$url = 'https://admin.zhenyangtang.com.cn/area/ChinaCitys.json';
$data = file_get_contents($url);
return json(['data' => json_decode($data, true)]);
}
```
Then update frontend to use:
```typescript
const apiUrl = import.meta.env.DEV
? '/api-proxy/area/ChinaCitys.json'
: '/adminapi/region/getChinaCitys' // Backend endpoint
```
## Related Files
### Frontend:
- `admin/src/views/consumer/prescription/index.vue`
- Updated `loadRegionData()` function
- `admin/src/views/consumer/prescription/order_list.vue`
- Updated `loadRegionData()` function
### Configuration:
- `admin/vite.config.ts`
- Proxy configuration (development only)
### Documentation:
- `REGION_DATA_SETUP.md` (should be updated to mention production URL)
## Environment Variables Reference
### Vite Built-in Variables:
- `import.meta.env.DEV` - Boolean, true in development
- `import.meta.env.PROD` - Boolean, true in production
- `import.meta.env.MODE` - String, 'development' or 'production'
### Usage Example:
```typescript
if (import.meta.env.DEV) {
console.log('Running in development mode')
}
if (import.meta.env.PROD) {
console.log('Running in production mode')
}
console.log('Current mode:', import.meta.env.MODE)
```
## Summary
✅ Fixed production build issue with region API
✅ Uses proxy in development for CORS-free development
✅ Uses direct URL in production for deployed application
✅ Automatic environment detection
✅ No build configuration changes needed
✅ Maintains fallback data for both environments
✅ Applied to both prescription index and order list views
The region selector now works correctly in both development and production environments!