358 lines
10 KiB
Markdown
358 lines
10 KiB
Markdown
# 省市区选择器功能说明
|
||
|
||
## 功能描述
|
||
|
||
在创建处方业务订单时,添加省市区级联选择器,方便用户选择收货地址的省市区信息。
|
||
|
||
## 修改内容
|
||
|
||
### 1. 表单界面(admin/src/views/consumer/prescription/index.vue)
|
||
|
||
#### 添加省市区选择器(第 792-810 行)
|
||
|
||
```vue
|
||
<el-col :span="12">
|
||
<el-form-item label="收货手机" prop="recipient_phone">
|
||
<el-input v-model="createOrderForm.recipient_phone" placeholder="用于物流联系" maxlength="20" />
|
||
</el-form-item>
|
||
</el-col>
|
||
<el-col :span="24">
|
||
<el-form-item label="省市区" prop="region">
|
||
<el-cascader
|
||
v-model="createOrderForm.region"
|
||
:options="regionOptions"
|
||
:props="{ value: 'name', label: 'name', children: 'children', emitPath: false, checkStrictly: false }"
|
||
placeholder="请选择省/市/区"
|
||
clearable
|
||
filterable
|
||
class="w-full"
|
||
@change="handleRegionChange"
|
||
/>
|
||
</el-form-item>
|
||
</el-col>
|
||
<el-col :span="24">
|
||
<el-form-item label="详细地址" prop="shipping_address">
|
||
<el-input
|
||
v-model="createOrderForm.shipping_address"
|
||
type="textarea"
|
||
:rows="2"
|
||
placeholder="请输入街道、门牌号等详细地址"
|
||
maxlength="200"
|
||
show-word-limit
|
||
/>
|
||
</el-form-item>
|
||
</el-col>
|
||
```
|
||
|
||
**组件配置说明:**
|
||
- `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
|
||
<el-select v-model="selectedAddressId" placeholder="选择常用地址" @change="fillAddress">
|
||
<el-option
|
||
v-for="addr in addressBook"
|
||
:key="addr.id"
|
||
:label="`${addr.name} ${addr.phone} ${addr.full_address}`"
|
||
:value="addr.id"
|
||
/>
|
||
</el-select>
|
||
```
|
||
|
||
### 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` - 处方订单列表页面
|
||
- 后端需要修改的文件(待确认):
|
||
- 订单模型文件
|
||
- 订单控制器文件
|
||
- 数据库迁移文件(如果需要单独存储省市区)
|