260 lines
7.5 KiB
Markdown
260 lines
7.5 KiB
Markdown
# Diagnosis Image URL Prefix Fix (诊断图片URL前缀修复)
|
|
|
|
## Issue
|
|
Image URLs in the diagnosis detail (tongue_images and report_files) were stored as relative paths without the domain prefix, causing issues when accessing them from external sources or different domains.
|
|
|
|
## Solution
|
|
Added logic to automatically prepend the current domain to image URLs that don't already have an `http://` or `https://` prefix.
|
|
|
|
## Changes Made
|
|
|
|
### File: `server/app/adminapi/logic/tcm/DiagnosisLogic.php`
|
|
|
|
#### 1. Updated tongue_images Processing
|
|
Added domain prefix logic after parsing the images array:
|
|
|
|
```php
|
|
if (!empty($diagnosis['tongue_images'])) {
|
|
// 先尝试 JSON 解析(兼容旧数据)
|
|
$files = json_decode($diagnosis['tongue_images'], true);
|
|
if (is_array($files)) {
|
|
$diagnosis['tongue_images'] = $files;
|
|
} else {
|
|
// JSON 解析失败则按逗号分割
|
|
$diagnosis['tongue_images'] = array_filter(explode(',', $diagnosis['tongue_images'])) ?: [];
|
|
}
|
|
|
|
// 为没有 http 前缀的图片添加域名
|
|
$domain = request()->domain();
|
|
$diagnosis['tongue_images'] = array_map(function($url) use ($domain) {
|
|
if (empty($url)) {
|
|
return $url;
|
|
}
|
|
// 如果已经包含 http:// 或 https://,则跳过
|
|
if (stripos($url, 'http://') === 0 || stripos($url, 'https://') === 0) {
|
|
return $url;
|
|
}
|
|
// 添加域名前缀
|
|
return $domain . $url;
|
|
}, $diagnosis['tongue_images']);
|
|
} else {
|
|
$diagnosis['tongue_images'] = [];
|
|
}
|
|
```
|
|
|
|
#### 2. Updated report_files Processing
|
|
Applied the same logic to report files:
|
|
|
|
```php
|
|
if (!empty($diagnosis['report_files'])) {
|
|
// 先尝试 JSON 解析(兼容旧数据)
|
|
$files = json_decode($diagnosis['report_files'], true);
|
|
if (is_array($files)) {
|
|
$diagnosis['report_files'] = $files;
|
|
} else {
|
|
// JSON 解析失败则按逗号分割
|
|
$diagnosis['report_files'] = array_filter(explode(',', $diagnosis['report_files'])) ?: [];
|
|
}
|
|
|
|
// 为没有 http 前缀的文件添加域名
|
|
$domain = request()->domain();
|
|
$diagnosis['report_files'] = array_map(function($url) use ($domain) {
|
|
if (empty($url)) {
|
|
return $url;
|
|
}
|
|
// 如果已经包含 http:// 或 https://,则跳过
|
|
if (stripos($url, 'http://') === 0 || stripos($url, 'https://') === 0) {
|
|
return $url;
|
|
}
|
|
// 添加域名前缀
|
|
return $domain . $url;
|
|
}, $diagnosis['report_files']);
|
|
} else {
|
|
$diagnosis['report_files'] = [];
|
|
}
|
|
```
|
|
|
|
## Logic Flow
|
|
|
|
### URL Processing Logic:
|
|
1. Parse the images/files array (JSON or comma-separated)
|
|
2. Get current domain using `request()->domain()`
|
|
3. For each URL in the array:
|
|
- Check if URL is empty → skip
|
|
- Check if URL starts with `http://` or `https://` → skip (already has protocol)
|
|
- Otherwise → prepend domain to the URL
|
|
|
|
### Examples:
|
|
|
|
#### Relative Path (Needs Domain):
|
|
```php
|
|
Input: "/uploads/images/tongue/2024/01/image.jpg"
|
|
Domain: "https://admin.zhenyangtang.com.cn"
|
|
Output: "https://admin.zhenyangtang.com.cn/uploads/images/tongue/2024/01/image.jpg"
|
|
```
|
|
|
|
#### Absolute URL (Skip):
|
|
```php
|
|
Input: "https://cdn.example.com/images/tongue.jpg"
|
|
Output: "https://cdn.example.com/images/tongue.jpg"
|
|
```
|
|
|
|
#### HTTP URL (Skip):
|
|
```php
|
|
Input: "http://example.com/image.jpg"
|
|
Output: "http://example.com/image.jpg"
|
|
```
|
|
|
|
#### Empty URL (Skip):
|
|
```php
|
|
Input: ""
|
|
Output: ""
|
|
```
|
|
|
|
## Benefits
|
|
|
|
### 1. Cross-Domain Compatibility
|
|
Images can now be accessed from different domains or external applications without path issues.
|
|
|
|
### 2. API Response Consistency
|
|
API responses always return complete, accessible URLs regardless of how they were stored.
|
|
|
|
### 3. Backward Compatibility
|
|
- Existing relative paths are automatically converted
|
|
- Existing absolute URLs are preserved
|
|
- No database migration required
|
|
|
|
### 4. Flexible Storage
|
|
- Database can store either relative or absolute paths
|
|
- System handles both formats transparently
|
|
- Future-proof for CDN integration
|
|
|
|
## Use Cases
|
|
|
|
### 1. Mobile App Access
|
|
Mobile apps can directly use the returned URLs without needing to construct them.
|
|
|
|
### 2. Third-Party Integration
|
|
External systems can access images using the complete URLs from API responses.
|
|
|
|
### 3. CDN Migration
|
|
When migrating to CDN, images with absolute CDN URLs will work alongside local relative paths.
|
|
|
|
### 4. Multi-Domain Setup
|
|
System works correctly across different domains (dev, staging, production).
|
|
|
|
## Testing Steps
|
|
|
|
### 1. Test Relative Path URLs
|
|
1. Create a diagnosis with tongue images stored as relative paths:
|
|
```
|
|
/uploads/images/tongue/2024/01/image.jpg
|
|
```
|
|
2. Fetch diagnosis detail via API
|
|
3. Verify response contains:
|
|
```json
|
|
{
|
|
"tongue_images": [
|
|
"https://admin.zhenyangtang.com.cn/uploads/images/tongue/2024/01/image.jpg"
|
|
]
|
|
}
|
|
```
|
|
|
|
### 2. Test Absolute URLs
|
|
1. Create a diagnosis with absolute URL:
|
|
```
|
|
https://cdn.example.com/images/tongue.jpg
|
|
```
|
|
2. Fetch diagnosis detail
|
|
3. Verify URL is unchanged:
|
|
```json
|
|
{
|
|
"tongue_images": [
|
|
"https://cdn.example.com/images/tongue.jpg"
|
|
]
|
|
}
|
|
```
|
|
|
|
### 3. Test Mixed URLs
|
|
1. Create a diagnosis with both relative and absolute URLs:
|
|
```
|
|
[
|
|
"/uploads/local.jpg",
|
|
"https://cdn.example.com/remote.jpg"
|
|
]
|
|
```
|
|
2. Fetch diagnosis detail
|
|
3. Verify correct processing:
|
|
```json
|
|
{
|
|
"tongue_images": [
|
|
"https://admin.zhenyangtang.com.cn/uploads/local.jpg",
|
|
"https://cdn.example.com/remote.jpg"
|
|
]
|
|
}
|
|
```
|
|
|
|
### 4. Test Empty/Null Values
|
|
1. Create a diagnosis with empty images
|
|
2. Fetch diagnosis detail
|
|
3. Verify empty array is returned:
|
|
```json
|
|
{
|
|
"tongue_images": []
|
|
}
|
|
```
|
|
|
|
### 5. Test Report Files
|
|
Repeat all tests above for `report_files` field.
|
|
|
|
## Technical Details
|
|
|
|
### Domain Detection
|
|
Uses `request()->domain()` which returns the current request domain including protocol:
|
|
- Development: `http://localhost:8000`
|
|
- Production: `https://admin.zhenyangtang.com.cn`
|
|
|
|
### Case-Insensitive Protocol Check
|
|
Uses `stripos()` for case-insensitive checking:
|
|
- Matches: `http://`, `HTTP://`, `Http://`
|
|
- Matches: `https://`, `HTTPS://`, `Https://`
|
|
|
|
### Array Processing
|
|
Uses `array_map()` for efficient processing of all URLs in the array.
|
|
|
|
## Related Files
|
|
|
|
### Backend:
|
|
- `server/app/adminapi/logic/tcm/DiagnosisLogic.php`
|
|
- Updated `tongue_images` processing
|
|
- Updated `report_files` processing
|
|
|
|
### Database:
|
|
- `tcm_diagnosis` table
|
|
- `tongue_images` column (stores JSON or comma-separated paths)
|
|
- `report_files` column (stores JSON or comma-separated paths)
|
|
|
|
## Notes
|
|
|
|
### Storage Format
|
|
The database continues to store paths as-is (relative or absolute). The conversion happens only when reading data for API responses.
|
|
|
|
### Performance
|
|
The `array_map()` operation is efficient and adds minimal overhead. For typical diagnosis records with 1-5 images, the performance impact is negligible.
|
|
|
|
### Future Enhancements
|
|
If needed, this logic could be extracted into a helper function for reuse across other file/image fields in the system.
|
|
|
|
## Summary
|
|
|
|
✅ Automatically adds domain prefix to relative image URLs
|
|
✅ Preserves absolute URLs (http/https)
|
|
✅ Handles both tongue_images and report_files
|
|
✅ Backward compatible with existing data
|
|
✅ Case-insensitive protocol detection
|
|
✅ Handles empty/null values gracefully
|
|
✅ No database migration required
|
|
✅ Works across different domains
|
|
|
|
Image URLs in diagnosis details are now always complete and accessible, improving API usability and cross-domain compatibility!
|