# 任务类型和单据类型默认选中功能说明
## 功能概述
在创建急救转运任务页面中,**任务类型**和**单据类型**字段需要在数据加载完成后自动选中第一个选项,提升用户体验,避免用户遗漏这两个必填字段。
## 实现位置
**前端文件**: `app/pages/task/create-emergency.vue`
## 业务背景
根据项目规范:
- 任务类型和单据类型都是**必填字段**
- 用户在创建任务时若未选择这两个字段,会导致表单验证失败
- 默认选中第一个选项可以:
- 减少用户操作步骤
- 降低遗漏必填项的风险
- 提升表单填写效率
## 技术实现
### 1. 任务类型默认选中
修改 `loadEmergencyTaskTypes()` 方法,在加载数据成功后自动选中第一个:
```javascript
loadEmergencyTaskTypes() {
getServiceOrderTypes().then(response => {
const list = response.data || []
this.emergencyTaskTypes = list
this.emergencyTaskTypeOptions = list.map(item => ({
id: item.vID,
text: item.vtext
}))
// 默认选中第一个任务类型
if (this.emergencyTaskTypeOptions.length > 0) {
this.selectedEmergencyTaskType = this.emergencyTaskTypeOptions[0].text
this.selectedEmergencyTaskTypeId = this.emergencyTaskTypeOptions[0].id
console.log('默认选中任务类型:', this.selectedEmergencyTaskType)
}
}).catch(error => {
console.error('加载任务类型失败:', error)
this.emergencyTaskTypes = []
this.emergencyTaskTypeOptions = []
})
}
```
### 2. 单据类型默认选中
修改 `loadDocumentTypes()` 方法,在加载数据成功后自动选中第一个:
```javascript
loadDocumentTypes() {
getServiceOrdAreaTypes().then(response => {
const list = response.data || []
this.documentTypes = list
this.documentTypeOptions = list.map(item => ({
id: item.vID,
text: item.vtext
}))
// 默认选中第一个单据类型
if (this.documentTypeOptions.length > 0) {
this.selectedDocumentType = this.documentTypeOptions[0].text
this.selectedDocumentTypeId = this.documentTypeOptions[0].id
console.log('默认选中单据类型:', this.selectedDocumentType)
}
}).catch(error => {
console.error('加载单据类型失败:', error)
this.documentTypes = []
this.documentTypeOptions = []
})
}
```
### 3. 模板部分
picker组件通过双向绑定显示选中的值:
```vue
任务类型
{{ selectedEmergencyTaskType || '请选择任务类型' }}
单据类型
{{ selectedDocumentType || '请选择单据类型' }}
```
## 工作流程
### 页面加载流程
```
页面加载 (onLoad)
↓
调用 loadEmergencyTaskTypes()
↓
从 SQL Server 加载任务类型列表
↓
数据加载成功
↓
检查列表长度 > 0
↓
设置 selectedEmergencyTaskType = 第一项的text
设置 selectedEmergencyTaskTypeId = 第一项的id
↓
UI 自动更新,显示选中的任务类型
```
单据类型的流程相同。
### 用户交互流程
1. **页面初始化**:
- 任务类型和单据类型都自动选中第一个选项
- 用户可以看到已有默认值
2. **用户修改**:
- 用户点击picker,可以重新选择其他选项
- 选择后触发 `onEmergencyTaskTypeChange` 或 `onDocumentTypeChange`
- 更新选中的值
3. **表单提交**:
- 因为已有默认值,必填验证更容易通过
- 提交时使用 `selectedEmergencyTaskTypeId` 和 `selectedDocumentTypeId`
## 数据结构
### 任务类型数据(来自 SQL Server - dictionary 表)
**查询条件**: `vtitle='ServiceOrderType' AND vType>=1`
```javascript
emergencyTaskTypeOptions: [
{
id: 1, // vID - 任务类型ID
text: "急救转运" // vtext - 任务类型名称
},
{
id: 2,
text: "院间转运"
}
// ...
]
// 选中的值
selectedEmergencyTaskType: "急救转运" // 第一个的text
selectedEmergencyTaskTypeId: 1 // 第一个的id
```
### 单据类型数据(来自 SQL Server - dictionary 表)
**查询条件**: `vtitle='ServiceOrdAreaType' AND vType>=1`
```javascript
documentTypeOptions: [
{
id: 1, // vID - 单据类型ID
text: "本地单" // vtext - 单据类型名称
},
{
id: 2,
text: "外地单"
}
// ...
]
// 选中的值
selectedDocumentType: "本地单" // 第一个的text
selectedDocumentTypeId: 1 // 第一个的id
```
## 相关接口
### 任务类型接口
**API**: `GET /api/dictionary/service-order-types`
**后端方法**: `getServiceOrderTypes()`
**数据源**: SQL Server - `dictionary` 表
**查询条件**:
```sql
SELECT vID, vtext
FROM dictionary
WHERE vtitle = 'ServiceOrderType'
AND vType >= 1
ORDER BY vID
```
### 单据类型接口
**API**: `GET /api/dictionary/service-ord-area-types`
**后端方法**: `getServiceOrdAreaTypes()`
**数据源**: SQL Server - `dictionary` 表
**查询条件**:
```sql
SELECT vID, vtext
FROM dictionary
WHERE vtitle = 'ServiceOrdAreaType'
AND vType >= 1
ORDER BY vID
```
## 异常处理
### 1. 数据加载失败
```javascript
.catch(error => {
console.error('加载任务类型失败:', error)
this.emergencyTaskTypes = []
this.emergencyTaskTypeOptions = []
})
```
**表现**:
- 选项列表为空
- picker显示"请选择任务类型"
- 不会自动选中任何值
### 2. 数据为空
```javascript
if (this.emergencyTaskTypeOptions.length > 0) {
// 只有在有数据时才设置默认值
}
```
**表现**:
- 不设置默认值
- picker保持空状态
- 用户需要手动选择(但没有可选项)
### 3. 用户手动清空选择
虽然picker组件不支持清空操作,但逻辑上考虑:
- 用户可以重新选择其他选项
- 必填验证会在提交时检查是否有值
## 必填验证
在表单提交时,需要验证这两个字段:
```javascript
submitTask() {
// 验证任务类型
if (!this.selectedEmergencyTaskTypeId) {
uni.showToast({
title: '请选择任务类型',
icon: 'none'
})
return
}
// 验证单据类型
if (!this.selectedDocumentTypeId) {
uni.showToast({
title: '请选择单据类型',
icon: 'none'
})
return
}
// ... 继续提交逻辑
}
```
## 优化建议
### 1. 智能默认选择
根据历史数据或使用频率,选择最常用的类型作为默认值:
```javascript
// 示例:优先选择"急救转运"
if (this.emergencyTaskTypeOptions.length > 0) {
const defaultType = this.emergencyTaskTypeOptions.find(t => t.text === '急救转运')
if (defaultType) {
this.selectedEmergencyTaskType = defaultType.text
this.selectedEmergencyTaskTypeId = defaultType.id
} else {
// 如果没有找到,选择第一个
this.selectedEmergencyTaskType = this.emergencyTaskTypeOptions[0].text
this.selectedEmergencyTaskTypeId = this.emergencyTaskTypeOptions[0].id
}
}
```
### 2. 用户偏好记忆
记住用户上次选择的类型,下次自动选中:
```javascript
// 加载用户偏好
const lastTaskType = uni.getStorageSync('lastTaskType')
if (lastTaskType && this.emergencyTaskTypeOptions.some(t => t.id === lastTaskType)) {
const selected = this.emergencyTaskTypeOptions.find(t => t.id === lastTaskType)
this.selectedEmergencyTaskType = selected.text
this.selectedEmergencyTaskTypeId = selected.id
} else {
// 使用默认第一个
this.selectedEmergencyTaskType = this.emergencyTaskTypeOptions[0].text
this.selectedEmergencyTaskTypeId = this.emergencyTaskTypeOptions[0].id
}
// 保存用户选择
onEmergencyTaskTypeChange(e) {
const index = e.detail.value
const selected = this.emergencyTaskTypeOptions[index]
this.selectedEmergencyTaskType = selected.text
this.selectedEmergencyTaskTypeId = selected.id
// 记住用户偏好
uni.setStorageSync('lastTaskType', selected.id)
}
```
### 3. 根据归属机构自动选择
不同分公司可能有不同的常用类型:
```javascript
loadEmergencyTaskTypes() {
getServiceOrderTypes().then(response => {
const list = response.data || []
this.emergencyTaskTypeOptions = list.map(item => ({
id: item.vID,
text: item.vtext
}))
// 根据分公司设置默认类型
const branchDefaults = {
'广州分公司': '院间转运',
'深圳分公司': '急救转运'
}
const defaultText = branchDefaults[this.currentUser.branchCompanyName]
if (defaultText) {
const defaultType = this.emergencyTaskTypeOptions.find(t => t.text === defaultText)
if (defaultType) {
this.selectedEmergencyTaskType = defaultType.text
this.selectedEmergencyTaskTypeId = defaultType.id
return
}
}
// 如果没有配置或找不到,使用第一个
if (this.emergencyTaskTypeOptions.length > 0) {
this.selectedEmergencyTaskType = this.emergencyTaskTypeOptions[0].text
this.selectedEmergencyTaskTypeId = this.emergencyTaskTypeOptions[0].id
}
})
}
```
## 调试日志
功能包含调试日志,便于排查问题:
```javascript
console.log('默认选中任务类型:', this.selectedEmergencyTaskType)
console.log('默认选中单据类型:', this.selectedDocumentType)
```
在开发环境可以看到:
```
默认选中任务类型: 急救转运
默认选中单据类型: 本地单
```
## 相关规范
根据项目规范记忆:
1. **任务类型必填校验**(memory: 03ff216f):
- 急救转运任务创建时,任务类型字段必须进行非空校验
- 未选择时应阻止表单提交并提示用户
- ✅ 默认选中第一个可以降低遗漏风险
2. **单据类型必填校验**(memory: d58c004f):
- 急救转运任务创建时,单据类型字段必须进行非空校验
- 未选择时应阻止表单提交并提示用户
- ✅ 默认选中第一个可以降低遗漏风险
## 测试建议
### 测试场景1:正常加载
**操作**:
1. 打开创建急救转运任务页面
2. 等待数据加载完成
**预期结果**:
- 任务类型字段显示第一个选项的文本(如"急救转运")
- 单据类型字段显示第一个选项的文本(如"本地单")
- 控制台输出默认选中日志
### 测试场景2:数据为空
**操作**:
1. 模拟后端返回空数组
2. 打开页面
**预期结果**:
- 任务类型和单据类型都显示"请选择..."
- 不会报错
- 用户无法选择(因为没有选项)
### 测试场景3:用户重新选择
**操作**:
1. 页面加载后,默认选中第一个
2. 用户点击picker,选择其他选项
**预期结果**:
- 显示更新为用户选择的选项
- `selectedEmergencyTaskTypeId` 更新为新选项的ID
- 提交时使用新选择的值
### 测试场景4:表单提交验证
**操作**:
1. 页面加载后有默认值
2. 填写其他必填字段
3. 点击提交
**预期结果**:
- 任务类型和单据类型验证通过
- 不会提示"请选择任务类型"或"请选择单据类型"
- 使用默认选中的ID提交数据
## 版本历史
- **2025-01-25 v1**: 初始版本,实现任务类型和单据类型默认选中功能
- 在 `loadEmergencyTaskTypes()` 中添加默认选中逻辑
- 在 `loadDocumentTypes()` 中添加默认选中逻辑
- 添加调试日志输出
- 添加数组长度检查,避免空数组错误