# 联系人必填和归属机构默认选中功能说明
## 功能概述
本次优化包含两个功能点:
1. **联系人字段设为必填**:确保急救转运任务中联系人信息完整,便于紧急情况下联系
2. **归属机构默认选中当前用户分公司**:自动设置用户所属分公司,同时更新地域过滤条件,优化用户体验
## 实现位置
**前端文件**: `app/pages/task/create-emergency.vue`
## 一、联系人必填功能
### 1.1 业务背景
急救转运任务中,联系人是关键信息,用于:
- 紧急情况下的沟通联系
- 确认患者身份和情况
- 协调转运过程中的各项事宜
- 后续任务跟进和反馈
因此将联系人字段设为必填,确保信息完整性。
### 1.2 技术实现
#### 模板修改
将联系人的label添加`required`类:
```vue
联系人
```
#### 表单验证
在 `validateForm()` 方法中添加联系人验证:
```javascript
validateForm() {
// ... 其他验证
if (!this.taskForm.patient.contact) {
this.$modal.showToast('请输入联系人')
return false
}
if (!this.taskForm.patient.name) {
this.$modal.showToast('请输入患者姓名')
return false
}
// ... 其他验证
return true
}
```
**验证顺序**:
1. 任务车辆
2. 任务类型
3. 单据类型
4. ✅ **联系人**(新增)
5. 患者姓名
6. 联系电话
7. 转出医院信息
8. 转入医院信息
### 1.3 样式说明
必填字段标识通过CSS伪元素实现:
```scss
.form-label {
&.required::before {
content: '*';
color: #ff4d4f;
margin-right: 4rpx;
font-weight: bold;
}
}
```
显示效果:`* 联系人`
## 二、归属机构默认选中功能
### 2.1 业务背景
根据项目规范和用户体验:
- 用户创建任务时,归属机构通常就是自己所在的分公司
- 自动选中可以减少用户操作步骤
- 归属机构会影响医院列表的地域过滤,需要自动更新
### 2.2 技术实现
#### 修改 loadBranchCompanies() 方法
```javascript
loadBranchCompanies() {
listBranchCompany().then(response => {
const list = response.data || []
// 过滤出 parent_id = 100 的部门(分公司)
this.organizationOptions = list.filter(dept => dept.parentId === 100)
// 生成picker的数据源(只显示名称)
this.organizations = this.organizationOptions.map(dept => dept.deptName)
// 默认设置为当前用户的分公司
if (this.currentUser.branchCompanyName) {
const index = this.organizationOptions.findIndex(
dept => dept.deptName === this.currentUser.branchCompanyName
)
if (index !== -1) {
this.selectedOrganization = this.currentUser.branchCompanyName
// 提取地域关键词(去除"分公司"后缀)
this.selectedRegion = this.selectedOrganization.replace(/分公司$/g, '').trim()
console.log('默认选中归属机构:', this.selectedOrganization, '地域:', this.selectedRegion)
// 加载医院列表(带地域过滤)
this.loadDefaultHospitals()
}
}
}).catch(error => {
console.error('加载分公司数据失败:', error)
this.organizationOptions = []
this.organizations = []
})
}
```
#### 优化 onLoad() 方法
移除重复的医院列表加载和归属机构设置:
```javascript
onLoad(options) {
// 先加载车辆列表,然后加载绑定车辆信息
this.getAvailableVehicles().then(() => {
this.getUserBoundVehicleInfo()
})
this.initSelectedStaff()
this.loadDeptStaff()
// 加载分公司数据(会自动设置默认分公司并加载医院列表)
this.loadBranchCompanies()
// 加载科室字典数据
this.loadDepartments()
// 加载任务类型数据
this.loadEmergencyTaskTypes()
// 加载单据类型数据
this.loadDocumentTypes()
}
```
**优化说明**:
- ❌ 移除了独立的 `this.selectedOrganization = this.currentUser.branchCompanyName`
- ❌ 移除了独立的 `this.loadDefaultHospitals()`
- ✅ `loadBranchCompanies()` 内部会完成这两个操作
- ✅ 避免了医院列表的重复加载
### 2.3 工作流程
```
页面加载 (onLoad)
↓
调用 loadBranchCompanies()
↓
从后端加载分公司列表
↓
过滤 parent_id = 100 的部门
↓
检查当前用户的 branchCompanyName
↓
在分公司列表中查找匹配项
↓
设置 selectedOrganization = 用户分公司名称
设置 selectedRegion = 提取的地域关键词
↓
调用 loadDefaultHospitals() 加载医院列表
↓
医院列表按地域过滤
↓
UI 更新,显示选中的归属机构
```
### 2.4 地域提取逻辑
将分公司名称转换为地域关键词:
```javascript
// 例如:"广州分公司" → "广州"
this.selectedRegion = this.selectedOrganization.replace(/分公司$/g, '').trim()
```
**示例**:
- "广州分公司" → "广州"
- "深圳分公司" → "深圳"
- "东莞分公司" → "东莞"
这个地域关键词会用于医院搜索的过滤条件。
## 三、数据流程图
### 联系人必填验证流程
```
用户点击"保存"
↓
调用 submitTask()
↓
调用 validateForm()
↓
检查 taskForm.patient.contact
↓
├─ 为空 → 提示"请输入联系人" → 阻止提交
└─ 有值 → 继续其他验证
```
### 归属机构默认选中流程
```
页面加载
↓
获取 currentUser.branchCompanyName
↓
├─ 有值(如"广州分公司")
│ ↓
│ 在 organizationOptions 中查找
│ ↓
│ ├─ 找到
│ │ ↓
│ │ 设置 selectedOrganization = "广州分公司"
│ │ 设置 selectedRegion = "广州"
│ │ 加载医院列表(地域过滤)
│ │ ↓
│ │ UI 显示"广州分公司"
│ │
│ └─ 未找到
│ ↓
│ 不设置默认值
│ 医院列表不过滤
│
└─ 无值
↓
不设置默认值
用户需要手动选择
```
## 四、数据结构
### 用户信息(来自 Vuex state)
```javascript
currentUser: {
userId: 1,
name: "张三",
nickName: "张三",
deptId: 101,
branchCompanyId: 100,
branchCompanyName: "广州分公司" // 关键字段
}
```
### 归属机构数据
```javascript
// 原始数据(来自后端)
organizationOptions: [
{
deptId: 100,
deptName: "广州分公司",
parentId: 100
},
{
deptId: 101,
deptName: "深圳分公司",
parentId: 100
}
]
// picker 显示数据
organizations: ["广州分公司", "深圳分公司"]
// 选中的值
selectedOrganization: "广州分公司"
selectedRegion: "广州" // 用于医院搜索过滤
```
### 表单数据
```javascript
taskForm: {
patient: {
contact: "李四", // ✅ 必填
phone: "13800138000", // ✅ 必填
name: "王五", // ✅ 必填
gender: "male",
idCard: "440106199001011234",
condition: ""
},
// ... 其他字段
}
```
## 五、相关接口
### 获取分公司列表
**API**: `GET /system/dept/list?parentId=100`
**前端方法**: `listBranchCompany()`
**返回数据**:
```json
{
"code": 200,
"data": [
{
"deptId": 100,
"deptName": "广州分公司",
"parentId": 100,
"orderNum": 1,
"leader": "张经理",
"phone": "020-12345678",
"status": "0"
},
{
"deptId": 101,
"deptName": "深圳分公司",
"parentId": 100,
"orderNum": 2,
"leader": "李经理",
"phone": "0755-87654321",
"status": "0"
}
]
}
```
### 搜索医院(带地域过滤)
**API**: `GET /hospital/search?keyword={keyword}®ion={region}`
**调用示例**:
```javascript
// selectedRegion = "广州"
searchHospitals('', '广州').then(response => {
// 返回广州地区的医院列表(前100条)
})
```
**过滤逻辑**(后端SQL):
```sql
WHERE (HopsProvince LIKE '%广州%'
OR HopsCity LIKE '%广州%'
OR HopsArea LIKE '%广州%')
```
## 六、异常处理
### 1. 用户未设置分公司
**场景**: `currentUser.branchCompanyName` 为空
**处理**:
- 不设置默认值
- `selectedOrganization` 保持为空
- picker 显示"请选择归属机构"
- 医院列表不进行地域过滤
### 2. 用户分公司不在列表中
**场景**: 数据不一致,用户的分公司不在 parent_id=100 的列表中
**处理**:
```javascript
const index = this.organizationOptions.findIndex(
dept => dept.deptName === this.currentUser.branchCompanyName
)
if (index !== -1) {
// 找到了,设置默认值
} else {
// 未找到,不设置默认值
// 用户需要手动选择
}
```
### 3. 联系人为空提交
**场景**: 用户未填写联系人就点击保存
**处理**:
```javascript
if (!this.taskForm.patient.contact) {
this.$modal.showToast('请输入联系人')
return false // 阻止提交
}
```
**用户看到**: Toast 提示"请输入联系人"
## 七、测试建议
### 测试场景1:联系人必填验证
**步骤**:
1. 打开创建急救转运任务页面
2. 填写其他必填字段(车辆、患者姓名、电话等)
3. 不填写联系人
4. 点击"保存"按钮
**预期结果**:
- 显示 Toast 提示"请输入联系人"
- 表单不提交
- 用户停留在当前页面
### 测试场景2:归属机构默认选中
**前置条件**: 当前用户的 branchCompanyName = "广州分公司"
**步骤**:
1. 打开创建急救转运任务页面
2. 观察归属机构字段
**预期结果**:
- 归属机构字段自动显示"广州分公司"
- `selectedRegion` = "广州"
- 医院列表加载时带地域过滤
- 控制台输出: "默认选中归属机构: 广州分公司 地域: 广州"
### 测试场景3:归属机构切换
**步骤**:
1. 页面加载后,归属机构默认显示"广州分公司"
2. 用户点击归属机构选择器
3. 选择"深圳分公司"
**预期结果**:
- `selectedOrganization` 更新为"深圳分公司"
- `selectedRegion` 更新为"深圳"
- 自动重新加载医院列表(带新的地域过滤)
- 医院搜索结果只显示深圳地区的医院
### 测试场景4:用户无分公司
**前置条件**: 当前用户的 branchCompanyName 为空或 null
**步骤**:
1. 打开创建急救转运任务页面
2. 观察归属机构字段
**预期结果**:
- 归属机构显示"请选择归属机构"
- 没有默认选中项
- 医院列表加载时不进行地域过滤
- 用户可以手动选择归属机构
## 八、优化建议
### 1. 联系人智能填充
根据患者姓名或历史记录,智能推荐联系人:
```javascript
// 监听患者姓名变化
watch: {
'taskForm.patient.name'(newVal) {
// 如果联系人为空,可以自动填充为患者姓名
if (!this.taskForm.patient.contact && newVal) {
this.taskForm.patient.contact = newVal
}
}
}
```
### 2. 联系人常用列表
记录用户常用的联系人,提供快速选择:
```javascript
// 本地存储常用联系人
const frequentContacts = uni.getStorageSync('frequentContacts') || []
// 显示快速选择按钮
{{ contact }}
```
### 3. 归属机构权限控制
某些用户可能只能看到特定的分公司:
```javascript
loadBranchCompanies() {
listBranchCompany().then(response => {
let list = response.data || []
// 根据用户权限过滤
if (!this.currentUser.isAdmin) {
list = list.filter(dept =>
dept.deptId === this.currentUser.branchCompanyId
)
}
this.organizationOptions = list.filter(dept => dept.parentId === 100)
// ...
})
}
```
## 九、相关规范
根据项目记忆:
1. **分公司数据加载规范**(memory: ba4557cf):
- ✅ 调用 `/system/dept/list` 接口
- ✅ 传入 `parentId=100` 参数
- ✅ 获取 parent_id=100 的部门作为分公司列表
2. **急救转运任务车辆自动填充规则**(memory: eec5a112):
- 车辆选择器必须加载当前用户所在分公司的所有车辆
- ✅ 本次修改确保了归属机构默认为用户分公司
- ✅ 地域过滤确保医院列表与分公司地域相关
## 十、版本历史
- **2025-01-25 v1**: 初始版本
- ✅ 联系人字段设为必填
- ✅ 添加联系人必填验证
- ✅ 归属机构默认选中当前用户分公司
- ✅ 自动更新 selectedRegion
- ✅ 优化 onLoad 方法,避免重复加载
- ✅ 添加调试日志