Files
zyt/医生资质图片数据流转说明.md
T
2026-03-20 13:56:40 +08:00

278 lines
21 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 医生资质图片数据流转说明
## 完整数据流转过程
### 1. 添加/编辑医生(管理后台)
```
┌─────────────────────────────────────────────────────────────────┐
│ 前端(Vue3) │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 用户上传图片 │
│ ↓ │
│ material-picker 组件 │
│ ↓ │
│ formData.qualification_images = [ │
│ "https://www.d.com/uploads/images/20260317/image1.png", │
│ "https://www.d.com/uploads/images/20260317/image2.png" │
│ ] │
│ ↓ │
│ 提交表单(POST请求) │
│ │
└─────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────┐
│ 后端接口(AdminController
├─────────────────────────────────────────────────────────────────┤
│ │
│ 接收参数: │
│ $params['qualification_images'] = [ │
│ "https://www.d.com/uploads/images/20260317/image1.png", │
│ "https://www.d.com/uploads/images/20260317/image2.png" │
│ ] │
│ ↓ │
│ 调用 AdminLogic::add() 或 AdminLogic::edit() │
│ │
└─────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────┐
│ 业务逻辑层(AdminLogic
├─────────────────────────────────────────────────────────────────┤
│ │
│ // 数据转换处理 │
│ if (is_array($params['qualification_images'])) { │
│ $qualificationImages = json_encode( │
│ $params['qualification_images'], │
│ JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES │
│ ); │
│ } │
│ ↓ │
│ 转换后的数据: │
│ $qualificationImages = '["https://www.d.com/uploads/images/ │
│ 20260317/image1.png","https://www.d.com/uploads/images/ │
│ 20260317/image2.png"]' │
│ ↓ │
│ 保存到数据库 │
│ │
└─────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────┐
│ 数据库(MySQL) │
├─────────────────────────────────────────────────────────────────┤
│ │
│ la_admin 表 │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ qualification_images (text) │ │
│ ├──────────────────────────────────────────────────────────┤ │
│ │ ["https://www.d.com/uploads/images/20260317/image1.png",│ │
│ │ "https://www.d.com/uploads/images/20260317/image2.png"] │ │
│ └──────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
```
### 2. 查看医生详情(管理后台)
```
┌─────────────────────────────────────────────────────────────────┐
│ 前端(Vue3) │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 点击编辑按钮 │
│ ↓ │
│ 调用 adminDetail({ id: 1 }) │
│ ↓ │
│ GET /adminapi/auth.admin/detail?id=1 │
│ │
└─────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────┐
│ 后端接口(AdminController
├─────────────────────────────────────────────────────────────────┤
│ │
│ 调用 AdminLogic::detail(['id' => 1]) │
│ │
└─────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────┐
│ 业务逻辑层(AdminLogic
├─────────────────────────────────────────────────────────────────┤
│ │
│ // 从数据库查询 │
│ $admin = Admin::field([...])->find()->toArray(); │
│ ↓ │
│ 查询结果: │
│ $admin['qualification_images'] = '["https://www.d.com/uploads/ │
│ images/20260317/image1.png","https://www.d.com/uploads/images/ │
│ 20260317/image2.png"]' │
│ ↓ │
│ // 转换为数组格式 │
│ if (!empty($admin['qualification_images'])) { │
│ $images = json_decode($admin['qualification_images'], true);│
│ if (is_array($images)) { │
│ $admin['qualification_images'] = $images; │
│ } │
│ } │
│ ↓ │
│ 转换后的数据: │
│ $admin['qualification_images'] = [ │
│ "https://www.d.com/uploads/images/20260317/image1.png", │
│ "https://www.d.com/uploads/images/20260317/image2.png" │
│ ] │
│ ↓ │
│ 返回给前端 │
│ │
└─────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────┐
│ 前端(Vue3) │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 接收响应数据: │
│ formData.qualification_images = [ │
│ "https://www.d.com/uploads/images/20260317/image1.png", │
│ "https://www.d.com/uploads/images/20260317/image2.png" │
│ ] │
│ ↓ │
│ material-picker 组件直接使用数组数据 │
│ ↓ │
│ 显示图片列表 │
│ │
└─────────────────────────────────────────────────────────────────┘
```
### 3. 小程序端查看医生详情
```
┌─────────────────────────────────────────────────────────────────┐
│ 小程序前端(uni-app) │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 进入医生详情页 │
│ ↓ │
│ GET /api/doctor/detail?id=1 │
│ │
└─────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────┐
│ 后端接口(DoctorController
├─────────────────────────────────────────────────────────────────┤
│ │
│ 调用 DoctorLogic::getDoctorDetail($doctorId) │
│ │
└─────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────┐
│ 业务逻辑层(DoctorLogic
├─────────────────────────────────────────────────────────────────┤
│ │
│ // 从数据库查询 │
│ $doctor = Admin::field([...])->find()->toArray(); │
│ ↓ │
│ 查询结果(保持JSON字符串格式): │
│ $doctorData['qualification_images'] = '["https://www.d.com/ │
│ uploads/images/20260317/image1.png","https://www.d.com/uploads/ │
│ images/20260317/image2.png"]' │
│ ↓ │
│ 直接返回(不转换) │
│ │
└─────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────┐
│ 小程序前端(uni-app) │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 接收响应数据: │
│ doctor.value.qualification_images = '["https://www.d.com/ │
│ uploads/images/20260317/image1.png","https://www.d.com/uploads/ │
│ images/20260317/image2.png"]' │
│ ↓ │
│ // 使用 computed 解析 │
│ const qualificationImages = computed(() => { │
│ if (!doctor.value?.qualification_images) return [] │
│ try { │
│ const images = typeof doctor.value.qualification_images │
│ === 'string' │
│ ? JSON.parse(doctor.value.qualification_images) │
│ : doctor.value.qualification_images │
│ return Array.isArray(images) ? images : [] │
│ } catch (e) { │
│ return [] │
│ } │
│ }) │
│ ↓ │
│ 解析后的数据: │
│ qualificationImages.value = [ │
│ "https://www.d.com/uploads/images/20260317/image1.png", │
│ "https://www.d.com/uploads/images/20260317/image2.png" │
│ ] │
│ ↓ │
│ 渲染图片网格 │
│ │
└─────────────────────────────────────────────────────────────────┘
```
## 关键点总结
### 1. 数据格式转换时机
| 场景 | 输入格式 | 输出格式 | 转换位置 |
|------|---------|---------|---------|
| 添加医生 | 数组 | JSON字符串 | AdminLogic::add() |
| 编辑医生 | 数组 | JSON字符串 | AdminLogic::edit() |
| 管理后台查看 | JSON字符串 | 数组 | AdminLogic::detail() |
| 小程序端查看 | JSON字符串 | JSON字符串 | 不转换,前端解析 |
### 2. 为什么管理后台要转换回数组?
因为 `material-picker` 组件需要数组格式的数据:
```vue
<material-picker v-model="formData.qualification_images" :limit="9" />
```
如果传入JSON字符串,组件无法正确显示已上传的图片。
### 3. 为什么小程序端不转换?
1. 保持API返回数据的一致性
2. 减少后端处理逻辑
3. 前端有完善的解析和容错机制
4. 便于缓存和传输
### 4. JSON编码参数说明
```php
json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES)
```
- `JSON_UNESCAPED_UNICODE`: 不转义中文字符
- `JSON_UNESCAPED_SLASHES`: 不转义URL中的斜杠 `/`
这样可以保证:
- URL正确性:`https://` 不会变成 `https:\/\/`
- 中文文件名正确显示
- 减少字符串长度
## 测试验证
### 验证数据转换是否正确
```php
// 测试代码
$testData = [
"https://www.d.com/uploads/images/20260317/测试图片1.png",
"https://www.d.com/uploads/images/20260317/测试图片2.png"
];
// 编码
$encoded = json_encode($testData, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
echo "编码后: " . $encoded . "\n";
// 输出: ["https://www.d.com/uploads/images/20260317/测试图片1.png","https://www.d.com/uploads/images/20260317/测试图片2.png"]
// 解码
$decoded = json_decode($encoded, true);
var_dump($decoded);
// 输出: array(2) { [0]=> string(...) [1]=> string(...) }
```