| | |
| | | /> |
| | | |
| | | <view class="form-item"> |
| | | <OrganizationSelector |
| | | <OrganizationSelector |
| | | ref="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> |
| | |
| | | /> |
| | | </view> |
| | | |
| | | <view class="form-item"> |
| | | <view class="form-label">执行任务人员</view> |
| | | <view class="staff-list"> |
| | | <view class="staff-item" v-for="(staff, index) in selectedStaff" :key="staff.userId"> |
| | | <view class="staff-info"> |
| | | <text class="staff-name">{{ staff.nickName }}</text> |
| | | <text class="staff-role">({{ getUserTypeName(staff.type) || '未知职位' }})</text> |
| | | </view> |
| | | <uni-icons |
| | | type="closeempty" |
| | | size="20" |
| | | color="#ff4d4f" |
| | | @click="removeStaff(index)" |
| | | ></uni-icons> |
| | | </view> |
| | | <view class="add-staff" @click="showStaffSelector"> |
| | | <uni-icons type="plusempty" size="20" color="#007AFF"></uni-icons> |
| | | <text>添加人员</text> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | <StaffSelector |
| | | v-model="selectedStaff" |
| | | label="执行任务人员" |
| | | :required="false" |
| | | :auto-add-current-user="false" |
| | | :current-user-removable="true" |
| | | :branch-dept-ids="allOrganizationIds" |
| | | @change="onStaffChange" |
| | | /> |
| | | |
| | | <view class="form-section-title">患者信息</view> |
| | | <view class="form-item"> |
| | |
| | | |
| | | <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> |
| | |
| | | ></map-selector> |
| | | </view> |
| | | </uni-popup> |
| | | |
| | | <!-- 人员选择器弹窗 --> |
| | | <uni-popup ref="staffPopup" type="bottom" :mask-click="false"> |
| | | <view class="staff-popup-container"> |
| | | <view class="popup-header"> |
| | | <view class="popup-title">选择执行人员</view> |
| | | <view class="close-btn" @click="closeStaffSelector"> |
| | | <uni-icons type="closeempty" size="20" color="#999"></uni-icons> |
| | | </view> |
| | | </view> |
| | | |
| | | <view class="search-bar"> |
| | | <input |
| | | class="search-input" |
| | | placeholder="搜索姓名或电话" |
| | | v-model="staffSearchKeyword" |
| | | @input="onStaffSearch" |
| | | /> |
| | | </view> |
| | | |
| | | <view class="filter-tabs"> |
| | | <view |
| | | class="filter-tab" |
| | | :class="{ active: staffFilterType === 'driver' }" |
| | | @click="filterStaff('driver')" |
| | | > |
| | | 司机 |
| | | </view> |
| | | <view |
| | | class="filter-tab" |
| | | :class="{ active: staffFilterType === 'doctor' }" |
| | | @click="filterStaff('doctor')" |
| | | > |
| | | 医生 |
| | | </view> |
| | | <view |
| | | class="filter-tab" |
| | | :class="{ active: staffFilterType === 'nurse' }" |
| | | @click="filterStaff('nurse')" |
| | | > |
| | | 护士 |
| | | </view> |
| | | </view> |
| | | |
| | | <scroll-view class="staff-list-scroll" scroll-y="true"> |
| | | <view |
| | | class="staff-list-item" |
| | | v-for="staff in filteredStaffList" |
| | | :key="staff.userId" |
| | | @click="toggleStaffSelection(staff)" |
| | | > |
| | | <view class="staff-item-info"> |
| | | <text class="staff-item-name">{{ staff.nickName }}</text> |
| | | <text class="staff-item-dept">{{ staff.deptName }}</text> |
| | | </view> |
| | | <view class="staff-item-check"> |
| | | <uni-icons |
| | | v-if="isStaffSelected(staff.userId)" |
| | | type="checkmarkempty" |
| | | size="24" |
| | | color="#007AFF" |
| | | ></uni-icons> |
| | | </view> |
| | | </view> |
| | | <view v-if="filteredStaffList.length === 0" class="empty-tip"> |
| | | 暂无人员数据 |
| | | </view> |
| | | </scroll-view> |
| | | |
| | | <view class="popup-footer"> |
| | | <button class="confirm-btn" @click="confirmStaffSelection">确定(已选{{ selectedStaff.length }})</button> |
| | | </view> |
| | | </view> |
| | | </uni-popup> |
| | | </scroll-view> |
| | | </template> |
| | | |
| | |
| | | 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 { listBranchUsers } from "@/api/system/user" |
| | | import { baiduDistanceByAddress } from "@/api/map" |
| | | import { calculateTransferPrice } from "@/api/price" |
| | | import MapSelector from './components/map-selector.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 DepartmentSelector from './components/DepartmentSelector.vue' |
| | | import distanceCalculator from '@/mixins/distanceCalculator.js' |
| | | |
| | | export default { |
| | |
| | | VehicleSelector, |
| | | OrganizationSelector, |
| | | HospitalSelector, |
| | | DiseaseSelector |
| | | DiseaseSelector, |
| | | DepartureSelector, |
| | | StaffSelector, |
| | | DepartmentSelector |
| | | }, |
| | | mixins: [distanceCalculator], |
| | | data() { |
| | |
| | | taskDetail: null, |
| | | selectedVehicleId: null, |
| | | selectedOrganizationId: null, |
| | | allOrganizationIds: [], // 所有可选机构ID数组 |
| | | selectedRegion: '', |
| | | mapSelectorType: '', |
| | | // 扩展 addressCoordinates 支持多种键名 |
| | | addressCoordinates: { |
| | | start: null, |
| | | end: null, |
| | | hospitalOutAddress: null, |
| | | hospitalInAddress: null |
| | | }, |
| | | // 出发地信息 |
| | | departureAddress: '', |
| | | departureLongitude: null, |
| | | departureLatitude: null, |
| | | selectedDiseases: [], // 已选择的病情列表 |
| | | selectedStaff: [], // 已选择的人员列表 |
| | | allStaffList: [], // 所有人员列表 |
| | | filteredStaffList: [], // 过滤后的人员列表 |
| | | staffSearchKeyword: '', // 人员搜索关键词 |
| | | staffFilterType: 'driver', // 人员筛选类型 |
| | | selectedDiseases: [], // 已选择的病情列表(确保初始化为空数组) |
| | | selectedStaff: [], // 已选择的人员列表(确保初始化为空数组) |
| | | taskForm: { |
| | | transferTime: '', |
| | | patient: { |
| | |
| | | if (options.id) { |
| | | this.taskId = options.id |
| | | this.loadTaskDetail() |
| | | this.loadDeptStaff() // 加载人员列表 |
| | | } else { |
| | | this.$modal.showToast('任务ID不能为空') |
| | | setTimeout(() => { |
| | | uni.navigateBack() |
| | | }, 1500) |
| | | } |
| | | }, |
| | | |
| | | mounted() { |
| | | // 页面挂载后加载所有机构ID |
| | | this.loadAllOrganizationIds() |
| | | }, |
| | | methods: { |
| | | // 加载任务详情 |
| | |
| | | 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 || '' |
| | |
| | | this.taskForm.patient.idCard = info.patientIdCard || '' |
| | | this.taskForm.patient.condition = info.patientCondition || '' |
| | | |
| | | // 解析病情信息 |
| | | this.parseDiseaseInfo(info.patientCondition, info.diseaseIds) |
| | | // 解析病情信息(修复:使用与创建界面一致的逻辑) |
| | | 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.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) { |
| | |
| | | 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) { |
| | |
| | | } 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) : '' |
| | | } |
| | | |
| | |
| | | console.log('设置目标地坐标:', this.taskDetail.destinationLongitude, this.taskDetail.destinationLatitude) |
| | | } |
| | | |
| | | // 设置执行人员 |
| | | if (this.taskDetail.assignees && this.taskDetail.assignees.length > 0) { |
| | | // 设置执行人员(修复:确保 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为空') |
| | | console.log('taskDetail.assignees:', this.taskDetail.assignees) |
| | | // 确保 selectedStaff 初始化为空数组 |
| | | this.selectedStaff = [] |
| | | } |
| | | |
| | | console.log('表单数据填充完成:', this.taskForm) |
| | |
| | | console.log('选中车辆:', vehicle) |
| | | }, |
| | | |
| | | // 加载所有机构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) |
| | | } |
| | | }, |
| | | |
| | | // 归属机构选择变化 |
| | | onOrganizationChange(orgData) { |
| | | // orgData 包含:deptId, deptName, serviceOrderClass, region |
| | | // orgData 包含:deptId, deptName, serviceOrderClass, region, departureAddress, departureLongitude, departureLatitude |
| | | this.selectedOrganizationId = orgData.deptId |
| | | console.log('选中归属机构:', orgData.deptName, '部门ID:', 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 (hospitalData.name === '家中') { |
| | | this.taskForm.hospitalOut.department = '其它' |
| | | this.taskForm.hospitalOut.departmentId = null |
| | | } |
| | | |
| | | // 如果转入地址已填写,自动计算距离 |
| | | if (this.taskForm.hospitalIn.address) { |
| | |
| | | console.log('转入医院变化:', hospitalData) |
| | | // 组件已经通过 v-model 更新了 taskForm.hospitalIn |
| | | |
| | | // 如果选择的是"家中",自动设置科室为"其它" |
| | | if (hospitalData.name === '家中') { |
| | | this.taskForm.hospitalIn.department = '其它' |
| | | this.taskForm.hospitalIn.departmentId = null |
| | | } |
| | | |
| | | // 如果转出地址已填写,自动计算距离 |
| | | if (this.taskForm.hospitalOut.address) { |
| | | // 如果两个都不是"家中",使用医院距离计算 |
| | |
| | | } |
| | | }, |
| | | |
| | | // 转出科室变化 |
| | | onHospitalOutDepartmentChange(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) { |
| | | 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 |
| | | } |
| | | }, |
| | | |
| | | // 病情变化 |
| | | onDiseaseChange(diseases) { |
| | | console.log('病情变化:', diseases) |
| | | // 组件已经通过 v-model 更新了 selectedDiseases |
| | | }, |
| | | |
| | | // 加载当前用户所在分公司的所有人员 |
| | | loadDeptStaff() { |
| | | console.log('开始加载人员列表') |
| | | // 人员变化 |
| | | onStaffChange(staff) { |
| | | console.log('选中人员变化:', staff) |
| | | // 组件已经通过 v-model 更新了 selectedStaff |
| | | }, |
| | | |
| | | // 解析病情信息(从字符串解析出ICD-10疾病列表)- 修复:与创建界面保持一致 |
| | | parseDiseaseInfo(conditionText, diseases) { |
| | | console.log('========== 开始解析病情信息 ==========') |
| | | console.log('conditionText:', conditionText) |
| | | console.log('diseases数组:', diseases) |
| | | |
| | | listBranchUsers().then(response => { |
| | | console.log('人员列表API响应:', response) |
| | | const userList = response.data || [] |
| | | console.log('解析出的用户列表:', userList, '数量:', userList.length) |
| | | |
| | | this.allStaffList = userList.map(user => ({ |
| | | userId: user.userId, |
| | | nickName: user.nickName, |
| | | phonenumber: user.phonenumber, |
| | | deptName: user.dept?.deptName || '', |
| | | postName: user.posts && user.posts.length > 0 ? user.posts[0].postName : '', |
| | | roleName: user.roles && user.roles.length > 0 ? user.roles[0].roleName : '', |
| | | type: this.getUserType(user) |
| | | })) |
| | | |
| | | console.log('处理后的人员列表:', this.allStaffList, '数量:', this.allStaffList.length) |
| | | |
| | | this.filterStaffList() |
| | | }).catch(error => { |
| | | console.error('加载人员列表失败:', error) |
| | | this.$modal.showToast('加载人员列表失败') |
| | | }) |
| | | }, |
| | | |
| | | // 根据用户的岗位或角色判断类型 |
| | | getUserType(user) { |
| | | const postName = user.posts && user.posts.length > 0 ? user.posts[0].postName : '' |
| | | const roleName = user.roles && user.roles.length > 0 ? user.roles[0].roleName : '' |
| | | const deptName = user.dept?.deptName || '' |
| | | |
| | | if (postName.includes('司机') || roleName.includes('司机') || deptName.includes('车队') || deptName.includes('司机')) { |
| | | return 'driver' |
| | | } |
| | | if (postName.includes('护士') || roleName.includes('护士') || deptName.includes('护士')) { |
| | | return 'nurse' |
| | | } |
| | | if (postName.includes('医生') || roleName.includes('医生') || deptName.includes('医生')) { |
| | | return 'doctor' |
| | | } |
| | | if (deptName.includes('医护')) { |
| | | return 'doctor' |
| | | } |
| | | |
| | | return 'driver' |
| | | }, |
| | | |
| | | getUserTypeName(staffType) { |
| | | switch(staffType) { |
| | | case 'nurse': |
| | | return '护士' |
| | | case 'doctor': |
| | | return '医生' |
| | | case 'driver': |
| | | return '司机' |
| | | default: |
| | | return '司机' |
| | | } |
| | | }, |
| | | |
| | | // 显示人员选择弹窗 |
| | | showStaffSelector() { |
| | | this.$refs.staffPopup.open() |
| | | this.filterStaffList() |
| | | }, |
| | | |
| | | // 关闭人员选择弹窗 |
| | | closeStaffSelector() { |
| | | this.$refs.staffPopup.close() |
| | | this.staffSearchKeyword = '' |
| | | this.staffFilterType = 'driver' |
| | | }, |
| | | |
| | | // 人员搜索 |
| | | onStaffSearch(e) { |
| | | this.staffSearchKeyword = e.detail.value |
| | | this.filterStaffList() |
| | | }, |
| | | |
| | | // 筛选人员类型 |
| | | filterStaff(type) { |
| | | this.staffFilterType = type |
| | | this.filterStaffList() |
| | | }, |
| | | |
| | | // 过滤人员列表 |
| | | filterStaffList() { |
| | | console.log('开始过滤人员列表,原始数量:', this.allStaffList.length) |
| | | let list = [...this.allStaffList] |
| | | |
| | | // 按类型过滤 |
| | | if (this.staffFilterType === 'driver') { |
| | | list = list.filter(staff => staff.type === 'driver') |
| | | } else if (this.staffFilterType === 'doctor') { |
| | | list = list.filter(staff => staff.type === 'doctor') |
| | | } else if (this.staffFilterType === 'nurse') { |
| | | list = list.filter(staff => staff.type === 'nurse') |
| | | } |
| | | |
| | | console.log('按类型过滤后:', this.staffFilterType, '数量:', list.length) |
| | | |
| | | // 按关键词搜索 |
| | | if (this.staffSearchKeyword && this.staffSearchKeyword.trim() !== '') { |
| | | const keyword = this.staffSearchKeyword.trim().toLowerCase() |
| | | list = list.filter(staff => { |
| | | return staff.nickName.toLowerCase().includes(keyword) || |
| | | (staff.phonenumber && staff.phonenumber.includes(keyword)) |
| | | }) |
| | | } |
| | | |
| | | console.log('按关键词过滤后,数量:', list.length) |
| | | |
| | | this.filteredStaffList = list |
| | | }, |
| | | |
| | | // 切换人员选中状态 |
| | | toggleStaffSelection(staff) { |
| | | const index = this.selectedStaff.findIndex(s => s.userId === staff.userId) |
| | | |
| | | if (index > -1) { |
| | | // 已选中,移除 |
| | | this.selectedStaff.splice(index, 1) |
| | | } else { |
| | | // 未选中,添加 |
| | | this.selectedStaff.push(staff) |
| | | } |
| | | }, |
| | | |
| | | // 判断人员是否已选中 |
| | | isStaffSelected(userId) { |
| | | return this.selectedStaff.some(staff => staff.userId === userId) |
| | | }, |
| | | |
| | | // 确认人员选择 |
| | | confirmStaffSelection() { |
| | | if (this.selectedStaff.length === 0) { |
| | | this.$modal.showToast('请至少选择一名人员') |
| | | return |
| | | } |
| | | this.closeStaffSelector() |
| | | }, |
| | | |
| | | // 移除人员 |
| | | removeStaff(index) { |
| | | this.selectedStaff.splice(index, 1) |
| | | }, |
| | | |
| | | // 解析病情信息(从字符串解析出ICD-10疾病列表) |
| | | parseDiseaseInfo(conditionText, diseaseIds) { |
| | | if (!conditionText) { |
| | | console.log('病情文本为空,清空选中病情') |
| | | this.selectedDiseases = [] |
| | | this.taskForm.patient.otherCondition = '' |
| | | return |
| | | } |
| | | |
| | | // 解析diseaseIds(逗号分隔的字符串转为数组) |
| | | const diseaseIdArray = diseaseIds ? diseaseIds.split(',').map(id => parseInt(id.trim())).filter(id => !isNaN(id)) : [] |
| | | |
| | | // 如果包含"其他:"分隔符,拆分病情和其他描述 |
| | | 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, diseaseIdArray) |
| | | this.parseDiseaseList(diseasePart, diseases) |
| | | } else { |
| | | // 没有"其他"部分,全部作为其他描述 |
| | | this.taskForm.patient.otherCondition = conditionText |
| | | this.selectedDiseases = [] |
| | | // 没有"其他"部分,尝试解析是否有疾病列表 |
| | | 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, diseaseIdArray) { |
| | | 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 |
| | | let index = 0 |
| | | |
| | | 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({ |
| | | icdName: icdName, |
| | | id: null, // 从字符串解析时,没有ID |
| | | icdCode: icdCode, |
| | | id: diseaseIdArray && index < diseaseIdArray.length ? diseaseIdArray[index] : null |
| | | icdName: icdName |
| | | }) |
| | | index++ |
| | | } |
| | | } |
| | | |
| | | console.log('从字符串解析完成,数量:', diseases.length) |
| | | this.selectedDiseases = diseases |
| | | console.log('--- parseDiseaseList 结束 ---\n') |
| | | }, |
| | | |
| | | // 选择转出医院地址 |
| | |
| | | }, |
| | | |
| | | buildSubmitData() { |
| | | // 确保 selectedDiseases 和 selectedStaff 不为 null(修复:防止迭代 null 导致错误) |
| | | if (!this.selectedDiseases) { |
| | | this.selectedDiseases = [] |
| | | } |
| | | if (!this.selectedStaff) { |
| | | this.selectedStaff = [] |
| | | } |
| | | |
| | | // 合并病情信息:选中的ICD-10疾病 + 其他描述 |
| | | let conditionText = '' |
| | | if (this.selectedDiseases.length > 0) { |
| | |
| | | } |
| | | } |
| | | |
| | | // 构建提交数据 - 使用与 TaskCreateVO 一致的结构 |
| | | const submitData = { |
| | | taskId: this.taskId, |
| | | taskType: 'EMERGENCY_TRANSFER', |
| | | deptId: this.selectedOrganizationId, |
| | | vehicleIds: this.selectedVehicleId ? [this.selectedVehicleId] : [], |
| | | plannedStartTime: this.taskForm.transferTime, |
| | | // 出发地使用 departureAddress(如果有),否则使用转出医院地址 |
| | | |
| | | // 出发地地址和坐标(使用转出医院地址) |
| | | 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), |
| | | // 执行人员列表 |
| | | assignees: this.selectedStaff.map(staff => ({ |
| | | |
| | | // 执行人员列表(确保不为 null) |
| | | assignees: (this.selectedStaff && Array.isArray(this.selectedStaff)) ? this.selectedStaff.map(staff => ({ |
| | | userId: staff.userId, |
| | | userName: staff.nickName, |
| | | userType: staff.type |
| | | })), |
| | | emergencyInfo: { |
| | | patientContact: this.taskForm.patient.contact, |
| | | patientPhone: this.taskForm.patient.phone, |
| | | patientName: this.taskForm.patient.name, |
| | | patientGender: this.taskForm.patient.gender, |
| | | patientIdCard: this.taskForm.patient.idCard, |
| | | patientCondition: conditionText, // 使用合并后的病情信息 |
| | | hospitalOutName: this.taskForm.hospitalOut.name, |
| | | hospitalOutDepartment: this.taskForm.hospitalOut.department, |
| | | hospitalOutBedNumber: this.taskForm.hospitalOut.bedNumber, |
| | | hospitalOutAddress: this.taskForm.hospitalOut.address, |
| | | // 转出医院GPS坐标(保存到扩展表) |
| | | hospitalOutLongitude: this.addressCoordinates.hospitalOutAddress ? this.addressCoordinates.hospitalOutAddress.lng : null, |
| | | hospitalOutLatitude: this.addressCoordinates.hospitalOutAddress ? this.addressCoordinates.hospitalOutAddress.lat : null, |
| | | hospitalInName: this.taskForm.hospitalIn.name, |
| | | hospitalInDepartment: this.taskForm.hospitalIn.department, |
| | | hospitalInBedNumber: this.taskForm.hospitalIn.bedNumber, |
| | | hospitalInAddress: this.taskForm.hospitalIn.address, |
| | | // 转入医院GPS坐标(保存到扩展表) |
| | | hospitalInLongitude: this.addressCoordinates.hospitalInAddress ? this.addressCoordinates.hospitalInAddress.lng : null, |
| | | hospitalInLatitude: this.addressCoordinates.hospitalInAddress ? this.addressCoordinates.hospitalInAddress.lat : null, |
| | | transferDistance: this.taskForm.transferDistance ? parseFloat(this.taskForm.transferDistance) : null, |
| | | transferPrice: this.taskForm.price ? parseFloat(this.taskForm.price) : null, |
| | | })) : [], |
| | | |
| | | // 患者信息(嵌套对象) |
| | | 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()) |
| | |
| | | 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 |
| | | } |
| | | } |
| | | |
| | | // 出发地GPS坐标 |
| | | if (this.departureLongitude && this.departureLatitude) { |
| | | submitData.departureLongitude = this.departureLongitude |
| | | submitData.departureLatitude = this.departureLatitude |
| | | } |
| | | |
| | | // 目标地GPS坐标由后端自动获取 |
| | | |
| | | return submitData |
| | | }, |
| | |
| | | this.$modal.confirm('确定要保存修改吗?').then(() => { |
| | | 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 |
| | |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .staff-popup-container { |
| | | height: 80vh; |
| | | background-color: white; |
| | | border-top-left-radius: 20rpx; |
| | | border-top-right-radius: 20rpx; |
| | | display: flex; |
| | | flex-direction: column; |
| | | |
| | | .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; |
| | | } |
| | | } |
| | | |
| | | .search-bar { |
| | | padding: 20rpx 30rpx; |
| | | border-bottom: 1rpx solid #f0f0f0; |
| | | |
| | | .search-input { |
| | | height: 70rpx; |
| | | padding: 0 20rpx; |
| | | background-color: #f5f5f5; |
| | | border-radius: 10rpx; |
| | | font-size: 28rpx; |
| | | } |
| | | } |
| | | |
| | | .filter-tabs { |
| | | display: flex; |
| | | padding: 20rpx 30rpx; |
| | | gap: 20rpx; |
| | | border-bottom: 1rpx solid #f0f0f0; |
| | | |
| | | .filter-tab { |
| | | flex: 1; |
| | | height: 60rpx; |
| | | line-height: 60rpx; |
| | | text-align: center; |
| | | background-color: #f5f5f5; |
| | | border-radius: 10rpx; |
| | | font-size: 28rpx; |
| | | color: #666; |
| | | |
| | | &.active { |
| | | background-color: #007AFF; |
| | | color: white; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .staff-list-scroll { |
| | | flex: 1; |
| | | padding: 20rpx 30rpx; |
| | | |
| | | .staff-list-item { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | padding: 20rpx; |
| | | margin-bottom: 15rpx; |
| | | background-color: #f8f8f8; |
| | | border-radius: 10rpx; |
| | | |
| | | .staff-item-info { |
| | | flex: 1; |
| | | |
| | | .staff-item-name { |
| | | display: block; |
| | | font-size: 30rpx; |
| | | color: #333; |
| | | margin-bottom: 8rpx; |
| | | } |
| | | |
| | | .staff-item-dept { |
| | | display: block; |
| | | font-size: 24rpx; |
| | | color: #999; |
| | | } |
| | | } |
| | | |
| | | .staff-item-check { |
| | | width: 50rpx; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | } |
| | | } |
| | | |
| | | .empty-tip { |
| | | text-align: center; |
| | | padding: 100rpx 0; |
| | | color: #999; |
| | | font-size: 28rpx; |
| | | } |
| | | } |
| | | |
| | | .popup-footer { |
| | | padding: 20rpx 30rpx; |
| | | border-top: 1rpx solid #f0f0f0; |
| | | |
| | | .confirm-btn { |
| | | width: 100%; |
| | | height: 80rpx; |
| | | background-color: #007AFF; |
| | | color: white; |
| | | border-radius: 10rpx; |
| | | font-size: 32rpx; |
| | | } |
| | | } |
| | | } |