# 省市区选择器功能说明
## 功能描述
在创建处方业务订单时,添加省市区级联选择器,方便用户选择收货地址的省市区信息。
## 修改内容
### 1. 表单界面(admin/src/views/consumer/prescription/index.vue)
#### 添加省市区选择器(第 792-810 行)
```vue
```
**组件配置说明:**
- `v-model="createOrderForm.region"`:绑定选中的省市区数组
- `:options="regionOptions"`:省市区数据源
- `value: 'name'`:使用 name 字段作为值
- `label: 'name'`:使用 name 字段作为显示文本
- `emitPath: false`:只返回最后一级的值(区/县)
- `checkStrictly: false`:必须选择到最后一级
- `clearable`:可清空
- `filterable`:可搜索
### 2. 数据模型更新(第 1175-1195 行)
```typescript
const createOrderForm = reactive({
patient_id: '' as number | string,
recipient_name: '',
recipient_phone: '',
region: [] as string[], // 新增:省市区数组
shipping_address: '', // 改为详细地址
// ... 其他字段
})
```
### 3. 省市区数据(第 1195-1340 行)
添加了常用省市区数据:
- 四川省(成都市、绵阳市)
- 北京市
- 上海市
- 广东省(广州市、深圳市)
```typescript
const regionOptions = ref([
{
name: '四川省',
children: [
{
name: '成都市',
children: [
{ name: '锦江区' },
{ name: '青羊区' },
// ... 更多区县
]
}
]
},
// ... 更多省份
])
```
### 4. 事件处理方法
```typescript
const handleRegionChange = (value: string[]) => {
console.log('选择的省市区:', value)
}
```
## 使用说明
### 用户操作流程
1. 点击"创建业务订单"按钮
2. 选择诊单患者
3. 填写收货人和收货手机
4. **点击"省市区"选择器**
5. 依次选择:省 → 市 → 区/县
6. 在"详细地址"中填写街道、门牌号等信息
7. 填写其他订单信息
8. 提交订单
### 界面效果
**编辑时:**
```
┌─────────────────────────────────────────────────┐
│ 收货人: [张三] 收货手机: [138****0000] │
├─────────────────────────────────────────────────┤
│ 省市区: [四川省 / 成都市 / 双流区 ▼] │
├─────────────────────────────────────────────────┤
│ 详细地址: │
│ ┌─────────────────────────────────────────────┐ │
│ │ 黄甲街道黄龙大道二段280号 │ │
│ └─────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────┘
```
**完整地址组合:**
```
四川省成都市双流区黄甲街道黄龙大道二段280号
```
## 后端支持
### 数据库字段建议
如果需要单独存储省市区信息,可以添加以下字段:
```sql
-- 在 prescription_order 表中添加省市区字段
ALTER TABLE `zyt_prescription_order`
ADD COLUMN `province` VARCHAR(50) DEFAULT '' COMMENT '省份' AFTER `recipient_phone`,
ADD COLUMN `city` VARCHAR(50) DEFAULT '' COMMENT '城市' AFTER `province`,
ADD COLUMN `district` VARCHAR(50) DEFAULT '' COMMENT '区/县' AFTER `city`;
-- 或者保持现有的 shipping_address 字段,前端组合完整地址
```
### 后端 API 修改
#### 方案 A:前端组合完整地址(推荐)
前端在提交时将省市区和详细地址组合:
```typescript
const submitOrder = async () => {
const fullAddress = createOrderForm.region.join('') + createOrderForm.shipping_address
await createPrescriptionOrder({
...createOrderForm,
shipping_address: fullAddress // 四川省成都市双流区黄甲街道...
})
}
```
#### 方案 B:分别存储省市区
后端接收独立的省市区字段:
```php
// 创建订单时
$order->province = $params['province'] ?? '';
$order->city = $params['city'] ?? '';
$order->district = $params['district'] ?? '';
$order->shipping_address = $params['shipping_address'] ?? '';
// 查询时返回
return [
'province' => $order->province,
'city' => $order->city,
'district' => $order->district,
'shipping_address' => $order->shipping_address,
'full_address' => $order->province . $order->city . $order->district . $order->shipping_address
];
```
## 扩展功能
### 1. 使用完整的省市区数据
当前只包含了部分常用省市区,实际项目中应该使用完整的数据。
**方案 A:使用 npm 包**
```bash
npm install element-china-area-data
```
```typescript
import { regionData } from 'element-china-area-data'
const regionOptions = ref(regionData)
```
**方案 B:从后端 API 获取**
```typescript
import { getRegionTree } from '@/api/common'
const regionOptions = ref([])
onMounted(async () => {
const res = await getRegionTree()
regionOptions.value = res.data
})
```
### 2. 自动填充历史地址
根据患者历史订单自动填充地址:
```typescript
const loadPatientLastAddress = async (patientId: number) => {
const res = await getPatientLastOrder(patientId)
if (res.data) {
createOrderForm.region = [res.data.province, res.data.city, res.data.district]
createOrderForm.shipping_address = res.data.detail_address
createOrderForm.recipient_name = res.data.recipient_name
createOrderForm.recipient_phone = res.data.recipient_phone
}
}
```
### 3. 地址簿功能
保存常用地址,快速选择:
```vue
```
### 4. 地址验证
验证地址的完整性和合法性:
```typescript
const validateAddress = () => {
if (createOrderForm.region.length !== 3) {
feedback.msgError('请选择完整的省市区')
return false
}
if (!createOrderForm.shipping_address.trim()) {
feedback.msgError('请填写详细地址')
return false
}
return true
}
```
## 注意事项
1. **数据格式**:
- `region` 是数组:`['四川省', '成都市', '双流区']`
- 提交时需要组合成完整地址字符串
2. **必填验证**:
- 省市区选择器应该设置为必填
- 详细地址也应该必填
3. **字符限制**:
- 详细地址限制 200 字符
- 建议省市区 + 详细地址总长度不超过 250 字符
4. **兼容性**:
- 兼容现有的 `shipping_address` 字段
- 旧数据可能没有省市区信息,需要做好兼容处理
5. **性能优化**:
- 省市区数据较大时,考虑懒加载
- 使用虚拟滚动优化长列表
## 表单验证规则
更新验证规则:
```typescript
const createOrderRules: FormRules = {
// ... 其他规则
region: [
{
required: true,
message: '请选择省市区',
trigger: 'change',
validator: (rule, value, callback) => {
if (!value || value.length !== 3) {
callback(new Error('请选择完整的省市区'))
} else {
callback()
}
}
}
],
shipping_address: [
{ required: true, message: '请输入详细地址', trigger: 'blur' },
{ min: 5, message: '详细地址至少5个字符', trigger: 'blur' }
]
}
```
## 测试要点
### 前端测试
1. ✅ 省市区选择器显示正常
2. ✅ 可以正常选择省市区
3. ✅ 搜索功能正常
4. ✅ 清空功能正常
5. ✅ 必填验证正常
6. ✅ 数据绑定正确
### 集成测试
1. ✅ 创建订单 → 选择省市区 → 填写详细地址 → 提交成功
2. ✅ 查看订单 → 地址显示完整
3. ✅ 编辑订单 → 省市区回显正确
4. ✅ 打印订单 → 地址格式正确
## 完成状态
- ✅ 前端界面添加完成
- ✅ 数据模型更新完成
- ✅ 省市区数据添加完成(简化版)
- ✅ 事件处理方法添加完成
- ⏳ 等待完整省市区数据集成
- ⏳ 等待后端 API 支持
- ⏳ 等待表单验证规则更新
## 相关文件
- `admin/src/views/consumer/prescription/index.vue` - 处方订单列表页面
- 后端需要修改的文件(待确认):
- 订单模型文件
- 订单控制器文件
- 数据库迁移文件(如果需要单独存储省市区)