21 KiB
21 KiB
医生资质图片数据流转说明
完整数据流转过程
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 组件需要数组格式的数据:
<material-picker v-model="formData.qualification_images" :limit="9" />
如果传入JSON字符串,组件无法正确显示已上传的图片。
3. 为什么小程序端不转换?
- 保持API返回数据的一致性
- 减少后端处理逻辑
- 前端有完善的解析和容错机制
- 便于缓存和传输
4. JSON编码参数说明
json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES)
JSON_UNESCAPED_UNICODE: 不转义中文字符JSON_UNESCAPED_SLASHES: 不转义URL中的斜杠/
这样可以保证:
- URL正确性:
https://不会变成https:\/\/ - 中文文件名正确显示
- 减少字符串长度
测试验证
验证数据转换是否正确
// 测试代码
$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(...) }