wlzboy
15 小时以前 f08739f46afe856f60ebb1d21ab23d72947629ed
app/pagesTask/edit-emergency.vue
@@ -19,7 +19,8 @@
      />
      
      <view class="form-item">
        <OrganizationSelector
        <OrganizationSelector
          ref="organizationSelector"
          v-model="selectedOrganizationId"
          :required="true"
          :auto-select-user-dept="false"
@@ -38,6 +39,26 @@
      />
      
      <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>
      <view class="form-item">
        <view class="form-label required">转运时间</view>
        <uni-datetime-picker 
          v-model="taskForm.transferTime" 
@@ -53,6 +74,7 @@
        :required="false"
        :auto-add-current-user="false"
        :current-user-removable="true"
        :branch-dept-ids="allOrganizationIds"
        @change="onStaffChange"
      />
      
@@ -117,25 +139,61 @@
      
      <view class="form-section-title">转出医院信息</view>
      <HospitalSelector
        label="区院名称"
        label="医院名称"
        address-label="转出地址"
        :required="true"
        :show-department="false"
        v-model="taskForm.hospitalOut"
        :dept-id="selectedOrganizationId"
        @change="onHospitalOutChange"
        @address-selected="onHospitalOutAddressSelected"
      />
      <DepartmentSelector
        label="转出科室"
        :required="true"
        v-model="taskForm.hospitalOut.department"
        :department-id="taskForm.hospitalOut.departmentId"
        :is-home="taskForm.hospitalOut.name === '家中'"
        @change="onHospitalOutDepartmentChange"
      />
      <view class="form-item">
        <view class="form-label">床号</view>
        <input
          class="form-input"
          placeholder="请输入床号"
          v-model="taskForm.hospitalOut.bedNumber"
        />
      </view>
      
      <view class="form-section-title">转入医院信息</view>
      <HospitalSelector
        label="医院名称"
        address-label="转入地址"
        :required="true"
        :show-department="false"
        v-model="taskForm.hospitalIn"
        :dept-id="selectedOrganizationId"
        @change="onHospitalInChange"
        @address-selected="onHospitalInAddressSelected"
      />
      <DepartmentSelector
        label="转入科室"
        :required="true"
        v-model="taskForm.hospitalIn.department"
        :department-id="taskForm.hospitalIn.departmentId"
        :is-home="taskForm.hospitalIn.name === '家中'"
        @change="onHospitalInDepartmentChange"
      />
      <view class="form-item">
        <view class="form-label">床号</view>
        <input
          class="form-input"
          placeholder="请输入床号"
          v-model="taskForm.hospitalIn.bedNumber"
        />
      </view>
      
      <view class="form-item">
        <view class="form-label">转运距离</view>
@@ -193,8 +251,9 @@
import uniDatetimePicker from '@/uni_modules/uni-datetime-picker/components/uni-datetime-picker/uni-datetime-picker.vue'
import uniPopup from '@/uni_modules/uni-popup/components/uni-popup/uni-popup.vue'
import { getTask, updateTask } from "@/api/task"
import { baiduDistanceByAddress } from "@/api/map"
import { tiandituDistanceByAddress } from "@/api/map"
import { calculateTransferPrice } from "@/api/price"
import { getServiceOrdAreaTypes, getServiceOrderTypes } from "@/api/dictionary"
import MapSelector from './components/map-selector.vue'
import VehicleSelector from './components/VehicleSelector.vue'
import OrganizationSelector from './components/OrganizationSelector.vue'
@@ -202,6 +261,7 @@
import DiseaseSelector from './components/DiseaseSelector.vue'
import DepartureSelector from './components/DepartureSelector.vue'
import StaffSelector from './components/StaffSelector.vue'
import DepartmentSelector from './components/DepartmentSelector.vue'
import distanceCalculator from '@/mixins/distanceCalculator.js'
export default {
@@ -214,7 +274,8 @@
    HospitalSelector,
    DiseaseSelector,
    DepartureSelector,
    StaffSelector
    StaffSelector,
    DepartmentSelector
  },
  mixins: [distanceCalculator],
  data() {
@@ -224,6 +285,7 @@
      taskDetail: null,
      selectedVehicleId: null,
      selectedOrganizationId: null,
      allOrganizationIds: [], // 所有可选机构ID数组
      selectedRegion: '',
      mapSelectorType: '',
      // 扩展 addressCoordinates 支持多种键名
@@ -239,6 +301,17 @@
      departureLatitude: null,
      selectedDiseases: [], // 已选择的病情列表(确保初始化为空数组)
      selectedStaff: [], // 已选择的人员列表(确保初始化为空数组)
      // 任务类型和单据类型相关
      selectedEmergencyTaskType: '', // 选中的任务类型文本
      selectedEmergencyTaskTypeId: null, // 选中的任务类型ID
      selectedDocumentType: '', // 选中的单据类型文本
      selectedDocumentTypeId: null, // 选中的单据类型ID
      pendingTaskTypeId: null, // 等待设置的任务类型ID
      pendingDocumentTypeId: null, // 等待设置的单据类型ID
      emergencyTaskTypes: [], // 任务类型列表(从 SQL Server 动态加载)
      emergencyTaskTypeOptions: [], // 任务类型选项(用于picker显示)
      documentTypes: [], // 单据类型列表
      documentTypeOptions: [], // 单据类型选项(用于picker显示)
      taskForm: {
        transferTime: '',
        patient: {
@@ -285,12 +358,21 @@
    if (options.id) {
      this.taskId = options.id
      this.loadTaskDetail()
      // 加载任务类型数据
      this.loadEmergencyTaskTypes()
      // 加载单据类型数据
      this.loadDocumentTypes()
    } else {
      this.$modal.showToast('任务ID不能为空')
      setTimeout(() => {
        uni.navigateBack()
      }, 1500)
    }
  },
  mounted() {
    // 页面挂载后加载所有机构ID
    this.loadAllOrganizationIds()
  },
  methods: {
    // 加载任务详情
@@ -320,8 +402,9 @@
          const info = this.taskDetail.emergencyInfo
          console.log('转运任务信息:', info)
          
          // 转运时间
          this.taskForm.transferTime = this.taskDetail.plannedStartTime || ''
          // 转运时间(修复:1900年的日期显示为空)
          const transferTime = this.taskDetail.plannedStartTime || ''
          this.taskForm.transferTime = transferTime && transferTime.startsWith('1900') ? '' : transferTime
          
          // 患者信息
          this.taskForm.patient.contact = info.patientContact || ''
@@ -338,8 +421,10 @@
          this.taskForm.hospitalOut.id = info.hospitalOutId || null
          this.taskForm.hospitalOut.name = info.hospitalOutName || ''
          this.taskForm.hospitalOut.department = info.hospitalOutDepartment || ''
          this.taskForm.hospitalOut.departmentId = info.hospitalOutDepartmentId || null
          this.taskForm.hospitalOut.bedNumber = info.hospitalOutBedNumber || ''
          this.taskForm.hospitalOut.address = info.hospitalOutAddress || ''
          console.log('转出医院科室ID:', info.hospitalOutDepartmentId)
          
          // 加载转出医院GPS坐标(不显示,但保存在数据中)
          if (info.hospitalOutLongitude && info.hospitalOutLatitude) {
@@ -354,8 +439,10 @@
          this.taskForm.hospitalIn.id = info.hospitalInId || null
          this.taskForm.hospitalIn.name = info.hospitalInName || ''
          this.taskForm.hospitalIn.department = info.hospitalInDepartment || ''
          this.taskForm.hospitalIn.departmentId = info.hospitalInDepartmentId || null
          this.taskForm.hospitalIn.bedNumber = info.hospitalInBedNumber || ''
          this.taskForm.hospitalIn.address = info.hospitalInAddress || ''
          console.log('转入医院科室ID:', info.hospitalInDepartmentId)
          
          // 加载转入医院GPS坐标(不显示,但保存在数据中)
          if (info.hospitalInLongitude && info.hospitalInLatitude) {
@@ -369,10 +456,36 @@
          // 转运距离和价格
          this.taskForm.transferDistance = info.transferDistance ? String(info.transferDistance) : ''
          this.taskForm.price = info.transferPrice ? String(info.transferPrice) : ''
          // 任务类型和单据类型
          if (info.taskTypeId) {
            // 直接设置任务类型,如果选项还未加载完成,则在加载完成后再次设置
            const taskType = this.emergencyTaskTypeOptions.find(option => option.id == info.taskTypeId)
            if (taskType) {
              this.selectedEmergencyTaskType = taskType.text
              this.selectedEmergencyTaskTypeId = taskType.id
            } else {
              // 如果选项还未加载完成,标记需要设置的ID
              this.pendingTaskTypeId = info.taskTypeId
            }
          }
          if (info.documentTypeId) {
            // 直接设置单据类型,如果选项还未加载完成,则在加载完成后再次设置
            const docType = this.documentTypeOptions.find(option => option.id == info.documentTypeId)
            if (docType) {
              this.selectedDocumentType = docType.text
              this.selectedDocumentTypeId = docType.id
            } else {
              // 如果选项还未加载完成,标记需要设置的ID
              this.pendingDocumentTypeId = info.documentTypeId
            }
          }
        } else {
          console.warn('任务详情中没有emergencyInfo字段,尝试从主对象获取数据')
          // 兼容处理:如果emergencyInfo不存在,尝试从主对象获取
          this.taskForm.transferTime = this.taskDetail.plannedStartTime || ''
          const transferTime = this.taskDetail.plannedStartTime || ''
          this.taskForm.transferTime = transferTime && transferTime.startsWith('1900') ? '' : transferTime
          this.taskForm.transferDistance = this.taskDetail.estimatedDistance ? String(this.taskDetail.estimatedDistance) : ''
        }
        
@@ -417,16 +530,24 @@
          console.log('设置目标地坐标:', this.taskDetail.destinationLongitude, this.taskDetail.destinationLatitude)
        }
        
        // 设置执行人员(修复:确保 assignees 不为 null)
        // 设置执行人员(修复:确保 assignees 不为 null,并正确映射字段)
        if (this.taskDetail.assignees && Array.isArray(this.taskDetail.assignees) && this.taskDetail.assignees.length > 0) {
          console.log('原始执行人员数据:', this.taskDetail.assignees)
          this.selectedStaff = this.taskDetail.assignees.map(assignee => ({
            userId: assignee.userId,
            nickName: assignee.userName,
            type: assignee.userType || 'driver',
            phonenumber: '',
            deptName: ''
          }))
          this.selectedStaff = this.taskDetail.assignees.map(assignee => {
            console.log('处理执行人员:', assignee)
            console.log('  - userName:', assignee.userName)
            console.log('  - nickName:', assignee.nickName)
            console.log('  - phonenumber:', assignee.phonenumber)
            console.log('  - phone:', assignee.phone)
            return {
              userId: assignee.userId,
              nickName: assignee.userName || assignee.nickName || '',
              type: assignee.userType || 'driver',
              phonenumber: assignee.phonenumber || assignee.phone || '',
              deptName: assignee.deptName || ''
            }
          })
          console.log('处理后的执行人员列表:', this.selectedStaff)
        } else {
          console.warn('任务没有分配执行人员或assignees为空')
@@ -449,6 +570,109 @@
    // 车辆选择变化
    onVehicleChange(vehicle) {
      console.log('选中车辆:', vehicle)
    },
    // 加载任务类型数据(从 SQL Server)
    loadEmergencyTaskTypes() {
      getServiceOrderTypes().then(response => {
        const list = response.data || []
        this.emergencyTaskTypes = list
        this.emergencyTaskTypeOptions = list.map(item => ({
          id: item.vID,
          text: item.vtext
        }))
        // 如果任务详情已加载,设置当前选中的任务类型
        if (this.taskDetail && this.taskDetail.emergencyInfo && this.taskDetail.emergencyInfo.taskTypeId) {
          const currentType = this.emergencyTaskTypeOptions.find(option => option.id == this.taskDetail.emergencyInfo.taskTypeId)
          if (currentType) {
            this.selectedEmergencyTaskType = currentType.text
            this.selectedEmergencyTaskTypeId = currentType.id
          }
        }
        // 检查是否有待设置的任务类型ID
        if (this.pendingTaskTypeId) {
          const pendingType = this.emergencyTaskTypeOptions.find(option => option.id == this.pendingTaskTypeId)
          if (pendingType) {
            this.selectedEmergencyTaskType = pendingType.text
            this.selectedEmergencyTaskTypeId = pendingType.id
            this.pendingTaskTypeId = null
          }
        }
      }).catch(error => {
        console.error('加载任务类型失败:', error)
        this.emergencyTaskTypes = []
        this.emergencyTaskTypeOptions = []
      })
    },
    // 任务类型选择
    onEmergencyTaskTypeChange(e) {
      const index = e.detail.value
      const selected = this.emergencyTaskTypeOptions[index]
      this.selectedEmergencyTaskType = selected.text
      this.selectedEmergencyTaskTypeId = selected.id
    },
    // 加载单据类型数据
    loadDocumentTypes() {
      getServiceOrdAreaTypes().then(response => {
        const list = response.data || []
        this.documentTypes = list
        this.documentTypeOptions = list.map(item => ({
          id: item.vID,
          text: item.vtext
        }))
        // 如果任务详情已加载,设置当前选中的单据类型
        if (this.taskDetail && this.taskDetail.emergencyInfo && this.taskDetail.emergencyInfo.documentTypeId) {
          const currentType = this.documentTypeOptions.find(option => option.id == this.taskDetail.emergencyInfo.documentTypeId)
          if (currentType) {
            this.selectedDocumentType = currentType.text
            this.selectedDocumentTypeId = currentType.id
          }
        }
        // 检查是否有待设置的单据类型ID
        if (this.pendingDocumentTypeId) {
          const pendingType = this.documentTypeOptions.find(option => option.id == this.pendingDocumentTypeId)
          if (pendingType) {
            this.selectedDocumentType = pendingType.text
            this.selectedDocumentTypeId = pendingType.id
            this.pendingDocumentTypeId = null
          }
        }
      }).catch(error => {
        console.error('加载单据类型失败:', error)
        this.documentTypes = []
        this.documentTypeOptions = []
      })
    },
    // 单据类型选择
    onDocumentTypeChange(e) {
      const index = e.detail.value
      const selected = this.documentTypeOptions[index]
      this.selectedDocumentType = selected.text
      this.selectedDocumentTypeId = selected.id
    },
    // 加载所有机构ID
    loadAllOrganizationIds() {
      // 通过 OrganizationSelector 组件获取所有机构
      const orgSelector = this.$refs.organizationSelector
      if (orgSelector) {
        orgSelector.reload().then(organizations => {
          this.allOrganizationIds = organizations.map(org => org.deptId)
          console.log('所有机构ID:', this.allOrganizationIds)
        })
      } else {
        // 如果组件还未挂载,稍后重试
        setTimeout(() => {
          this.loadAllOrganizationIds()
        }, 100)
      }
    },
    
    // 归属机构选择变化
@@ -487,6 +711,13 @@
      console.log('转出医院变化:', hospitalData)
      // 组件已经通过 v-model 更新了 taskForm.hospitalOut
      
      // 如果选择的是"家中",自动设置科室为"其它"
      if (hospitalData.name === '家中') {
        this.taskForm.hospitalOut.department = '其它'
        this.taskForm.hospitalOut.departmentId = null
      }
      // 注意:选择新的医院时,不自动更新科室信息,保持用户已选择的科室
      // 如果转入地址已填写,自动计算距离
      if (this.taskForm.hospitalIn.address) {
        // 如果两个都不是"家中",使用医院距离计算
@@ -511,6 +742,13 @@
      console.log('转入医院变化:', hospitalData)
      // 组件已经通过 v-model 更新了 taskForm.hospitalIn
      
      // 如果选择的是"家中",自动设置科室为"其它"
      if (hospitalData.name === '家中') {
        this.taskForm.hospitalIn.department = '其它'
        this.taskForm.hospitalIn.departmentId = null
      }
      // 注意:选择新的医院时,不自动更新科室信息,保持用户已选择的科室
      // 如果转出地址已填写,自动计算距离
      if (this.taskForm.hospitalOut.address) {
        // 如果两个都不是"家中",使用医院距离计算
@@ -527,6 +765,30 @@
    onHospitalInAddressSelected(data) {
      if (this.taskForm.hospitalOut.address) {
        this.calculateDistanceByManualAddress()
      }
    },
    // 转出科室变化
    onHospitalOutDepartmentChange(data) {
      console.log('转出科室变化:', data)
      if (data && typeof data === 'object') {
        this.taskForm.hospitalOut.department = data.department
        this.taskForm.hospitalOut.departmentId = data.departmentId
      } else {
        this.taskForm.hospitalOut.department = data
        this.taskForm.hospitalOut.departmentId = null
      }
    },
    // 转入科室变化
    onHospitalInDepartmentChange(data) {
      console.log('转入科室变化:', data)
      if (data && typeof data === 'object') {
        this.taskForm.hospitalIn.department = data.department
        this.taskForm.hospitalIn.departmentId = data.departmentId
      } else {
        this.taskForm.hospitalIn.department = data
        this.taskForm.hospitalIn.departmentId = null
      }
    },
    
@@ -700,6 +962,16 @@
        return false
      }
      
      if (!this.selectedEmergencyTaskType) {
        this.$modal.showToast('请选择任务类型')
        return false
      }
      if (!this.selectedDocumentType) {
        this.$modal.showToast('请选择单据类型')
        return false
      }
      if (!this.taskForm.patient.contact) {
        this.$modal.showToast('请输入联系人')
        return false
@@ -715,6 +987,12 @@
        return false
      }
      
      // 验证联系电话格式
      if (this.taskForm.patient.phone && !/^1[3-9]\d{9}$/.test(this.taskForm.patient.phone)) {
        this.$modal.showToast('请输入正确的手机号码')
        return false
      }
      if (!this.taskForm.hospitalOut.name) {
        this.$modal.showToast('请输入转出医院名称')
        return false
@@ -725,6 +1003,11 @@
        return false
      }
      
      if (!this.taskForm.hospitalOut.department) {
        this.$modal.showToast('请选择转出科室')
        return false
      }
      if (!this.taskForm.hospitalIn.name) {
        this.$modal.showToast('请输入转入医院名称')
        return false
@@ -732,6 +1015,46 @@
      
      if (!this.taskForm.hospitalIn.address) {
        this.$modal.showToast('请选择转入医院地址')
        return false
      }
      if (!this.taskForm.hospitalIn.department) {
        this.$modal.showToast('请选择转入科室')
        return false
      }
      // 验证成交价必填
      if (!this.taskForm.price || this.taskForm.price.trim() === '') {
        this.$modal.showToast('请输入成交价')
        return false
      }
      // 验证成交价格式(必须是数字)
      if (isNaN(this.taskForm.price) || parseFloat(this.taskForm.price) < 0) {
        this.$modal.showToast('请输入有效的成交价')
        return false
      }
      // 验证患者身份证格式(如果填写了)
      if (this.taskForm.patient.idCard && this.taskForm.patient.idCard.trim() !== '') {
        const idCard = this.taskForm.patient.idCard.trim()
        // 简单验证18位身份证
        if (!/^\d{17}[\dXx]$/.test(idCard)) {
          this.$modal.showToast('请输入正确的18位身份证号码')
          return false
        }
      }
      // 验证病情至少选择一项或填写其他描述
      if ((!this.selectedDiseases || this.selectedDiseases.length === 0) &&
          (!this.taskForm.patient.otherCondition || this.taskForm.patient.otherCondition.trim() === '')) {
        this.$modal.showToast('请选择病情或填写其他病情描述')
        return false
      }
      // 验证执行人员至少选择一个
      if (!this.selectedStaff || this.selectedStaff.length === 0) {
        this.$modal.showToast('请至少选择一个执行人员')
        return false
      }
      
@@ -774,6 +1097,9 @@
        deptId: this.selectedOrganizationId,
        vehicleIds: this.selectedVehicleId ? [this.selectedVehicleId] : [],
        plannedStartTime: this.taskForm.transferTime,
        // 任务类型和单据类型
        taskTypeId: this.selectedEmergencyTaskTypeId,
        documentTypeId: this.selectedDocumentTypeId,
        
        // 出发地地址和坐标(使用转出医院地址)
        departureAddress: this.departureAddress || this.taskForm.hospitalOut.address,
@@ -854,6 +1180,9 @@
        this.loading = true
        const submitData = this.buildSubmitData()
        
        console.log('提交数据 - 转出医院科室ID:', submitData.hospitalOut.departmentId)
        console.log('提交数据 - 转入医院科室ID:', submitData.hospitalIn.departmentId)
        updateTask(submitData).then(response => {
          this.loading = false
          console.log('任务更新响应:', response)
@@ -894,7 +1223,8 @@
      
      // 调用百度地图API计算距离
      const region = this.selectedRegion || '广州'
      baiduDistanceByAddress(fromAddress, region, toAddress, region)
      //baiduDistanceByAddress(fromAddress, region, toAddress, region)
      tiandituDistanceByAddress(fromAddress,toAddress)
        .then(response => {
          uni.hideLoading()
          
@@ -1008,6 +1338,7 @@
    }
  }
}
</script>
<style lang="scss" scoped>