<template>
|
<scroll-view class="edit-emergency-task-container" scroll-y="true">
|
<view class="form-header">
|
<view class="back-btn" @click="goBack">
|
<uni-icons type="arrowleft" size="20"></uni-icons>
|
</view>
|
<view class="title">编辑转运任务</view>
|
</view>
|
|
<view class="form-section" v-if="taskDetail">
|
<!-- 使用车辆选择器组件 -->
|
<VehicleSelector
|
label="任务车辆"
|
v-model="selectedVehicleId"
|
:dept-id="currentUser.deptId"
|
vehicle-type="EMERGENCY"
|
:auto-select-bound="false"
|
@change="onVehicleChange"
|
/>
|
|
<view class="form-item">
|
<OrganizationSelector
|
v-model="selectedOrganizationId"
|
:required="true"
|
:auto-select-user-dept="false"
|
@change="onOrganizationChange"
|
/>
|
</view>
|
|
<DepartureSelector
|
:address.sync="departureAddress"
|
:longitude.sync="departureLongitude"
|
:latitude.sync="departureLatitude"
|
:region="selectedRegion"
|
:required="false"
|
@address-selected="onDepartureAddressSelected"
|
@location-success="onDepartureLocationSuccess"
|
/>
|
|
<view class="form-item">
|
<view class="form-label required">转运时间</view>
|
<uni-datetime-picker
|
v-model="taskForm.transferTime"
|
type="datetime"
|
:placeholder="'请选择转运时间'"
|
class="form-input"
|
/>
|
</view>
|
|
<StaffSelector
|
v-model="selectedStaff"
|
label="执行任务人员"
|
:required="false"
|
:auto-add-current-user="false"
|
:current-user-removable="true"
|
@change="onStaffChange"
|
/>
|
|
<view class="form-section-title">患者信息</view>
|
<view class="form-item">
|
<view class="form-label required">联系人</view>
|
<input
|
class="form-input"
|
placeholder="请输入联系人"
|
v-model="taskForm.patient.contact"
|
/>
|
</view>
|
|
<view class="form-item">
|
<view class="form-label required">联系电话</view>
|
<input
|
class="form-input"
|
type="number"
|
placeholder="请输入联系电话"
|
v-model="taskForm.patient.phone"
|
/>
|
</view>
|
|
<view class="form-item">
|
<view class="form-label required">患者姓名</view>
|
<input
|
class="form-input"
|
placeholder="请输入患者姓名"
|
v-model="taskForm.patient.name"
|
/>
|
</view>
|
|
<view class="form-item">
|
<view class="form-label">性别</view>
|
<view class="radio-group">
|
<label class="radio-item">
|
<radio value="male" :checked="taskForm.patient.gender === 'male'" @click="taskForm.patient.gender = 'male'" />
|
<text>男</text>
|
</label>
|
<label class="radio-item">
|
<radio value="female" :checked="taskForm.patient.gender === 'female'" @click="taskForm.patient.gender = 'female'" />
|
<text>女</text>
|
</label>
|
</view>
|
</view>
|
|
<view class="form-item">
|
<view class="form-label">患者身份证</view>
|
<input
|
class="form-input"
|
type="idcard"
|
placeholder="请输入患者身份证号"
|
v-model="taskForm.patient.idCard"
|
/>
|
</view>
|
|
<DiseaseSelector
|
v-model="selectedDiseases"
|
:other-description.sync="taskForm.patient.otherCondition"
|
@change="onDiseaseChange"
|
/>
|
|
<view class="form-section-title">转出医院信息</view>
|
<HospitalSelector
|
label="区院名称"
|
address-label="转出地址"
|
:required="true"
|
v-model="taskForm.hospitalOut"
|
:dept-id="selectedOrganizationId"
|
@change="onHospitalOutChange"
|
@address-selected="onHospitalOutAddressSelected"
|
/>
|
|
<view class="form-section-title">转入医院信息</view>
|
<HospitalSelector
|
label="医院名称"
|
address-label="转入地址"
|
:required="true"
|
v-model="taskForm.hospitalIn"
|
:dept-id="selectedOrganizationId"
|
@change="onHospitalInChange"
|
@address-selected="onHospitalInAddressSelected"
|
/>
|
|
<view class="form-item">
|
<view class="form-label">转运距离</view>
|
<input
|
class="form-input"
|
type="digit"
|
placeholder="自动计算"
|
v-model="taskForm.transferDistance"
|
disabled
|
/>
|
</view>
|
|
<view class="form-item">
|
<view class="form-label">成交价</view>
|
<input
|
class="form-input"
|
type="digit"
|
placeholder="请输入成交价"
|
v-model="taskForm.price"
|
/>
|
</view>
|
|
<view class="form-actions">
|
<button class="submit-btn" @click="submitTask" :disabled="loading">
|
{{ loading ? '保存中...' : '保存' }}
|
</button>
|
</view>
|
</view>
|
|
<view class="loading" v-else>
|
<uni-icons type="spinner-cycle" size="40" color="#007AFF"></uni-icons>
|
<text>加载中...</text>
|
</view>
|
|
<!-- 地图选择器弹窗 -->
|
<uni-popup ref="mapPopup" type="bottom" :mask-click="false">
|
<view class="map-popup-container">
|
<view class="popup-header">
|
<view class="popup-title">选择地址</view>
|
<view class="close-btn" @click="closeMapSelector">
|
<uni-icons type="closeempty" size="20" color="#999"></uni-icons>
|
</view>
|
</view>
|
<map-selector
|
:initial-address="getInitialAddress()"
|
@addressSelected="onAddressSelected"
|
></map-selector>
|
</view>
|
</uni-popup>
|
</scroll-view>
|
</template>
|
|
<script>
|
import { mapState } from 'vuex'
|
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 { calculateTransferPrice } from "@/api/price"
|
import MapSelector from './components/map-selector.vue'
|
import VehicleSelector from './components/VehicleSelector.vue'
|
import OrganizationSelector from './components/OrganizationSelector.vue'
|
import HospitalSelector from './components/HospitalSelector.vue'
|
import DiseaseSelector from './components/DiseaseSelector.vue'
|
import DepartureSelector from './components/DepartureSelector.vue'
|
import StaffSelector from './components/StaffSelector.vue'
|
import distanceCalculator from '@/mixins/distanceCalculator.js'
|
|
export default {
|
components: {
|
uniDatetimePicker,
|
uniPopup,
|
MapSelector,
|
VehicleSelector,
|
OrganizationSelector,
|
HospitalSelector,
|
DiseaseSelector,
|
DepartureSelector,
|
StaffSelector
|
},
|
mixins: [distanceCalculator],
|
data() {
|
return {
|
loading: false,
|
taskId: null,
|
taskDetail: null,
|
selectedVehicleId: null,
|
selectedOrganizationId: null,
|
selectedRegion: '',
|
mapSelectorType: '',
|
// 扩展 addressCoordinates 支持多种键名
|
addressCoordinates: {
|
start: null,
|
end: null,
|
hospitalOutAddress: null,
|
hospitalInAddress: null
|
},
|
// 出发地信息
|
departureAddress: '',
|
departureLongitude: null,
|
departureLatitude: null,
|
selectedDiseases: [], // 已选择的病情列表(确保初始化为空数组)
|
selectedStaff: [], // 已选择的人员列表(确保初始化为空数组)
|
taskForm: {
|
transferTime: '',
|
patient: {
|
contact: '',
|
phone: '',
|
name: '',
|
gender: 'male',
|
idCard: '',
|
condition: '',
|
otherCondition: '' // 其他病情描述
|
},
|
hospitalOut: {
|
id: null,
|
name: '',
|
department: '',
|
departmentId: null,
|
bedNumber: '',
|
address: ''
|
},
|
hospitalIn: {
|
id: null,
|
name: '',
|
department: '',
|
departmentId: null,
|
bedNumber: '',
|
address: ''
|
},
|
transferDistance: '',
|
price: ''
|
}
|
}
|
},
|
computed: {
|
...mapState({
|
currentUser: state => ({
|
name: state.user.nickName || '张三',
|
position: '司机',
|
deptId: state.user.deptId || 100,
|
branchCompanyName: state.user.branchCompanyName
|
})
|
})
|
},
|
onLoad(options) {
|
if (options.id) {
|
this.taskId = options.id
|
this.loadTaskDetail()
|
} else {
|
this.$modal.showToast('任务ID不能为空')
|
setTimeout(() => {
|
uni.navigateBack()
|
}, 1500)
|
}
|
},
|
methods: {
|
// 加载任务详情
|
loadTaskDetail() {
|
if (!this.taskId) {
|
this.$modal.showToast('任务ID不能为空')
|
return
|
}
|
|
console.log('开始加载任务详情,taskId:', this.taskId)
|
|
getTask(this.taskId).then(response => {
|
console.log('任务详情API响应:', response)
|
|
this.taskDetail = response.data || response
|
|
if (!this.taskDetail) {
|
console.error('任务详情为空')
|
this.$modal.showToast('任务数据加载失败')
|
return
|
}
|
|
console.log('任务详情数据:', this.taskDetail)
|
|
// 填充表单数据 - 转运任务特有字段
|
if (this.taskDetail.emergencyInfo) {
|
const info = this.taskDetail.emergencyInfo
|
console.log('转运任务信息:', info)
|
|
// 转运时间
|
this.taskForm.transferTime = this.taskDetail.plannedStartTime || ''
|
|
// 患者信息
|
this.taskForm.patient.contact = info.patientContact || ''
|
this.taskForm.patient.phone = info.patientPhone || ''
|
this.taskForm.patient.name = info.patientName || ''
|
this.taskForm.patient.gender = info.patientGender || 'male'
|
this.taskForm.patient.idCard = info.patientIdCard || ''
|
this.taskForm.patient.condition = info.patientCondition || ''
|
|
// 解析病情信息(修复:使用与创建界面一致的逻辑)
|
this.parseDiseaseInfo(info.patientCondition, info.diseases)
|
|
// 转出医院信息
|
this.taskForm.hospitalOut.id = info.hospitalOutId || null
|
this.taskForm.hospitalOut.name = info.hospitalOutName || ''
|
this.taskForm.hospitalOut.department = info.hospitalOutDepartment || ''
|
this.taskForm.hospitalOut.bedNumber = info.hospitalOutBedNumber || ''
|
this.taskForm.hospitalOut.address = info.hospitalOutAddress || ''
|
|
// 加载转出医院GPS坐标(不显示,但保存在数据中)
|
if (info.hospitalOutLongitude && info.hospitalOutLatitude) {
|
this.addressCoordinates.hospitalOutAddress = {
|
lng: info.hospitalOutLongitude,
|
lat: info.hospitalOutLatitude
|
}
|
console.log('加载转出医院GPS坐标:', info.hospitalOutLongitude, info.hospitalOutLatitude)
|
}
|
|
// 转入医院信息
|
this.taskForm.hospitalIn.id = info.hospitalInId || null
|
this.taskForm.hospitalIn.name = info.hospitalInName || ''
|
this.taskForm.hospitalIn.department = info.hospitalInDepartment || ''
|
this.taskForm.hospitalIn.bedNumber = info.hospitalInBedNumber || ''
|
this.taskForm.hospitalIn.address = info.hospitalInAddress || ''
|
|
// 加载转入医院GPS坐标(不显示,但保存在数据中)
|
if (info.hospitalInLongitude && info.hospitalInLatitude) {
|
this.addressCoordinates.hospitalInAddress = {
|
lng: info.hospitalInLongitude,
|
lat: info.hospitalInLatitude
|
}
|
console.log('加载转入医院GPS坐标:', info.hospitalInLongitude, info.hospitalInLatitude)
|
}
|
|
// 转运距离和价格
|
this.taskForm.transferDistance = info.transferDistance ? String(info.transferDistance) : ''
|
this.taskForm.price = info.transferPrice ? String(info.transferPrice) : ''
|
} else {
|
console.warn('任务详情中没有emergencyInfo字段,尝试从主对象获取数据')
|
// 兼容处理:如果emergencyInfo不存在,尝试从主对象获取
|
this.taskForm.transferTime = this.taskDetail.plannedStartTime || ''
|
this.taskForm.transferDistance = this.taskDetail.estimatedDistance ? String(this.taskDetail.estimatedDistance) : ''
|
}
|
|
|
// 设置车辆信息
|
if (this.taskDetail.assignedVehicles && this.taskDetail.assignedVehicles.length > 0) {
|
const firstVehicle = this.taskDetail.assignedVehicles[0]
|
this.selectedVehicleId = firstVehicle.vehicleId
|
console.log('设置车辆ID:', this.selectedVehicleId)
|
} else {
|
console.warn('任务没有分配车辆')
|
}
|
|
// 设置归属机构
|
if (this.taskDetail.deptId) {
|
this.selectedOrganizationId = this.taskDetail.deptId
|
console.log('设置归属机构ID:', this.selectedOrganizationId)
|
} else {
|
console.warn('未找到归属机构信息')
|
}
|
|
// 设置出发地信息(地址和坐标)
|
if (this.taskDetail.departureAddress) {
|
this.departureAddress = this.taskDetail.departureAddress
|
}
|
if (this.taskDetail.departureLongitude && this.taskDetail.departureLatitude) {
|
this.departureLongitude = this.taskDetail.departureLongitude
|
this.departureLatitude = this.taskDetail.departureLatitude
|
console.log('设置出发地坐标:', this.departureLongitude, this.departureLatitude)
|
}
|
|
// 设置目标地信息(转入医院的地址和坐标)
|
if (this.taskDetail.destinationAddress) {
|
// 目标地地址已经在 taskForm.hospitalIn.address 中设置
|
console.log('目标地地址:', this.taskDetail.destinationAddress)
|
}
|
if (this.taskDetail.destinationLongitude && this.taskDetail.destinationLatitude) {
|
this.addressCoordinates.hospitalInAddress = {
|
lng: this.taskDetail.destinationLongitude,
|
lat: this.taskDetail.destinationLatitude
|
}
|
console.log('设置目标地坐标:', this.taskDetail.destinationLongitude, this.taskDetail.destinationLatitude)
|
}
|
|
// 设置执行人员(修复:确保 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: ''
|
}))
|
console.log('处理后的执行人员列表:', this.selectedStaff)
|
} else {
|
console.warn('任务没有分配执行人员或assignees为空')
|
console.log('taskDetail.assignees:', this.taskDetail.assignees)
|
// 确保 selectedStaff 初始化为空数组
|
this.selectedStaff = []
|
}
|
|
console.log('表单数据填充完成:', this.taskForm)
|
}).catch(error => {
|
console.error('加载任务详情失败:', error)
|
console.error('错误详情:', error.response || error.message || error)
|
this.$modal.showToast('加载任务详情失败: ' + (error.message || '网络错误'))
|
setTimeout(() => {
|
uni.navigateBack()
|
}, 1500)
|
})
|
},
|
|
// 车辆选择变化
|
onVehicleChange(vehicle) {
|
console.log('选中车辆:', vehicle)
|
},
|
|
// 归属机构选择变化
|
onOrganizationChange(orgData) {
|
// orgData 包含:deptId, deptName, serviceOrderClass, region, departureAddress, departureLongitude, departureLatitude
|
this.selectedOrganizationId = orgData.deptId
|
this.selectedRegion = orgData.region
|
|
// 自动填充出发地信息(机构的地址和坐标)
|
if (orgData.departureAddress) {
|
this.departureAddress = orgData.departureAddress
|
this.departureLongitude = orgData.departureLongitude || null
|
this.departureLatitude = orgData.departureLatitude || null
|
console.log('自动填充机构出发地:', this.departureAddress, '坐标:', this.departureLongitude, this.departureLatitude)
|
}
|
|
console.log('选中归属机构:', orgData.deptName, '部门ID:', orgData.deptId, '地域:', orgData.region)
|
},
|
|
// 出发地地址选择(从地图建议中选择)
|
onDepartureAddressSelected(data) {
|
// data 包含: address, longitude, latitude, location
|
console.log('出发地地址选择:', data)
|
// 组件已经通过 .sync 更新了 departureAddress, departureLongitude, departureLatitude
|
},
|
|
// 出发地GPS定位成功
|
onDepartureLocationSuccess(data) {
|
// data 包含: address, longitude, latitude
|
console.log('出发地GPS定位成功:', data)
|
// 组件已经通过 .sync 更新了 departureAddress, departureLongitude, departureLatitude
|
},
|
|
// 转出医院变化
|
onHospitalOutChange(hospitalData) {
|
console.log('转出医院变化:', hospitalData)
|
// 组件已经通过 v-model 更新了 taskForm.hospitalOut
|
|
// 如果转入地址已填写,自动计算距离
|
if (this.taskForm.hospitalIn.address) {
|
// 如果两个都不是"家中",使用医院距离计算
|
if (hospitalData.name !== '家中' && this.taskForm.hospitalIn.name !== '家中') {
|
this.calculateHospitalDistance()
|
} else {
|
// 有一个是"家中",使用地址计算
|
this.calculateDistanceByManualAddress()
|
}
|
}
|
},
|
|
// 转出医院地址选择事件(简化)
|
onHospitalOutAddressSelected(data) {
|
if (this.taskForm.hospitalIn.address) {
|
this.calculateDistanceByManualAddress()
|
}
|
},
|
|
// 转入医院变化
|
onHospitalInChange(hospitalData) {
|
console.log('转入医院变化:', hospitalData)
|
// 组件已经通过 v-model 更新了 taskForm.hospitalIn
|
|
// 如果转出地址已填写,自动计算距离
|
if (this.taskForm.hospitalOut.address) {
|
// 如果两个都不是"家中",使用医院距离计算
|
if (hospitalData.name !== '家中' && this.taskForm.hospitalOut.name !== '家中') {
|
this.calculateHospitalDistance()
|
} else {
|
// 有一个是"家中",使用地址计算
|
this.calculateDistanceByManualAddress()
|
}
|
}
|
},
|
|
// 转入医院地址选择事件(简化)
|
onHospitalInAddressSelected(data) {
|
if (this.taskForm.hospitalOut.address) {
|
this.calculateDistanceByManualAddress()
|
}
|
},
|
|
// 病情变化
|
onDiseaseChange(diseases) {
|
console.log('病情变化:', diseases)
|
// 组件已经通过 v-model 更新了 selectedDiseases
|
},
|
|
// 人员变化
|
onStaffChange(staff) {
|
console.log('选中人员变化:', staff)
|
// 组件已经通过 v-model 更新了 selectedStaff
|
},
|
|
// 解析病情信息(从字符串解析出ICD-10疾病列表)- 修复:与创建界面保持一致
|
parseDiseaseInfo(conditionText, diseases) {
|
console.log('========== 开始解析病情信息 ==========')
|
console.log('conditionText:', conditionText)
|
console.log('diseases数组:', diseases)
|
|
if (!conditionText) {
|
console.log('病情文本为空,清空选中病情')
|
this.selectedDiseases = []
|
this.taskForm.patient.otherCondition = ''
|
return
|
}
|
|
// 如果包含"其他:"分隔符,拆分病情和其他描述
|
if (conditionText.includes('\n其他:')) {
|
const parts = conditionText.split('\n其他:')
|
const diseasePart = parts[0]
|
this.taskForm.patient.otherCondition = parts[1] || ''
|
console.log('病情部分:', diseasePart)
|
console.log('其他描述:', this.taskForm.patient.otherCondition)
|
|
// 解析病情部分
|
this.parseDiseaseList(diseasePart, diseases)
|
} else {
|
// 没有"其他"部分,尝试解析是否有疾病列表
|
const hasDiseasesFormat = /([^(]+)\(([^)]+)\)/.test(conditionText)
|
console.log('是否包含疾病格式:', hasDiseasesFormat)
|
|
if (hasDiseasesFormat) {
|
// 有疾病格式,解析疾病列表
|
this.parseDiseaseList(conditionText, diseases)
|
this.taskForm.patient.otherCondition = ''
|
} else {
|
// 没有疾病格式,全部作为其他描述
|
console.log('无疾病格式,作为其他描述')
|
this.taskForm.patient.otherCondition = conditionText
|
this.selectedDiseases = []
|
}
|
}
|
|
console.log('解析完成,selectedDiseases:', JSON.stringify(this.selectedDiseases))
|
console.log('解析完成,otherCondition:', this.taskForm.patient.otherCondition)
|
console.log('========================================\n')
|
},
|
|
// 解析病情列表(格式:疾病名(编码)、疾病名(编码))
|
parseDiseaseList(diseasePart, diseasesData) {
|
console.log('--- parseDiseaseList 开始 ---')
|
console.log('diseasePart:', diseasePart)
|
console.log('diseasesData:', diseasesData)
|
|
if (!diseasePart) {
|
console.log('病情部分为空')
|
this.selectedDiseases = []
|
return
|
}
|
|
// 如果后端已经返回了diseases数组,直接使用
|
if (diseasesData && Array.isArray(diseasesData) && diseasesData.length > 0) {
|
console.log('使用后端返回的diseases数组,数量:', diseasesData.length)
|
this.selectedDiseases = diseasesData.map(d => ({
|
id: d.icdId || null,
|
icdCode: d.icdCode || '',
|
icdName: d.icdName || ''
|
}))
|
console.log('解析后的selectedDiseases:', JSON.stringify(this.selectedDiseases))
|
return
|
}
|
|
// 否则,从字符串解析
|
console.log('从字符串解析病情')
|
// 匹配格式:疾病名(编码)
|
const regex = /([^(]+)\(([^)]+)\)/g
|
const diseases = []
|
let match
|
|
while ((match = regex.exec(diseasePart)) !== null) {
|
const icdName = match[1].replace(/[、,\s]+$/, '').replace(/^[、,\s]+/, '').trim()
|
const icdCode = match[2].trim()
|
|
console.log('匹配到病情 - 名称:', icdName, '编码:', icdCode)
|
|
// 只添加病情名称不为空的项
|
if (icdName) {
|
diseases.push({
|
id: null, // 从字符串解析时,没有ID
|
icdCode: icdCode,
|
icdName: icdName
|
})
|
}
|
}
|
|
console.log('从字符串解析完成,数量:', diseases.length)
|
this.selectedDiseases = diseases
|
console.log('--- parseDiseaseList 结束 ---\n')
|
},
|
|
// 选择转出医院地址
|
selectHospitalOutAddress() {
|
this.mapSelectorType = 'hospitalOut'
|
this.$refs.mapPopup.open()
|
},
|
|
// 选择转入医院地址
|
selectHospitalInAddress() {
|
this.mapSelectorType = 'hospitalIn'
|
this.$refs.mapPopup.open()
|
},
|
|
getInitialAddress() {
|
if (this.mapSelectorType === 'hospitalOut') {
|
return this.taskForm.hospitalOut.address
|
} else if (this.mapSelectorType === 'hospitalIn') {
|
return this.taskForm.hospitalIn.address
|
}
|
return ''
|
},
|
|
onAddressSelected(address) {
|
const formattedAddress = address.title + ' - ' + address.address
|
|
if (this.mapSelectorType === 'hospitalOut') {
|
this.taskForm.hospitalOut.address = formattedAddress
|
this.setLocationByAddress('start', address)
|
} else if (this.mapSelectorType === 'hospitalIn') {
|
this.taskForm.hospitalIn.address = formattedAddress
|
this.setLocationByAddress('end', address)
|
}
|
|
// 监听mixin中的距离计算完成事件
|
this.$once('distance-calculated', (distance) => {
|
this.taskForm.transferDistance = this.formatDistance(distance)
|
})
|
|
this.closeMapSelector()
|
},
|
|
closeMapSelector() {
|
this.$refs.mapPopup.close()
|
this.mapSelectorType = ''
|
},
|
|
validateForm() {
|
if (!this.selectedVehicleId) {
|
this.$modal.showToast('请选择任务车辆')
|
return false
|
}
|
|
if (!this.selectedOrganizationId) {
|
this.$modal.showToast('请选择归属机构')
|
return false
|
}
|
|
if (!this.taskForm.transferTime) {
|
this.$modal.showToast('请选择转运时间')
|
return false
|
}
|
|
if (!this.taskForm.patient.contact) {
|
this.$modal.showToast('请输入联系人')
|
return false
|
}
|
|
if (!this.taskForm.patient.phone) {
|
this.$modal.showToast('请输入联系电话')
|
return false
|
}
|
|
if (!this.taskForm.patient.name) {
|
this.$modal.showToast('请输入患者姓名')
|
return false
|
}
|
|
if (!this.taskForm.hospitalOut.name) {
|
this.$modal.showToast('请输入转出医院名称')
|
return false
|
}
|
|
if (!this.taskForm.hospitalOut.address) {
|
this.$modal.showToast('请选择转出医院地址')
|
return false
|
}
|
|
if (!this.taskForm.hospitalIn.name) {
|
this.$modal.showToast('请输入转入医院名称')
|
return false
|
}
|
|
if (!this.taskForm.hospitalIn.address) {
|
this.$modal.showToast('请选择转入医院地址')
|
return false
|
}
|
|
return true
|
},
|
|
buildSubmitData() {
|
// 确保 selectedDiseases 和 selectedStaff 不为 null(修复:防止迭代 null 导致错误)
|
if (!this.selectedDiseases) {
|
this.selectedDiseases = []
|
}
|
if (!this.selectedStaff) {
|
this.selectedStaff = []
|
}
|
|
// 合并病情信息:选中的ICD-10疾病 + 其他描述
|
let conditionText = ''
|
if (this.selectedDiseases.length > 0) {
|
// 过滤掉病情名称为空的项,并构建病情字符串
|
const diseaseNames = this.selectedDiseases
|
.filter(d => d.icdName && d.icdName.trim())
|
.map(d => `${d.icdName}(${d.icdCode})`)
|
.join('、')
|
if (diseaseNames) {
|
conditionText = diseaseNames
|
}
|
}
|
if (this.taskForm.patient.otherCondition && this.taskForm.patient.otherCondition.trim()) {
|
if (conditionText) {
|
conditionText += '\n其他:' + this.taskForm.patient.otherCondition
|
} else {
|
conditionText = this.taskForm.patient.otherCondition
|
}
|
}
|
|
// 构建提交数据 - 使用与 TaskCreateVO 一致的结构
|
const submitData = {
|
taskId: this.taskId,
|
taskType: 'EMERGENCY_TRANSFER',
|
deptId: this.selectedOrganizationId,
|
vehicleIds: this.selectedVehicleId ? [this.selectedVehicleId] : [],
|
plannedStartTime: this.taskForm.transferTime,
|
|
// 出发地地址和坐标(使用转出医院地址)
|
departureAddress: this.departureAddress || this.taskForm.hospitalOut.address,
|
departureLongitude: this.departureLongitude || (this.addressCoordinates.hospitalOutAddress ? this.addressCoordinates.hospitalOutAddress.lng : null),
|
departureLatitude: this.departureLatitude || (this.addressCoordinates.hospitalOutAddress ? this.addressCoordinates.hospitalOutAddress.lat : null),
|
|
// 目标地地址和坐标(使用转入医院地址)
|
destinationAddress: this.taskForm.hospitalIn.address,
|
destinationLongitude: this.addressCoordinates.hospitalInAddress ? this.addressCoordinates.hospitalInAddress.lng : null,
|
destinationLatitude: this.addressCoordinates.hospitalInAddress ? this.addressCoordinates.hospitalInAddress.lat : null,
|
|
// 转运距离和价格(主任务字段)
|
distance: this.taskForm.transferDistance ? parseFloat(this.taskForm.transferDistance) : null,
|
price: this.taskForm.price ? parseFloat(this.taskForm.price) : null,
|
|
// 病情ID列表(用于同步调度单的OrdICD_ID参数)
|
diseaseIds: this.selectedDiseases.map(d => d.id).filter(id => id !== null),
|
|
// 执行人员列表(确保不为 null)
|
assignees: (this.selectedStaff && Array.isArray(this.selectedStaff)) ? this.selectedStaff.map(staff => ({
|
userId: staff.userId,
|
userName: staff.nickName,
|
userType: staff.type
|
})) : [],
|
|
// 患者信息(嵌套对象)
|
patient: {
|
contact: this.taskForm.patient.contact,
|
phone: this.taskForm.patient.phone,
|
name: this.taskForm.patient.name,
|
gender: this.taskForm.patient.gender,
|
idCard: this.taskForm.patient.idCard,
|
condition: conditionText, // 使用合并后的病情信息
|
// 病情详细信息(过滤掉空的病情名称)
|
diseases: this.selectedDiseases
|
.filter(d => d.icdName && d.icdName.trim())
|
.map(d => ({
|
icdId: d.id,
|
icdCode: d.icdCode,
|
icdName: d.icdName
|
}))
|
},
|
|
// 转出医院信息(嵌套对象)
|
hospitalOut: {
|
id: this.taskForm.hospitalOut.id,
|
name: this.taskForm.hospitalOut.name,
|
address: this.taskForm.hospitalOut.address,
|
longitude: this.addressCoordinates.hospitalOutAddress ? this.addressCoordinates.hospitalOutAddress.lng : null,
|
latitude: this.addressCoordinates.hospitalOutAddress ? this.addressCoordinates.hospitalOutAddress.lat : null,
|
department: this.taskForm.hospitalOut.department,
|
departmentId: this.taskForm.hospitalOut.departmentId,
|
bedNumber: this.taskForm.hospitalOut.bedNumber
|
},
|
|
// 转入医院信息(嵌套对象)
|
hospitalIn: {
|
id: this.taskForm.hospitalIn.id,
|
name: this.taskForm.hospitalIn.name,
|
address: this.taskForm.hospitalIn.address,
|
longitude: this.addressCoordinates.hospitalInAddress ? this.addressCoordinates.hospitalInAddress.lng : null,
|
latitude: this.addressCoordinates.hospitalInAddress ? this.addressCoordinates.hospitalInAddress.lat : null,
|
department: this.taskForm.hospitalIn.department,
|
departmentId: this.taskForm.hospitalIn.departmentId,
|
bedNumber: this.taskForm.hospitalIn.bedNumber
|
}
|
}
|
|
return submitData
|
},
|
|
submitTask() {
|
if (!this.validateForm()) {
|
return
|
}
|
|
this.$modal.confirm('确定要保存修改吗?').then(() => {
|
this.loading = true
|
const submitData = this.buildSubmitData()
|
|
updateTask(submitData).then(response => {
|
this.loading = false
|
console.log('任务更新响应:', response)
|
this.$modal.showToast('任务更新成功')
|
setTimeout(() => {
|
uni.navigateBack()
|
}, 1500)
|
}).catch(error => {
|
this.loading = false
|
console.error('任务更新失败:', error)
|
console.error('错误详情:', error.response || error.message || error)
|
const errorMsg = error.response?.data?.msg || error.message || '请重试'
|
this.$modal.showToast('任务更新失败: ' + errorMsg)
|
})
|
}).catch(() => {})
|
},
|
|
goBack() {
|
uni.navigateBack()
|
},
|
|
// 自动计算两个医院之间的距离
|
calculateHospitalDistance() {
|
const fromAddress = this.taskForm.hospitalOut.address
|
const toAddress = this.taskForm.hospitalIn.address
|
|
if (!fromAddress || !toAddress) {
|
console.log('地址信息不完整,无法计算距离')
|
return
|
}
|
|
console.log('开始计算距离:', fromAddress, '->', toAddress)
|
|
// 显示加载提示
|
uni.showLoading({
|
title: '计算距离中...'
|
})
|
|
// 调用百度地图API计算距离
|
const region = this.selectedRegion || '广州'
|
baiduDistanceByAddress(fromAddress, region, toAddress, region)
|
.then(response => {
|
uni.hideLoading()
|
|
if (response.code === 200 && response.data) {
|
const distanceInMeters = response.data.distance
|
// 转换为公里,保留1位小数
|
const distanceInKm = (distanceInMeters / 1000).toFixed(1)
|
this.taskForm.transferDistance = distanceInKm
|
|
console.log('距离计算成功:', distanceInKm, 'km')
|
this.$modal.showToast(`距离: ${distanceInKm}公里`)
|
|
// 距离计算成功后,自动计算成交价
|
this.calculatePrice()
|
} else {
|
console.error('距离计算失败:', response.msg)
|
this.$modal.showToast('距离计算失败,请手动输入')
|
}
|
})
|
.catch(error => {
|
uni.hideLoading()
|
console.error('距离计算失败:', error)
|
this.$modal.showToast('距离计算失败,请手动输入')
|
})
|
},
|
|
// 手动输入地址时计算距离
|
calculateDistanceByManualAddress() {
|
const fromAddress = this.taskForm.hospitalOut.address
|
const toAddress = this.taskForm.hospitalIn.address
|
|
if (!fromAddress || !toAddress) {
|
return
|
}
|
|
console.log('计算手动输入地址距离:', fromAddress, '->', toAddress)
|
|
// 显示加载提示
|
uni.showLoading({
|
title: '计算距离中...'
|
})
|
|
// 调用百度地图API计算距离
|
const region = this.selectedRegion || '广州'
|
baiduDistanceByAddress(fromAddress, region, toAddress, region)
|
.then(response => {
|
uni.hideLoading()
|
|
if (response.code === 200 && response.data) {
|
const distanceInMeters = response.data.distance
|
// 转换为公里,保留1位小数
|
const distanceInKm = (distanceInMeters / 1000).toFixed(1)
|
this.taskForm.transferDistance = distanceInKm
|
|
console.log('距离计算成功:', distanceInKm, 'km')
|
this.$modal.showToast(`距离: ${distanceInKm}公里`)
|
|
// 距离计算成功后,自动计算成交价
|
this.calculatePrice()
|
} else {
|
console.error('距离计算失败:', response.msg)
|
this.$modal.showToast('距离计算失败,请手动输入')
|
}
|
})
|
.catch(error => {
|
uni.hideLoading()
|
console.error('距离计算失败:', error)
|
this.$modal.showToast('距离计算失败,请手动输入')
|
})
|
},
|
|
// 计算成交价
|
calculatePrice() {
|
const fromAddress = this.taskForm.hospitalOut.address
|
const toAddress = this.taskForm.hospitalIn.address
|
const distance = this.taskForm.transferDistance
|
|
// 如果地址或距离不完整,不进行计算
|
if (!fromAddress || !toAddress || !distance || parseFloat(distance) <= 0) {
|
console.log('地址或距离信息不完整,跳过成交价计算')
|
return
|
}
|
|
console.log('开始计算成交价:', fromAddress, '->', toAddress, '距离:', distance)
|
|
// 调用成交价计算接口
|
calculateTransferPrice({
|
fromAddress: fromAddress,
|
toAddress: toAddress,
|
distance: parseFloat(distance),
|
region: this.selectedRegion || ''
|
}).then(response => {
|
if (response.code === 200 && response.data) {
|
const price = response.data.price
|
|
// 只有当返回的价格大于0时,才自动填充成交价
|
if (price && price > 0) {
|
this.taskForm.price = price.toFixed(2)
|
console.log('成交价计算成功:', price)
|
this.$modal.showToast(`成交价: ¥${price.toFixed(2)}`)
|
} else {
|
console.log('成交价为0,不自动填充')
|
}
|
} else {
|
console.log('成交价计算失败,保持手动输入')
|
}
|
}).catch(error => {
|
console.error('成交价计算失败:', error)
|
// 计算失败时不提示用户,允许用户手动输入
|
})
|
}
|
}
|
}
|
</script>
|
|
<style lang="scss" scoped>
|
.edit-emergency-task-container {
|
padding: 20rpx;
|
background-color: #f5f5f5;
|
min-height: 100vh;
|
|
.form-header {
|
display: flex;
|
align-items: center;
|
padding: 20rpx 0;
|
margin-bottom: 30rpx;
|
|
.back-btn {
|
width: 60rpx;
|
height: 60rpx;
|
border-radius: 50%;
|
background-color: #f0f0f0;
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
margin-right: 20rpx;
|
}
|
|
.title {
|
font-size: 36rpx;
|
font-weight: bold;
|
color: #333;
|
}
|
}
|
|
.form-section {
|
background-color: white;
|
border-radius: 15rpx;
|
padding: 30rpx;
|
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05);
|
|
.form-section-title {
|
font-size: 32rpx;
|
font-weight: bold;
|
margin: 40rpx 0 20rpx 0;
|
padding-bottom: 10rpx;
|
border-bottom: 1rpx solid #f0f0f0;
|
}
|
|
.form-item {
|
margin-bottom: 40rpx;
|
|
.form-label {
|
font-size: 28rpx;
|
margin-bottom: 15rpx;
|
color: #333;
|
|
&.required::before {
|
content: '*';
|
color: #ff3b30;
|
margin-right: 4rpx;
|
}
|
}
|
|
.form-input {
|
height: 70rpx;
|
padding: 0 20rpx;
|
border: 1rpx solid #eee;
|
border-radius: 10rpx;
|
font-size: 28rpx;
|
|
&.picker-input {
|
display: flex;
|
align-items: center;
|
justify-content: space-between;
|
}
|
|
&[disabled] {
|
background-color: #f5f5f5;
|
color: #999;
|
}
|
}
|
|
.form-textarea {
|
width: 100%;
|
min-height: 150rpx;
|
padding: 20rpx;
|
border: 1rpx solid #eee;
|
border-radius: 10rpx;
|
font-size: 28rpx;
|
}
|
|
.radio-group {
|
display: flex;
|
gap: 40rpx;
|
|
.radio-item {
|
display: flex;
|
align-items: center;
|
gap: 10rpx;
|
font-size: 28rpx;
|
color: #333;
|
}
|
}
|
|
.staff-list {
|
.staff-item {
|
display: flex;
|
justify-content: space-between;
|
align-items: center;
|
padding: 20rpx;
|
margin-bottom: 15rpx;
|
background-color: #f8f8f8;
|
border-radius: 10rpx;
|
|
.staff-info {
|
display: flex;
|
align-items: center;
|
gap: 10rpx;
|
|
.staff-name {
|
font-size: 28rpx;
|
color: #333;
|
}
|
|
.staff-role {
|
font-size: 24rpx;
|
color: #999;
|
}
|
}
|
}
|
|
.add-staff {
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
gap: 10rpx;
|
padding: 20rpx;
|
border: 2rpx dashed #007AFF;
|
border-radius: 10rpx;
|
color: #007AFF;
|
font-size: 28rpx;
|
cursor: pointer;
|
|
&:active {
|
background-color: #f0f8ff;
|
}
|
}
|
}
|
}
|
|
.form-actions {
|
margin-top: 50rpx;
|
text-align: center;
|
|
.submit-btn {
|
width: 80%;
|
height: 80rpx;
|
background-color: #007AFF;
|
color: white;
|
border-radius: 10rpx;
|
font-size: 32rpx;
|
|
&[disabled] {
|
background-color: #ccc;
|
color: #999;
|
}
|
}
|
}
|
}
|
|
.loading {
|
display: flex;
|
flex-direction: column;
|
align-items: center;
|
justify-content: center;
|
height: 400rpx;
|
color: #999;
|
|
text {
|
margin-top: 20rpx;
|
font-size: 28rpx;
|
}
|
}
|
|
.map-popup-container {
|
height: 80vh;
|
background-color: white;
|
border-top-left-radius: 20rpx;
|
border-top-right-radius: 20rpx;
|
overflow: hidden;
|
|
.popup-header {
|
display: flex;
|
justify-content: space-between;
|
align-items: center;
|
padding: 20rpx 30rpx;
|
border-bottom: 1rpx solid #f0f0f0;
|
|
.popup-title {
|
font-size: 32rpx;
|
font-weight: bold;
|
color: #333;
|
}
|
|
.close-btn {
|
width: 50rpx;
|
height: 50rpx;
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
}
|
}
|
}
|
}
|
</style>
|