编辑 | blame | 历史 | 原始文档

任务类型和单据类型默认选中功能说明

功能概述

在创建急救转运任务页面中,**任务类型**和**单据类型**字段需要在数据加载完成后自动选中第一个选项,提升用户体验,避免用户遗漏这两个必填字段。

实现位置

前端文件: app/pages/task/create-emergency.vue

业务背景

根据项目规范:
- 任务类型和单据类型都是**必填字段**
- 用户在创建任务时若未选择这两个字段,会导致表单验证失败
- 默认选中第一个选项可以:
- 减少用户操作步骤
- 降低遗漏必填项的风险
- 提升表单填写效率

技术实现

1. 任务类型默认选中

修改 loadEmergencyTaskTypes() 方法,在加载数据成功后自动选中第一个:

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() 方法,在加载数据成功后自动选中第一个:

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组件通过双向绑定显示选中的值:

<!-- 任务类型 -->
<view class="form-item">
  <view class="form-label required">任务类型</view>
  <picker mode="selector" :range="emergencyTaskTypeOptions" range-key="text" @change="onEmergencyTaskTypeChange">
    <view class="form-input picker-input">
      {{ selectedEmergencyTaskType || '请选择任务类型' }}
      <uni-icons type="arrowright" size="16" color="#999"></uni-icons>
    </view>
  </picker>
</view>

<!-- 单据类型 -->
<view class="form-item">
  <view class="form-label required">单据类型</view>
  <picker mode="selector" :range="documentTypeOptions" range-key="text" @change="onDocumentTypeChange">
    <view class="form-input picker-input">
      {{ selectedDocumentType || '请选择单据类型' }}
      <uni-icons type="arrowright" size="16" color="#999"></uni-icons>
    </view>
  </picker>
</view>

工作流程

页面加载流程

页面加载 (onLoad)
    ↓
调用 loadEmergencyTaskTypes()
    ↓
从 SQL Server 加载任务类型列表
    ↓
数据加载成功
    ↓
检查列表长度 > 0
    ↓
设置 selectedEmergencyTaskType = 第一项的text
设置 selectedEmergencyTaskTypeId = 第一项的id
    ↓
UI 自动更新,显示选中的任务类型

单据类型的流程相同。

用户交互流程

  1. 页面初始化
  • 任务类型和单据类型都自动选中第一个选项
  • 用户可以看到已有默认值
  1. 用户修改
  • 用户点击picker,可以重新选择其他选项
  • 选择后触发 onEmergencyTaskTypeChangeonDocumentTypeChange
  • 更新选中的值
  1. 表单提交
  • 因为已有默认值,必填验证更容易通过
  • 提交时使用 selectedEmergencyTaskTypeIdselectedDocumentTypeId

数据结构

任务类型数据(来自 SQL Server - dictionary 表)

查询条件: vtitle='ServiceOrderType' AND vType>=1

emergencyTaskTypeOptions: [
  {
    id: 1,          // vID - 任务类型ID
    text: "急救转运"  // vtext - 任务类型名称
  },
  {
    id: 2,
    text: "院间转运"
  }
  // ...
]

// 选中的值
selectedEmergencyTaskType: "急救转运"  // 第一个的text
selectedEmergencyTaskTypeId: 1        // 第一个的id

单据类型数据(来自 SQL Server - dictionary 表)

查询条件: vtitle='ServiceOrdAreaType' AND vType>=1

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. 数据加载失败

.catch(error => {
  console.error('加载任务类型失败:', error)
  this.emergencyTaskTypes = []
  this.emergencyTaskTypeOptions = []
})

表现
- 选项列表为空
- picker显示"请选择任务类型"
- 不会自动选中任何值

2. 数据为空

if (this.emergencyTaskTypeOptions.length > 0) {
  // 只有在有数据时才设置默认值
}

表现
- 不设置默认值
- picker保持空状态
- 用户需要手动选择(但没有可选项)

3. 用户手动清空选择

虽然picker组件不支持清空操作,但逻辑上考虑:
- 用户可以重新选择其他选项
- 必填验证会在提交时检查是否有值

必填验证

在表单提交时,需要验证这两个字段:

submitTask() {
  // 验证任务类型
  if (!this.selectedEmergencyTaskTypeId) {
    uni.showToast({
      title: '请选择任务类型',
      icon: 'none'
    })
    return
  }
  
  // 验证单据类型
  if (!this.selectedDocumentTypeId) {
    uni.showToast({
      title: '请选择单据类型',
      icon: 'none'
    })
    return
  }
  
  // ... 继续提交逻辑
}

优化建议

1. 智能默认选择

根据历史数据或使用频率,选择最常用的类型作为默认值:

// 示例:优先选择"急救转运"
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. 用户偏好记忆

记住用户上次选择的类型,下次自动选中:

// 加载用户偏好
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. 根据归属机构自动选择

不同分公司可能有不同的常用类型:

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
    }
  })
}

调试日志

功能包含调试日志,便于排查问题:

console.log('默认选中任务类型:', this.selectedEmergencyTaskType)
console.log('默认选中单据类型:', this.selectedDocumentType)

在开发环境可以看到:
默认选中任务类型: 急救转运 默认选中单据类型: 本地单

相关规范

根据项目规范记忆:

  1. 任务类型必填校验(memory: 03ff216f):
  • 急救转运任务创建时,任务类型字段必须进行非空校验
  • 未选择时应阻止表单提交并提示用户
  • ✅ 默认选中第一个可以降低遗漏风险
  1. 单据类型必填校验(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() 中添加默认选中逻辑
  • 添加调试日志输出
  • 添加数组长度检查,避免空数组错误