| | |
| | | import { listTask, changeTaskStatus } from '@/api/task' |
| | | import { mapState } from 'vuex' |
| | | import { formatDateTime } from '@/utils/common' |
| | | import { checkTaskCanDepart } from '@/utils/taskValidator' |
| | | |
| | | export default { |
| | | components: { |
| | |
| | | }, |
| | | |
| | | // å¤çä»»å¡æä½ |
| | | handleTaskAction(task, action) { |
| | | async handleTaskAction(task, action) { |
| | | switch (action) { |
| | | case 'depart': |
| | | // åºå -> ç¶æå为åºåä¸ |
| | | this.$modal.confirm('ç¡®å®è¦åºååï¼').then(() => { |
| | | this.updateTaskStatus(task.taskId, 'DEPARTING', 'ä»»å¡å·²åºå') |
| | | }).catch(() => {}); |
| | | // æ¾ç¤ºå è½½æç¤º |
| | | uni.showLoading({ |
| | | title: 'æ£æ¥ä»»å¡ç¶æ...' |
| | | }); |
| | | |
| | | try { |
| | | // è°ç¨å·¥å
·ç±»æ£æ¥ä»»å¡æ¯å¦å¯ä»¥åºåï¼å
å«åºæ¬æ ¡éªåå²çªæ£æ¥ï¼ |
| | | const checkResult = await checkTaskCanDepart(task) |
| | | |
| | | uni.hideLoading(); |
| | | |
| | | console.log('åºåæ£æ¥ç»æ:', checkResult); |
| | | console.log('valid:', checkResult.valid); |
| | | console.log('conflicts:', checkResult.conflicts); |
| | | |
| | | if (!checkResult.valid) { |
| | | // æ ¡éªå¤±è´¥ï¼æ¾ç¤ºæç¤ºä¿¡æ¯å¹¶æä¾è·³è½¬é项 |
| | | const conflicts = checkResult.conflicts || []; |
| | | const conflictInfo = conflicts.length > 0 ? conflicts[0] : null; |
| | | |
| | | console.log('å²çªä¿¡æ¯:', conflictInfo); |
| | | |
| | | // 妿æå²çªä»»å¡ä¿¡æ¯ï¼æä¾è·³è½¬æé® |
| | | if (conflictInfo && conflictInfo.taskId) { |
| | | console.log('æ¾ç¤ºå¸¦è·³è½¬æé®çå¼¹çªï¼ä»»å¡ID:', conflictInfo.taskId); |
| | | |
| | | const conflictTaskId = conflictInfo.taskId; |
| | | const message = checkResult.message || conflictInfo.message || 'åå¨å²çªä»»å¡'; |
| | | |
| | | uni.showModal({ |
| | | title: 'æç¤º', |
| | | content: message, |
| | | confirmText: 'å»å¤ç', |
| | | cancelText: 'ç¥éäº', |
| | | success: function(res) { |
| | | console.log('å¼¹çªç¹å»ç»æ:', res); |
| | | if (res.confirm) { |
| | | // ç¨æ·ç¹å»"ç°å¨å»å¤ç"ï¼è·³è½¬å°å²çªä»»å¡è¯¦æ
页 |
| | | console.log('åå¤è·³è½¬å°ä»»å¡è¯¦æ
页:', conflictTaskId); |
| | | uni.navigateTo({ |
| | | url: `/pagesTask/detail?id=${conflictTaskId}` |
| | | }); |
| | | } |
| | | }, |
| | | fail: function(err) { |
| | | console.error('æ¾ç¤ºå¼¹çªå¤±è´¥:', err); |
| | | } |
| | | }); |
| | | } else { |
| | | // 没æå²çªä»»å¡IDï¼åªæ¾ç¤ºæç¤º |
| | | console.log('æ¾ç¤ºæ®éæç¤ºå¼¹çª'); |
| | | uni.showModal({ |
| | | title: 'æç¤º', |
| | | content: checkResult.message || '任塿 ¡éªå¤±è´¥', |
| | | showCancel: false, |
| | | confirmText: 'ç¥éäº', |
| | | fail: function(err) { |
| | | console.error('æ¾ç¤ºå¼¹çªå¤±è´¥:', err); |
| | | } |
| | | }); |
| | | } |
| | | return; |
| | | } |
| | | |
| | | // æææ£æ¥éè¿ï¼å¯ä»¥åºå |
| | | this.$modal.confirm('ç¡®å®è¦åºååï¼').then(() => { |
| | | this.updateTaskStatus(task.taskId, 'DEPARTING', 'ä»»å¡å·²åºå') |
| | | }).catch(() => {}); |
| | | |
| | | } catch (error) { |
| | | uni.hideLoading(); |
| | | console.error('æ£æ¥ä»»å¡ç¶æå¤±è´¥:', error); |
| | | // æ£æ¥å¤±è´¥æ¶ï¼ä»ç¶å
许åºå |
| | | this.$modal.confirm('æ£æ¥ä»»å¡ç¶æå¤±è´¥ï¼æ¯å¦ç»§ç»åºåï¼').then(() => { |
| | | this.updateTaskStatus(task.taskId, 'DEPARTING', 'ä»»å¡å·²åºå') |
| | | }).catch(() => {}); |
| | | } |
| | | break; |
| | | |
| | | case 'cancel': |
| | |
| | | <view class="form-label">éæ©å¾ç</view> |
| | | <button class="choose-image-btn" @click="chooseImage"> |
| | | <uni-icons type="image" size="20"></uni-icons> |
| | | <text>ç¹å»éæ©</text> |
| | | <text class="btn-text">ç¹å»éæ©</text> |
| | | </button> |
| | | </view> |
| | | <view class="preview-area" v-if="tempImagePath"> |
| | |
| | | color: #666; |
| | | font-size: 28rpx; |
| | | |
| | | text { |
| | | .btn-text { |
| | | margin-left: 10rpx; |
| | | } |
| | | } |
| New file |
| | |
| | | <template> |
| | | <view class="form-item"> |
| | | <view class="form-label" :class="{ required: required }">{{ label }}</view> |
| | | <picker |
| | | v-if="!isHome && departmentOptions.length > 0" |
| | | mode="selector" |
| | | :range="departmentOptions" |
| | | range-key="text" |
| | | :value="selectedIndex" |
| | | @change="onDepartmentChange" |
| | | > |
| | | <view class="form-input picker-input"> |
| | | {{ displayText }} |
| | | <uni-icons type="arrowright" size="16" color="#999"></uni-icons> |
| | | </view> |
| | | </picker> |
| | | <input |
| | | v-else-if="!isHome" |
| | | class="form-input" |
| | | placeholder="请è¾å
¥ç§å®¤" |
| | | :value="value" |
| | | @input="onDepartmentInput" |
| | | /> |
| | | <view v-else class="form-input picker-input disabled"> |
| | | å
¶å® |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | import { getHospitalDepartments } from "@/api/dictionary" |
| | | |
| | | export default { |
| | | name: 'DepartmentSelector', |
| | | props: { |
| | | // æ ç¾ææ¬ |
| | | label: { |
| | | type: String, |
| | | default: 'ç§å®¤' |
| | | }, |
| | | // æ¯å¦å¿
å¡« |
| | | required: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | // å½åéä¸çç§å®¤åç§° |
| | | value: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | // å½åéä¸çç§å®¤ID |
| | | departmentId: { |
| | | type: [Number, String], |
| | | default: null |
| | | }, |
| | | // æ¯å¦ä¸º"å®¶ä¸"ï¼å¦ææ¯å®¶ä¸ï¼æ¾ç¤º"å
¶å®"ä¸ä¸å¯éæ©ï¼ |
| | | isHome: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | // å ä½ç¬¦ |
| | | placeholder: { |
| | | type: String, |
| | | default: 'è¯·éæ©ç§å®¤' |
| | | } |
| | | }, |
| | | data() { |
| | | return { |
| | | departmentOptions: [], // ç§å®¤é项å表 |
| | | selectedIndex: -1 |
| | | } |
| | | }, |
| | | computed: { |
| | | displayText() { |
| | | if (this.selectedIndex >= 0 && this.selectedIndex < this.departmentOptions.length) { |
| | | return this.departmentOptions[this.selectedIndex].text |
| | | } |
| | | return this.value || this.placeholder |
| | | } |
| | | }, |
| | | watch: { |
| | | value: { |
| | | immediate: true, |
| | | handler(newVal) { |
| | | if (newVal) { |
| | | this.updateSelectedIndex(newVal) |
| | | } else { |
| | | this.selectedIndex = -1 |
| | | } |
| | | } |
| | | }, |
| | | departmentId: { |
| | | immediate: true, |
| | | handler(newVal) { |
| | | if (newVal) { |
| | | this.updateSelectedIndexById(newVal) |
| | | } |
| | | } |
| | | }, |
| | | departmentOptions: { |
| | | immediate: true, |
| | | handler() { |
| | | if (this.value) { |
| | | this.updateSelectedIndex(this.value) |
| | | } else if (this.departmentId) { |
| | | this.updateSelectedIndexById(this.departmentId) |
| | | } |
| | | } |
| | | } |
| | | }, |
| | | mounted() { |
| | | this.loadDepartments() |
| | | }, |
| | | methods: { |
| | | // å è½½ç§å®¤æ°æ® |
| | | loadDepartments() { |
| | | getHospitalDepartments().then(response => { |
| | | const list = response.data || [] |
| | | this.departmentOptions = list.map(item => ({ |
| | | id: item.vID, |
| | | text: item.vtext, |
| | | dictValue: item.vtext |
| | | })) |
| | | }).catch(error => { |
| | | console.error('å è½½ç§å®¤æ°æ®å¤±è´¥:', error) |
| | | this.departmentOptions = [] |
| | | }) |
| | | }, |
| | | |
| | | // æ ¹æ®ç§å®¤åç§°æ´æ°éä¸ç´¢å¼ |
| | | updateSelectedIndex(departmentName) { |
| | | if (!departmentName || this.departmentOptions.length === 0) { |
| | | this.selectedIndex = -1 |
| | | return |
| | | } |
| | | |
| | | const index = this.departmentOptions.findIndex(d => d.text === departmentName) |
| | | this.selectedIndex = index !== -1 ? index : -1 |
| | | }, |
| | | |
| | | // æ ¹æ®ç§å®¤IDæ´æ°éä¸ç´¢å¼ |
| | | updateSelectedIndexById(departmentId) { |
| | | if (!departmentId || this.departmentOptions.length === 0) { |
| | | this.selectedIndex = -1 |
| | | return |
| | | } |
| | | |
| | | const index = this.departmentOptions.findIndex(d => d.id == departmentId) |
| | | this.selectedIndex = index !== -1 ? index : -1 |
| | | }, |
| | | |
| | | // ç§å®¤éæ©ååï¼pickerï¼ |
| | | onDepartmentChange(e) { |
| | | const index = e.detail.value |
| | | |
| | | // å®å
¨æ£æ¥ï¼ç¡®ä¿ç´¢å¼ææä¸é项åå¨ |
| | | if (index < 0 || index >= this.departmentOptions.length) { |
| | | console.warn('ç§å®¤éæ©ç´¢å¼è¶ç:', index, 'æ°ç»é¿åº¦:', this.departmentOptions.length) |
| | | return |
| | | } |
| | | |
| | | const selected = this.departmentOptions[index] |
| | | |
| | | // äºæ¬¡æ£æ¥ï¼ç¡®ä¿éä¸é¡¹åå¨ä¸ætext屿§ |
| | | if (!selected || !selected.text) { |
| | | console.warn('ç§å®¤éé¡¹æ°æ®å¼å¸¸:', selected) |
| | | return |
| | | } |
| | | |
| | | this.selectedIndex = index |
| | | |
| | | this.$emit('input', selected.text) |
| | | this.$emit('change', { |
| | | department: selected.text, |
| | | departmentId: selected.id |
| | | }) |
| | | }, |
| | | |
| | | // ç§å®¤è¾å
¥ï¼æå¨è¾å
¥ï¼ |
| | | onDepartmentInput(e) { |
| | | const department = e.detail.value |
| | | this.$emit('input', department) |
| | | this.$emit('change', { |
| | | department: department, |
| | | departmentId: null |
| | | }) |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .form-item { |
| | | margin-bottom: 40rpx; |
| | | |
| | | .form-label { |
| | | font-size: 28rpx; |
| | | margin-bottom: 15rpx; |
| | | color: #333; |
| | | |
| | | &.required::before { |
| | | content: '*'; |
| | | color: #ff0000; |
| | | margin-right: 5rpx; |
| | | } |
| | | } |
| | | |
| | | .form-input { |
| | | width: 100%; |
| | | height: 70rpx; |
| | | padding: 0 20rpx; |
| | | border: 1rpx solid #eee; |
| | | border-radius: 10rpx; |
| | | font-size: 28rpx; |
| | | box-sizing: border-box; |
| | | |
| | | &.picker-input { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | } |
| | | |
| | | &.disabled { |
| | | background-color: #f5f5f5; |
| | | color: #999; |
| | | } |
| | | } |
| | | } |
| | | </style> |
| | | |
| | |
| | | </view> |
| | | </view> |
| | | |
| | | <view class="form-item" v-if="showDepartment"> |
| | | <view class="form-label" :class="{ required: departmentRequired }">ç§å®¤</view> |
| | | <picker |
| | | v-if="selectedHospitalName !== 'å®¶ä¸' && departmentOptions.length > 0" |
| | | mode="selector" |
| | | :range="departmentOptions" |
| | | range-key="text" |
| | | @change="onDepartmentChange" |
| | | > |
| | | <view class="form-input picker-input"> |
| | | {{ departmentValue || 'è¯·éæ©ç§å®¤' }} |
| | | <uni-icons type="arrowright" size="16" color="#999"></uni-icons> |
| | | </view> |
| | | </picker> |
| | | <input |
| | | v-else-if="selectedHospitalName !== 'å®¶ä¸'" |
| | | class="form-input" |
| | | placeholder="请è¾å
¥ç§å®¤" |
| | | :value="departmentValue" |
| | | @input="onDepartmentInput" |
| | | /> |
| | | <view v-else class="form-input picker-input disabled"> |
| | | å
¶å® |
| | | </view> |
| | | </view> |
| | | |
| | | <view class="form-item" v-if="showBedNumber"> |
| | | <view class="form-label">åºå·</view> |
| | | <input |
| | | class="form-input" |
| | | placeholder="请è¾å
¥åºå·" |
| | | :value="bedNumberValue" |
| | | @input="onBedNumberInput" |
| | | /> |
| | | </view> |
| | | |
| | | <view class="form-item"> |
| | | <view class="form-label" :class="{ required: required }">{{ addressLabel }}</view> |
| | | <view class="address-input-container" v-if="selectedHospitalName === 'å®¶ä¸'"> |
| | |
| | | address: '' |
| | | }) |
| | | }, |
| | | // æ¯å¦æ¾ç¤ºç§å®¤ |
| | | showDepartment: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | // ç§å®¤æ¯å¦å¿
å¡« |
| | | departmentRequired: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | // ç§å®¤é项å表ï¼ç¨äº pickerï¼ |
| | | departmentOptions: { |
| | | type: Array, |
| | | default: () => [] |
| | | }, |
| | | // æ¯å¦æ¾ç¤ºåºå· |
| | | showBedNumber: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | // é¨é¨IDï¼ç¨äºåºåè¿æ»¤ï¼ |
| | | deptId: { |
| | | type: [Number, String], |
| | |
| | | computed: { |
| | | addressValue() { |
| | | return this.value.address || '' |
| | | }, |
| | | departmentValue() { |
| | | return this.value.department || '' |
| | | }, |
| | | bedNumberValue() { |
| | | return this.value.bedNumber || '' |
| | | } |
| | | }, |
| | | watch: { |
| | |
| | | const hospitalData = { |
| | | id: hospital.hospId, |
| | | name: hospital.hospName, |
| | | department: this.value.department || '', |
| | | departmentId: this.value.departmentId || null, |
| | | bedNumber: this.value.bedNumber || '', |
| | | address: hospital.hospName === 'å®¶ä¸' ? '' : this.buildFullAddress(hospital) |
| | | } |
| | | |
| | | // å¦æéæ©çæ¯"å®¶ä¸"ï¼ç§å®¤è®¾ç½®ä¸º"å
¶å®" |
| | | if (hospital.hospName === 'å®¶ä¸') { |
| | | hospitalData.department = 'å
¶å®' |
| | | hospitalData.departmentId = null |
| | | } |
| | | |
| | | this.showResults = false |
| | |
| | | ...this.value, |
| | | address: fullAddress |
| | | }) |
| | | this.$emit('address-selected', { |
| | | address: fullAddress, |
| | | location: item.location |
| | | }) |
| | | |
| | | this.showAddressSuggestions = false |
| | | this.addressSuggestions = [] |
| | | }, |
| | | |
| | | // ç§å®¤éæ©ååï¼pickerï¼ |
| | | onDepartmentChange(e) { |
| | | const index = e.detail.value |
| | | const selected = this.departmentOptions[index] |
| | | const updatedValue = { |
| | | ...this.value, |
| | | department: selected.text, |
| | | departmentId: selected.id |
| | | } |
| | | this.$emit('input', updatedValue) |
| | | this.$emit('department-change', { |
| | | department: selected.text, |
| | | departmentId: selected.id |
| | | }) |
| | | }, |
| | | |
| | | // ç§å®¤è¾å
¥ï¼æå¨è¾å
¥ï¼ |
| | | onDepartmentInput(e) { |
| | | const department = e.detail.value |
| | | this.$emit('input', { |
| | | ...this.value, |
| | | department: department |
| | | }) |
| | | this.$emit('department-change', department) |
| | | }, |
| | | |
| | | // åºå·è¾å
¥ |
| | | onBedNumberInput(e) { |
| | | const bedNumber = e.detail.value |
| | | this.$emit('input', { |
| | | ...this.value, |
| | | bedNumber: bedNumber |
| | | }) |
| | | this.$emit('bed-number-change', bedNumber) |
| | | } |
| | | } |
| | | } |
| | |
| | | label="å»é¢åç§°" |
| | | address-label="转åºå°å" |
| | | :required="true" |
| | | :department-required="true" |
| | | :show-department="false" |
| | | v-model="taskForm.hospitalOut" |
| | | :dept-id="selectedOrganizationId" |
| | | :region="selectedRegion" |
| | | :department-options="departmentOptions" |
| | | @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" |
| | | :department-required="true" |
| | | :show-department="false" |
| | | v-model="taskForm.hospitalIn" |
| | | :dept-id="selectedOrganizationId" |
| | | :region="selectedRegion" |
| | | :department-options="departmentOptions" |
| | | @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 required">转è¿å
¬éæ°</view> |
| | |
| | | import { checkVehicleActiveTasks } from "@/api/task" |
| | | |
| | | import { getDicts } from "@/api/dict" |
| | | import { getServiceOrdAreaTypes, getServiceOrderTypes, getHospitalDepartments } from "@/api/dictionary" |
| | | import { getServiceOrdAreaTypes, getServiceOrderTypes } from "@/api/dictionary" |
| | | import { listBranchCompany, getDept } from "@/api/system/dept" |
| | | 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 StaffSelector from './components/StaffSelector.vue' |
| | | import DepartmentSelector from './components/DepartmentSelector.vue' |
| | | |
| | | export default { |
| | | components: { |
| | |
| | | HospitalSelector, |
| | | DiseaseSelector, |
| | | DepartureSelector, |
| | | StaffSelector |
| | | StaffSelector, |
| | | DepartmentSelector |
| | | }, |
| | | data() { |
| | | return { |
| | |
| | | emergencyTaskTypeOptions: [], // ä»»å¡ç±»åé项ï¼ç¨äºpickeræ¾ç¤ºï¼ |
| | | documentTypes: [], // åæ®ç±»åå表 |
| | | documentTypeOptions: [], // åæ®ç±»åé项ï¼ç¨äºpickeræ¾ç¤ºï¼ |
| | | departmentOptions: [], // ç§å®¤åå
¸æ°æ® |
| | | loading: false, |
| | | // æºè½è¯å«ç¸å
³ |
| | | rawText: '', |
| | |
| | | this.getAvailableVehicles().then(() => { |
| | | this.getUserBoundVehicleInfo() |
| | | }) |
| | | // å è½½ç§å®¤åå
¸æ°æ® |
| | | this.loadDepartments() |
| | | // å 载任å¡ç±»åæ°æ® |
| | | this.loadEmergencyTaskTypes() |
| | | // å è½½åæ®ç±»åæ°æ® |
| | |
| | | } |
| | | }, |
| | | |
| | | // å è½½ç§å®¤æ°æ®ï¼ä» SQL Server 卿å è½½ï¼ |
| | | loadDepartments() { |
| | | getHospitalDepartments().then(response => { |
| | | const list = response.data || []; |
| | | this.departmentOptions = list.map(item => ({ |
| | | id: item.vID, |
| | | text: item.vtext, |
| | | dictValue: item.vtext // 为äºä¿æå
¼å®¹æ§ï¼ä¿çdictValueåæ®µ |
| | | })); |
| | | // console.log('ç§å®¤æ°æ®å è½½æå:', this.departmentOptions); |
| | | }).catch(error => { |
| | | console.error('å è½½ç§å®¤æ°æ®å¤±è´¥:', error) |
| | | this.departmentOptions = [] |
| | | }) |
| | | }, |
| | | |
| | | // å 载任å¡ç±»åæ°æ®ï¼ä» SQL Serverï¼ |
| | | loadEmergencyTaskTypes() { |
| | | getServiceOrderTypes().then(response => { |
| | |
| | | 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) { |
| | | // å¦æä¸¤ä¸ªé½ä¸æ¯"å®¶ä¸",使ç¨å»é¢è·ç¦»è®¡ç® |
| | |
| | | onHospitalInAddressSelected(data) { |
| | | if (this.taskForm.hospitalOut.address) { |
| | | this.calculateDistanceByManualAddress() |
| | | } |
| | | }, |
| | | |
| | | // 转åºç§å®¤åå |
| | | 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 |
| | | } |
| | | }, |
| | | |
| | |
| | | if (result.phone) this.taskForm.patient.phone = result.phone |
| | | if (result.price) this.taskForm.price = result.price |
| | | |
| | | // åºç¨ç§å®¤ä¿¡æ¯ï¼å¹é
departmentOptions ä¸çæ°æ®ï¼ |
| | | // åºç¨ç§å®¤ä¿¡æ¯ï¼éè¿ DepartmentSelector ç»ä»¶å¤çï¼ |
| | | if (result.departmentOut) { |
| | | const deptOut = this.matchDepartment(result.departmentOut) |
| | | if (deptOut) { |
| | | this.taskForm.hospitalOut.department = deptOut.text |
| | | this.taskForm.hospitalOut.departmentId = deptOut.id |
| | | } |
| | | this.taskForm.hospitalOut.department = result.departmentOut |
| | | // ç§å®¤IDä¼å¨ DepartmentSelector ç»ä»¶ä¸èªå¨å¹é
|
| | | } |
| | | if (result.departmentIn) { |
| | | const deptIn = this.matchDepartment(result.departmentIn) |
| | | if (deptIn) { |
| | | this.taskForm.hospitalIn.department = deptIn.text |
| | | this.taskForm.hospitalIn.departmentId = deptIn.id |
| | | } |
| | | this.taskForm.hospitalIn.department = result.departmentIn |
| | | // ç§å®¤IDä¼å¨ DepartmentSelector ç»ä»¶ä¸èªå¨å¹é
|
| | | } |
| | | |
| | | // å¤çå»é¢åç§° â 精确å¹é
å»é¢å¹¶è¡¥å
¨å°åä¸IDï¼ä¸éå¶åå
¬å¸åºåï¼ |
| | |
| | | return '' |
| | | }, |
| | | |
| | | // å¹é
ç§å®¤ï¼ä¼å
ä½¿ç¨ departmentOptions ä¸çæ°æ®ï¼ |
| | | matchDepartment(deptName) { |
| | | if (!deptName || !this.departmentOptions || this.departmentOptions.length === 0) { |
| | | return null |
| | | } |
| | | |
| | | const normalized = deptName.trim().toUpperCase() |
| | | |
| | | // 1. 精确å¹é
ï¼ä¸åºå大å°åï¼ |
| | | let matched = this.departmentOptions.find(d => |
| | | d.text.toUpperCase() === normalized |
| | | ) |
| | | if (matched) return matched |
| | | |
| | | // 2. å
å«å¹é
ï¼ç§å®¤åå
å«è¯å«å°çå
³é®è¯ï¼ |
| | | matched = this.departmentOptions.find(d => |
| | | d.text.toUpperCase().includes(normalized) || |
| | | normalized.includes(d.text.toUpperCase()) |
| | | ) |
| | | if (matched) return matched |
| | | |
| | | // 3. 模ç³å¹é
ï¼å»é¤"ç§"ã"室"çåç¼åå¹é
ï¼ |
| | | const cleanedInput = normalized.replace(/[ç§å®¤é¨]/g, '') |
| | | matched = this.departmentOptions.find(d => { |
| | | const cleanedDept = d.text.toUpperCase().replace(/[ç§å®¤é¨]/g, '') |
| | | return cleanedDept === cleanedInput || |
| | | cleanedDept.includes(cleanedInput) || |
| | | cleanedInput.includes(cleanedDept) |
| | | }) |
| | | if (matched) return matched |
| | | |
| | | return null |
| | | }, |
| | | |
| | | // æåç§å®¤ä¿¡æ¯ |
| | | extractDepartment(text, type) { |
| | | // 常è§ç§å®¤å
³é®è¯ï¼ä½ä¸ºå
åºæ¹æ¡ï¼ |
| | |
| | | 'æ£éªç§', 'ç
çç§', 'è¯åç§', 'è¥å
»ç§' |
| | | ] |
| | | |
| | | // ä¼å
å°è¯ä» departmentOptions ä¸å¹é
|
| | | if (this.departmentOptions && this.departmentOptions.length > 0) { |
| | | // æå»º departmentOptions çå¹é
模å¼ï¼æé¿åº¦ååºï¼ |
| | | const optionTexts = this.departmentOptions.map(d => d.text).sort((a, b) => b.length - a.length) |
| | | const optionPattern = optionTexts.map(t => t.replace(/[()ï¼ï¼]/g, '\\$&')).join('|') |
| | | |
| | | if (optionPattern) { |
| | | const regex = new RegExp(`(${optionPattern})`, 'gi') |
| | | const matches = text.match(regex) |
| | | |
| | | if (matches && matches.length > 0) { |
| | | // 妿æ¯è½¬åºï¼å第ä¸ä¸ªç§å®¤ï¼å¦ææ¯è½¬å
¥ï¼åæåä¸ä¸ªç§å®¤ |
| | | return type === 'out' ? matches[0] : matches[matches.length - 1] |
| | | } |
| | | } |
| | | } |
| | | |
| | | // å
åºï¼ä½¿ç¨é»è®¤ç§å®¤å表å¹é
|
| | | // 使ç¨é»è®¤ç§å®¤å表å¹é
|
| | | const sortedDepts = departments.sort((a, b) => b.length - a.length) |
| | | const deptPattern = sortedDepts.join('|') |
| | | |
| | |
| | | <view |
| | | class="assignee-item" |
| | | v-for="(assignee, index) in taskDetail.assignees" |
| | | :key="assignee.userId || index" |
| | | :key="'assignee-' + (assignee.userId || assignee.userName || index)" |
| | | > |
| | | <view class="assignee-index">{{ index + 1 }}</view> |
| | | <view class="assignee-info"> |
| | |
| | | </view> |
| | | </view> |
| | | |
| | | <view class="detail-section" v-if="taskDetail.taskDescription"> |
| | | <view class="detail-section" v-if="taskDetail.taskDescription && taskDetail.taskType !== 'EMERGENCY_TRANSFER'"> |
| | | <view class="section-title">ä»»å¡æè¿°</view> |
| | | <view class="description">{{ taskDetail.taskDescription }}</view> |
| | | </view> |
| | | |
| | | <view class="detail-section" v-if="taskDetail.remark"> |
| | | <view class="detail-section" v-if="taskDetail.remark && taskDetail.taskType !== 'EMERGENCY_TRANSFER'"> |
| | | <view class="section-title">夿³¨ä¿¡æ¯</view> |
| | | <view class="description">{{ taskDetail.remark }}</view> |
| | | </view> |
| | |
| | | <view class="section-title">æ¯ä»è®°å½</view> |
| | | <view |
| | | class="payment-record-item" |
| | | v-for="payment in paymentInfo.paidPayments" |
| | | :key="payment.id" |
| | | v-for="(payment, index) in paymentInfo.paidPayments" |
| | | :key="'payment-' + (payment.id || index)" |
| | | > |
| | | <view class="payment-header"> |
| | | <view |
| | |
| | | import { checkVehicleActiveTasks } from '@/api/task' |
| | | import { getPaymentInfo } from '@/api/payment' |
| | | import { formatDateTime } from '@/utils/common' |
| | | import { validateTaskForDepart, validateTaskForSettlement, getTaskVehicleId, checkTaskCanDepart } from '@/utils/taskValidator' |
| | | import AttachmentUpload from './components/AttachmentUpload.vue' |
| | | |
| | | export default { |
| | |
| | | |
| | | // å¤çç»ç® |
| | | handleSettlement() { |
| | | // æ ¡éªä»»å¡æ¯å¦å¯ä»¥ç»ç® |
| | | const validation = validateTaskForSettlement(this.taskDetail) |
| | | if (!validation.valid) { |
| | | this.$modal.confirm(`${validation.message}ï¼éè¦å
ä¿®æ¹ä»»å¡åæè½ç»ç®ãæ¯å¦ç°å¨å»ä¿®æ¹ï¼`).then(() => { |
| | | this.handleEdit() |
| | | }).catch(() => {}) |
| | | return |
| | | } |
| | | |
| | | uni.navigateTo({ |
| | | url: '/pagesTask/settlement?taskId=' + this.taskId |
| | | }) |
| | |
| | | }, |
| | | |
| | | // æ£æ¥è½¦è¾ç¶æå¹¶åºå |
| | | checkVehicleAndDepart() { |
| | | // æ£æ¥åºåæ¶é´æ¯å¦ä¸ºç©ºæ1900å¹´ï¼ä¿®å¤ï¼é²æ¢æ ææ¶é´ï¼ |
| | | if (!this.taskDetail.plannedStartTime || this.taskDetail.plannedStartTime.startsWith('1900')) { |
| | | this.$modal.confirm('ä»»å¡çè½¬è¿æ¶é´æªè®¾ç½®ææ æï¼éè¦å
ä¿®æ¹ä»»å¡è¡¥å
è½¬è¿æ¶é´åæè½åºåãæ¯å¦ç°å¨å»ä¿®æ¹ï¼').then(() => { |
| | | this.handleEdit() |
| | | }).catch(() => {}) |
| | | return |
| | | } |
| | | |
| | | // è·åä»»å¡è½¦è¾ID |
| | | const vehicleId = this.getVehicleId(); |
| | | if (!vehicleId) { |
| | | this.$modal.showToast('æªæ¾å°ä»»å¡è½¦è¾ä¿¡æ¯'); |
| | | return; |
| | | } |
| | | |
| | | async checkVehicleAndDepart() { |
| | | // æ¾ç¤ºå è½½æç¤º |
| | | uni.showLoading({ |
| | | title: 'æ£æ¥è½¦è¾ç¶æ...' |
| | | title: 'æ£æ¥ä»»å¡ç¶æ...' |
| | | }); |
| | | |
| | | checkVehicleActiveTasks(vehicleId).then(response => { |
| | | try { |
| | | // è°ç¨å·¥å
·ç±»æ£æ¥ä»»å¡æ¯å¦å¯ä»¥åºåï¼å
å«åºæ¬æ ¡éªåå²çªæ£æ¥ï¼ |
| | | const checkResult = await checkTaskCanDepart(this.taskDetail) |
| | | |
| | | uni.hideLoading(); |
| | | |
| | | const activeTasks = response.data || []; |
| | | console.log('åºåæ£æ¥ç»æ:', checkResult); |
| | | console.log('valid:', checkResult.valid); |
| | | console.log('conflicts:', checkResult.conflicts); |
| | | |
| | | // è¿æ»¤æå½å任塿¬èº«ï¼ä¿®å¤ï¼é²æ¢ activeTasks 为 nullï¼ |
| | | const otherActiveTasks = (activeTasks && Array.isArray(activeTasks)) ? activeTasks.filter(task => task.taskId !== this.taskId) : []; |
| | | |
| | | if (otherActiveTasks.length > 0) { |
| | | // è½¦è¾æå
¶ä»æ£å¨è¿è¡ä¸çä»»å¡ |
| | | const task = otherActiveTasks[0]; |
| | | const taskStatus = this.getStatusText(task.taskStatus); |
| | | const message = `该车è¾å·²ææ£å¨è½¬è¿ä¸çä»»å¡ï¼ |
| | | |
| | | ä»»å¡åå·ï¼${task.taskCode} |
| | | ä»»å¡ç¶æï¼${taskStatus} |
| | | |
| | | 请å
宿å½åä»»å¡åååºåæ°ä»»å¡ã`; |
| | | if (!checkResult.valid) { |
| | | // æ ¡éªå¤±è´¥ï¼æ¾ç¤ºæç¤ºä¿¡æ¯å¹¶æä¾è·³è½¬é项 |
| | | const conflicts = checkResult.conflicts || []; |
| | | const conflictInfo = conflicts.length > 0 ? conflicts[0] : null; |
| | | |
| | | uni.showModal({ |
| | | title: 'æç¤º', |
| | | content: message, |
| | | showCancel: false, |
| | | confirmText: 'æç¥éäº' |
| | | }); |
| | | console.log('å²çªä¿¡æ¯:', conflictInfo); |
| | | |
| | | // 妿æå²çªä»»å¡ä¿¡æ¯ï¼æä¾è·³è½¬æé® |
| | | if (conflictInfo && conflictInfo.taskId) { |
| | | console.log('æ¾ç¤ºå¸¦è·³è½¬æé®çå¼¹çªï¼ä»»å¡ID:', conflictInfo.taskId); |
| | | |
| | | const conflictTaskId = conflictInfo.taskId; |
| | | const message = checkResult.message || conflictInfo.message || 'åå¨å²çªä»»å¡'; |
| | | |
| | | uni.showModal({ |
| | | title: 'æç¤º', |
| | | content: message, |
| | | confirmText: 'å»å¤ç', |
| | | cancelText: 'ç¥éäº', |
| | | success: function(res) { |
| | | console.log('å¼¹çªç¹å»ç»æ:', res); |
| | | if (res.confirm) { |
| | | // ç¨æ·ç¹å»"ç°å¨å»å¤ç"ï¼è·³è½¬å°å²çªä»»å¡è¯¦æ
页 |
| | | console.log('åå¤è·³è½¬å°ä»»å¡è¯¦æ
页:', conflictTaskId); |
| | | uni.redirectTo({ |
| | | url: `/pagesTask/detail?id=${conflictTaskId}` |
| | | }); |
| | | } |
| | | }, |
| | | fail: function(err) { |
| | | console.error('æ¾ç¤ºå¼¹çªå¤±è´¥:', err); |
| | | } |
| | | }); |
| | | } else { |
| | | // 没æå²çªä»»å¡IDï¼åªæ¾ç¤ºæç¤º |
| | | console.log('æ¾ç¤ºæ®éæç¤ºå¼¹çª'); |
| | | uni.showModal({ |
| | | title: 'æç¤º', |
| | | content: checkResult.message || '任塿 ¡éªå¤±è´¥', |
| | | showCancel: false, |
| | | confirmText: 'ç¥éäº', |
| | | fail: function(err) { |
| | | console.error('æ¾ç¤ºå¼¹çªå¤±è´¥:', err); |
| | | } |
| | | }); |
| | | } |
| | | return; |
| | | } |
| | | |
| | | // è½¦è¾æ²¡æå
¶ä»æ£å¨è¿è¡ä¸çä»»å¡ï¼å¯ä»¥åºå |
| | | // æææ£æ¥éè¿ï¼å¯ä»¥åºå |
| | | this.$modal.confirm('ç¡®å®è¦åºååï¼').then(() => { |
| | | this.updateTaskStatus('DEPARTING', 'ä»»å¡å·²åºå') |
| | | }).catch(() => {}); |
| | | |
| | | }).catch(error => { |
| | | } catch (error) { |
| | | uni.hideLoading(); |
| | | console.error('æ£æ¥è½¦è¾ç¶æå¤±è´¥:', error); |
| | | console.error('æ£æ¥ä»»å¡ç¶æå¤±è´¥:', error); |
| | | // æ£æ¥å¤±è´¥æ¶ï¼ä»ç¶å
许åºå |
| | | this.$modal.confirm('æ£æ¥è½¦è¾ç¶æå¤±è´¥ï¼æ¯å¦ç»§ç»åºåï¼').then(() => { |
| | | this.$modal.confirm('æ£æ¥ä»»å¡ç¶æå¤±è´¥ï¼æ¯å¦ç»§ç»åºåï¼').then(() => { |
| | | this.updateTaskStatus('DEPARTING', 'ä»»å¡å·²åºå') |
| | | }).catch(() => {}); |
| | | }); |
| | | } |
| | | }, |
| | | |
| | | // è·åä»»å¡è½¦è¾ID |
| | |
| | | |
| | | <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> |
| | |
| | | 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 { |
| | |
| | | HospitalSelector, |
| | | DiseaseSelector, |
| | | DepartureSelector, |
| | | StaffSelector |
| | | StaffSelector, |
| | | DepartmentSelector |
| | | }, |
| | | mixins: [distanceCalculator], |
| | | data() { |
| | |
| | | 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) |
| New file |
| | |
| | | /** |
| | | * 任塿 ¡éªå·¥å
·ç±» |
| | | * ç¨äºç»ä¸ç®¡çä»»å¡ç¸å
³çåç½®æ ¡éªé»è¾ |
| | | */ |
| | | |
| | | import request from '@/utils/request' |
| | | |
| | | /** |
| | | * æ ¡éªä»»å¡æ¯å¦å¯ä»¥æ§è¡æä½ï¼åºåãç»ç®çï¼ |
| | | * @param {Object} task - ä»»å¡å¯¹è±¡ |
| | | * @param {Object} options - æ ¡éªé项 |
| | | * @param {Boolean} options.checkAssignees - æ¯å¦æ£æ¥æ§è¡äººåï¼é»è®¤true |
| | | * @param {Boolean} options.checkVehicles - æ¯å¦æ£æ¥è½¦è¾ï¼é»è®¤true |
| | | * @param {Boolean} options.checkPlannedTime - æ¯å¦æ£æ¥é¢çº¦æ¶é´ï¼é»è®¤true |
| | | * @returns {Object} { valid: Boolean, message: String, field: String } |
| | | */ |
| | | export function validateTaskForAction(task, options = {}) { |
| | | const { |
| | | checkAssignees = true, |
| | | checkVehicles = true, |
| | | checkPlannedTime = true |
| | | } = options |
| | | |
| | | // 1. æ£æ¥æ§è¡äººå |
| | | if (checkAssignees) { |
| | | const assigneeResult = validateAssignees(task) |
| | | if (!assigneeResult.valid) { |
| | | return assigneeResult |
| | | } |
| | | } |
| | | |
| | | // 2. æ£æ¥è½¦è¾ |
| | | if (checkVehicles) { |
| | | const vehicleResult = validateVehicles(task) |
| | | if (!vehicleResult.valid) { |
| | | return vehicleResult |
| | | } |
| | | } |
| | | |
| | | // 3. æ£æ¥é¢çº¦æ¶é´ |
| | | if (checkPlannedTime) { |
| | | const timeResult = validatePlannedTime(task) |
| | | if (!timeResult.valid) { |
| | | return timeResult |
| | | } |
| | | } |
| | | |
| | | return { valid: true, message: '', field: '' } |
| | | } |
| | | |
| | | /** |
| | | * æ£æ¥ä»»å¡æ¯å¦å·²åé
æ§è¡äººå |
| | | * @param {Object} task - ä»»å¡å¯¹è±¡ |
| | | * @returns {Object} { valid: Boolean, message: String, field: String } |
| | | */ |
| | | export function validateAssignees(task) { |
| | | if (!task.assignees || task.assignees.length === 0) { |
| | | return { |
| | | valid: false, |
| | | message: '任塿ªåé
æ§è¡äººå', |
| | | field: 'assignees' |
| | | } |
| | | } |
| | | return { valid: true, message: '', field: '' } |
| | | } |
| | | |
| | | /** |
| | | * æ£æ¥ä»»å¡æ¯å¦å·²åé
è½¦è¾ |
| | | * @param {Object} task - ä»»å¡å¯¹è±¡ |
| | | * @returns {Object} { valid: Boolean, message: String, field: String } |
| | | */ |
| | | export function validateVehicles(task) { |
| | | // æ¯æä¸¤ç§å段åï¼vehicleList å assignedVehicles |
| | | const vehicles = task.vehicleList || task.assignedVehicles |
| | | |
| | | if (!vehicles || vehicles.length === 0) { |
| | | return { |
| | | valid: false, |
| | | message: '任塿ªåé
车è¾', |
| | | field: 'vehicles' |
| | | } |
| | | } |
| | | return { valid: true, message: '', field: '' } |
| | | } |
| | | |
| | | /** |
| | | * æ£æ¥ä»»å¡é¢çº¦æ¶é´æ¯å¦ææ |
| | | * @param {Object} task - ä»»å¡å¯¹è±¡ |
| | | * @returns {Object} { valid: Boolean, message: String, field: String } |
| | | */ |
| | | export function validatePlannedTime(task) { |
| | | if (!task.plannedStartTime) { |
| | | return { |
| | | valid: false, |
| | | message: 'ä»»å¡çè½¬è¿æ¶é´æªè®¾ç½®', |
| | | field: 'plannedStartTime' |
| | | } |
| | | } |
| | | |
| | | // æ£æ¥æ¯å¦ä¸ºæ ææ¶é´ï¼1900å¹´ï¼ |
| | | if (task.plannedStartTime.startsWith('1900')) { |
| | | return { |
| | | valid: false, |
| | | message: 'ä»»å¡çè½¬è¿æ¶é´æ æ', |
| | | field: 'plannedStartTime' |
| | | } |
| | | } |
| | | |
| | | return { valid: true, message: '', field: '' } |
| | | } |
| | | |
| | | /** |
| | | * è·åä»»å¡ç车è¾ID |
| | | * @param {Object} task - ä»»å¡å¯¹è±¡ |
| | | * @returns {Number|null} 车è¾IDï¼æªæ¾å°è¿ånull |
| | | */ |
| | | export function getTaskVehicleId(task) { |
| | | if (!task) { |
| | | return null |
| | | } |
| | | |
| | | // ä»è½¦è¾å表ä¸è·å第ä¸ä¸ªè½¦è¾çID |
| | | const vehicles = task.assignedVehicles || task.vehicleList |
| | | if (vehicles && vehicles.length > 0) { |
| | | return vehicles[0].vehicleId |
| | | } |
| | | |
| | | // æè
ä»å个车è¾å¯¹è±¡è·å |
| | | if (task.vehicleId) { |
| | | return task.vehicleId |
| | | } |
| | | |
| | | return null |
| | | } |
| | | |
| | | /** |
| | | * æ ¡éªä»»å¡æ¯å¦å¯ä»¥åºå |
| | | * @param {Object} task - ä»»å¡å¯¹è±¡ |
| | | * @returns {Object} { valid: Boolean, message: String, field: String } |
| | | */ |
| | | export function validateTaskForDepart(task) { |
| | | return validateTaskForAction(task, { |
| | | checkAssignees: true, |
| | | checkVehicles: true, |
| | | checkPlannedTime: true |
| | | }) |
| | | } |
| | | |
| | | /** |
| | | * æ ¡éªä»»å¡æ¯å¦å¯ä»¥ç»ç® |
| | | * @param {Object} task - ä»»å¡å¯¹è±¡ |
| | | * @returns {Object} { valid: Boolean, message: String, field: String } |
| | | */ |
| | | export function validateTaskForSettlement(task) { |
| | | return validateTaskForAction(task, { |
| | | checkAssignees: true, |
| | | checkVehicles: true, |
| | | checkPlannedTime: true |
| | | }) |
| | | } |
| | | |
| | | /** |
| | | * æ£æ¥ä»»å¡æ¯å¦å¯ä»¥åºåï¼è°ç¨å端æ¥å£ï¼ |
| | | * æ£æ¥ï¼ |
| | | * 1. åºæ¬æ ¡éªï¼è½¦è¾ãæ§è¡äººåãé¢çº¦æ¶é´ |
| | | * 2. 车è¾å²çªæ£æ¥ï¼æ¯å¦ææªå®æçä»»å¡ |
| | | * 3. 人åå²çªæ£æ¥ï¼æ§è¡äººæ¯å¦ææªå®æçä»»å¡ |
| | | * |
| | | * @param {Object} task - ä»»å¡å¯¹è±¡ |
| | | * @returns {Promise<Object>} { valid: Boolean, message: String, conflicts: Array } |
| | | */ |
| | | export async function checkTaskCanDepart(task) { |
| | | // 1. å
è¿è¡åºæ¬æ ¡éª |
| | | const basicValidation = validateTaskForDepart(task) |
| | | if (!basicValidation.valid) { |
| | | return { |
| | | ...basicValidation, |
| | | conflicts: [] // ç¡®ä¿è¿åç对象å
å«conflictsåæ®µ |
| | | } |
| | | } |
| | | |
| | | // 2. è°ç¨å端æ¥å£æ£æ¥è½¦è¾å人åå²çª |
| | | try { |
| | | const response = await request({ |
| | | url: `/task/${task.taskId}/check-depart`, |
| | | method: 'get' |
| | | }) |
| | | |
| | | console.log('å端è¿åçåå§æ°æ®:', response) |
| | | |
| | | if (response.code === 200 && response.data) { |
| | | const { valid, conflicts } = response.data |
| | | |
| | | console.log('valid:', valid) |
| | | console.log('conflicts:', conflicts) |
| | | |
| | | if (!valid && conflicts && conflicts.length > 0) { |
| | | // æå²çªï¼è¿å第ä¸ä¸ªå²çªä¿¡æ¯ |
| | | return { |
| | | valid: false, |
| | | message: conflicts[0].message, |
| | | conflicts: conflicts |
| | | } |
| | | } |
| | | |
| | | return { valid: true, message: '', conflicts: [] } |
| | | } |
| | | |
| | | return { valid: false, message: 'æ£æ¥å¤±è´¥ï¼è¯·éè¯', conflicts: [] } |
| | | } catch (error) { |
| | | console.error('æ£æ¥ä»»å¡æ¯å¦å¯ä»¥åºå失败:', error) |
| | | // æ¥å£å¤±è´¥æ¶ï¼åªè¿è¡åºæ¬æ ¡éªï¼å
许åºå |
| | | return { valid: true, message: '', conflicts: [] } |
| | | } |
| | | } |
| | | |
| | | export default { |
| | | validateTaskForAction, |
| | | validateAssignees, |
| | | validateVehicles, |
| | | validatePlannedTime, |
| | | getTaskVehicleId, |
| | | validateTaskForDepart, |
| | | validateTaskForSettlement, |
| | | checkTaskCanDepart |
| | | } |
| New file |
| | |
| | | # 转è¿ä»»å¡ç¶æåæ´è®°å½åæ¥å°æ§ç³»ç»åè½è¯´æ |
| | | |
| | | ## ä¸ãåè½æ¦è¿° |
| | | |
| | | æ¬åè½å®ç°äºå¨è½¬è¿ä»»å¡ç¶æåçåæ´æ¶ï¼èªå¨å°ç¶æåæ´è®°å½åæ¥å°SQL Serveræ§ç³»ç»ç `DispatchOrd_Running` 表ä¸ã该åè½éè¿Springäºä»¶ç嬿ºå¶å®ç°ï¼ç¡®ä¿ç¶æåæ´ç宿´è®°å½å追踪ã |
| | | |
| | | ## äºãæ ¸å¿ç»ä»¶ |
| | | |
| | | ### 1. æ°æ®åºè¡¨ç»æ |
| | | |
| | | **æ§ç³»ç»è¡¨ï¼DispatchOrd_Running**ï¼SQL Serverï¼ |
| | | |
| | | ```sql |
| | | create table DispatchOrd_Running( |
| | | id int comment "èªå¢ä¸»é®", |
| | | DispatchOrdIDDt bigint comment 'è°åº¦åID', |
| | | DispatchOrdState int comment 'ç¶æ', |
| | | DispatchOrdStartDate datetime comment 'ç¶ææ¶é´', |
| | | DispatchOrdStartOA int comment 'æä½ç¶æçOAç¨æ·ID', |
| | | OA_latitude float comment 'æ´æ°ç¶ææ¶ç纬度', |
| | | OA_longitude float comment 'æ´æ°ç¶ææ¶çç»åº¦', |
| | | OA_address nvarchar(400) comment 'æ´æ°ç¶ææ¶çå°å' |
| | | ) |
| | | ``` |
| | | |
| | | ### 2. Mapperæ¥å£ |
| | | |
| | | **LegacyTransferSyncMapper.java** |
| | | |
| | | æ°å¢æ¹æ³ï¼ |
| | | ```java |
| | | /** |
| | | * æå
¥è°åº¦åç¶æåæ´è®°å½å° DispatchOrd_Running 表 |
| | | * |
| | | * @param dispatchOrdID è°åº¦åID |
| | | * @param dispatchOrdState ç¶æç |
| | | * @param dispatchOrdStartDate ç¶ææ¶é´ |
| | | * @param dispatchOrdStartOA æä½ç¶æçOAç¨æ·ID |
| | | * @param oaLatitude æ´æ°ç¶ææ¶ç纬度 |
| | | * @param oaLongitude æ´æ°ç¶ææ¶çç»åº¦ |
| | | * @param oaAddress æ´æ°ç¶ææ¶çå°å |
| | | * @return å½±åè¡æ° |
| | | */ |
| | | int insertDispatchOrdRunning( |
| | | @Param("dispatchOrdID") Long dispatchOrdID, |
| | | @Param("dispatchOrdState") Integer dispatchOrdState, |
| | | @Param("dispatchOrdStartDate") java.util.Date dispatchOrdStartDate, |
| | | @Param("dispatchOrdStartOA") Long dispatchOrdStartOA, |
| | | @Param("oaLatitude") Double oaLatitude, |
| | | @Param("oaLongitude") Double oaLongitude, |
| | | @Param("oaAddress") String oaAddress |
| | | ); |
| | | ``` |
| | | |
| | | ### 3. Mapper XMLé
ç½® |
| | | |
| | | **LegacyTransferSyncMapper.xml** |
| | | |
| | | ```xml |
| | | <!-- æå
¥è°åº¦åç¶æåæ´è®°å½å° DispatchOrd_Running 表 --> |
| | | <insert id="insertDispatchOrdRunning"> |
| | | INSERT INTO DispatchOrd_Running ( |
| | | DispatchOrdIDDt, |
| | | DispatchOrdState, |
| | | DispatchOrdStartDate, |
| | | DispatchOrdStartOA, |
| | | OA_latitude, |
| | | OA_longitude, |
| | | OA_address |
| | | ) VALUES ( |
| | | #{dispatchOrdID}, |
| | | #{dispatchOrdState}, |
| | | #{dispatchOrdStartDate}, |
| | | #{dispatchOrdStartOA}, |
| | | #{oaLatitude}, |
| | | #{oaLongitude}, |
| | | #{oaAddress} |
| | | ) |
| | | </insert> |
| | | ``` |
| | | |
| | | ### 4. äºä»¶çå¬å¨ |
| | | |
| | | **DispatchOrdRunningListener.java** |
| | | |
| | | - **ä½ç½®**: `ruoyi-system/src/main/java/com/ruoyi/system/listener/` |
| | | - **åè½**: çå¬ä»»å¡ç¶æåæ´äºä»¶ï¼TaskStatusChangedEventï¼ï¼èªå¨åæ¥ç¶æåæ´è®°å½å°æ§ç³»ç» |
| | | - **ç¹æ§**: |
| | | - â
**弿¥å¤ç**: ä½¿ç¨ `@Async` 注解ï¼ä¸é»å¡ä¸»ä¸å¡æµç¨ |
| | | - â
**äºä»¶çå¬**: ä½¿ç¨ `@EventListener` 注解çå¬ç¶æåæ´äºä»¶ |
| | | - â
**æºè½è¿æ»¤**: åªå¤çæ¥æè½¬è¿ä»»å¡ä¸å·²åæ¥å°æ§ç³»ç»çä»»å¡ |
| | | - â
**ç¶æè½¬æ¢**: èªå¨å°æ°ç³»ç»ç¶æè½¬æ¢ä¸ºæ§ç³»ç»ç¶æç |
| | | - â
**GPSè®°å½**: è®°å½ç¶æåæ´æ¶çGPSä½ç½®åå°åä¿¡æ¯ |
| | | - â
**容éå¤ç**: å¼å¸¸ä¸å½±å主ä¸å¡æµç¨ |
| | | |
| | | ## ä¸ã工使µç¨ |
| | | |
| | | ```mermaid |
| | | graph TB |
| | | A[转è¿ä»»å¡ç¶æåæ´] --> B[SysTaskServiceImpl.changeTaskStatus] |
| | | B --> C[åå¸TaskStatusChangedEventäºä»¶] |
| | | C --> D[DispatchOrdRunningListenerçå¬] |
| | | D --> E{æ¯å¦å¯ç¨æ§ç³»ç»åæ¥?} |
| | | E -->|å¦| F[è·³è¿åæ¥] |
| | | E -->|æ¯| G{æ¯å¦æ¥æè½¬è¿ä»»å¡?} |
| | | G -->|å¦| F |
| | | G -->|æ¯| H{è°åº¦åæ¯å¦å·²åæ¥?} |
| | | H -->|å¦| F |
| | | H -->|æ¯| I[转æ¢ç¶æç ] |
| | | I --> J{ç¶æéè¦åæ¥?} |
| | | J -->|å¦| F |
| | | J -->|æ¯| K[æå
¥DispatchOrd_Running表] |
| | | K --> L[è®°å½æ¥å¿] |
| | | ``` |
| | | |
| | | ## åãç¶ææ å°å
³ç³» |
| | | |
| | | æ°ç³»ç»ç¶æ â æ§ç³»ç»ç¶æç æ å°ï¼ |
| | | |
| | | | æ°ç³»ç»ç¶æ | TaskStatusæä¸¾ | æ§ç³»ç»ç¶æç | æ§ç³»ç»ç¶ææè¿° | |
| | | |-----------|---------------|-------------|---------------| |
| | | | åºåä¸ | DEPARTING | 4 | å·²åºè½¦ï¼å»æ¥æ£è
éä¸ï¼ | |
| | | | ä»»å¡ä¸ | IN_PROGRESS | 6 | å·²åºè½¦ï¼æå¡ä¸ï¼ | |
| | | | è¿ç¨ä¸ | RETURNING | 7 | å·²éè¾¾ï¼åç¨ä¸ï¼ | |
| | | | 已宿 | COMPLETED | 8 | å·²è¿å | |
| | | | 已忶 | CANCELLED | 10 | 忶 | |
| | | | å¾
å¤ç | PENDING | - | ä¸åæ¥ | |
| | | | å·²å°è¾¾ | ARRIVED | - | ä¸åæ¥ | |
| | | |
| | | ## äºã忥æ¡ä»¶ |
| | | |
| | | 满足以ä¸**æææ¡ä»¶**æ¶æä¼åæ¥ç¶æåæ´è®°å½ï¼ |
| | | |
| | | 1. â
æ§ç³»ç»åæ¥åè½å·²å¯ç¨ï¼`legacy.system.enabled=true`ï¼ |
| | | 2. â
ä»»å¡ç±»åä¸ºæ¥æè½¬è¿ï¼`EMERGENCY_TRANSFER`ï¼ |
| | | 3. â
ä»»å¡å·²åæ¥å°æ§ç³»ç»ï¼`legacy_dispatch_ord_id` ä¸ä¸ºç©ºï¼ |
| | | 4. â
æ°ç¶æéè¦åæ¥å°æ§ç³»ç»ï¼åè§ç¶ææ å°è¡¨ï¼ |
| | | |
| | | ## å
ã使ç¨ç¤ºä¾ |
| | | |
| | | ### 1. èªå¨è§¦åï¼æ¨èï¼ |
| | | |
| | | å½è½¬è¿ä»»å¡ç¶æåçåæ´æ¶ï¼ç³»ç»ä¼èªå¨è§¦ååæ¥ï¼ |
| | | |
| | | ```java |
| | | // å¨SysTaskServiceImplä¸åæ´ç¶æ |
| | | sysTaskService.changeTaskStatus(taskId, TaskStatus.DEPARTING, "叿ºå·²åºå"); |
| | | |
| | | // ç³»ç»èªå¨ï¼ |
| | | // 1. åå¸TaskStatusChangedEventäºä»¶ |
| | | // 2. DispatchOrdRunningListenerçå¬å¹¶å¤ç |
| | | // 3. æå
¥è®°å½å°DispatchOrd_Running表 |
| | | ``` |
| | | |
| | | ### 2. æ¥å¿ç¤ºä¾ |
| | | |
| | | **æååæ¥çæ¥å¿**ï¼ |
| | | ``` |
| | | 2025-12-05 14:30:15 INFO DispatchOrdRunningListener - æ¶å°ä»»å¡ç¶æåæ´äºä»¶ï¼åå¤åæ¥å°DispatchOrd_Runningï¼ä»»å¡IDï¼1001ï¼æ§ç¶æï¼PENDINGï¼æ°ç¶æï¼DEPARTING |
| | | 2025-12-05 14:30:15 INFO DispatchOrdRunningListener - å¼å§åæ¥ç¶æåæ´è®°å½å°DispatchOrd_Runningï¼DispatchOrdID: 12345, ç¶æç : 4, ç¶ææè¿°: å·²åºè½¦ï¼å»æ¥æ£è
éä¸ï¼ |
| | | 2025-12-05 14:30:15 INFO DispatchOrdRunningListener - ç¶æåæ´è®°å½å·²åæ¥å°DispatchOrd_Runningï¼DispatchOrdID: 12345, ç¶æç : 4 (å·²åºè½¦ï¼å»æ¥æ£è
éä¸ï¼), GPS: [113.264385, 23.12911], å°å: 广å·å¸è¶ç§åºXXè·¯XXå· |
| | | ``` |
| | | |
| | | **è·³è¿åæ¥çæ¥å¿**ï¼ |
| | | ``` |
| | | 2025-12-05 14:30:15 DEBUG DispatchOrdRunningListener - è°åº¦åæªåæ¥å°æ§ç³»ç»ï¼è·³è¿DispatchOrd_Running忥ï¼ä»»å¡ID: 1001 |
| | | ``` |
| | | |
| | | ## ä¸ãæ°æ®è®°å½å
容 |
| | | |
| | | æ¯æ¬¡ç¶æåæ´ä¼è®°å½ä»¥ä¸ä¿¡æ¯ï¼ |
| | | |
| | | | åæ®µ | 说æ | æ°æ®æ¥æº | |
| | | |-----|------|---------| |
| | | | DispatchOrdIDDt | è°åº¦åID | sys_task_emergency.legacy_dispatch_ord_id | |
| | | | DispatchOrdState | ç¶æç | 仿°ç³»ç»TaskStatus转æ¢èæ¥ | |
| | | | DispatchOrdStartDate | ç¶ææ¶é´ | å½åæ¶é´ | |
| | | | DispatchOrdStartOA | æä½äººID | TaskStatusChangedEvent.creatorId | |
| | | | OA_latitude | 纬度 | TaskStatusChangedEvent.latitude | |
| | | | OA_longitude | ç»åº¦ | TaskStatusChangedEvent.longitude | |
| | | | OA_address | å°å | TaskStatusChangedEvent.address | |
| | | |
| | | ## å
«ãçæ§åè°è¯ |
| | | |
| | | ### 1. æ¥çç¶æåæ´è®°å½ |
| | | |
| | | ```sql |
| | | -- SQL Server䏿¥è¯¢æè¿çç¶æåæ´è®°å½ |
| | | SELECT TOP 20 |
| | | DispatchOrdIDDt, |
| | | DispatchOrdState, |
| | | DispatchOrdStartDate, |
| | | DispatchOrdStartOA, |
| | | OA_latitude, |
| | | OA_longitude, |
| | | OA_address |
| | | FROM DispatchOrd_Running |
| | | ORDER BY DispatchOrdStartDate DESC |
| | | ``` |
| | | |
| | | ### 2. æ¥è¯¢ç¹å®è°åº¦åçç¶æåæ´åå² |
| | | |
| | | ```sql |
| | | -- æ¥è¯¢æä¸ªè°åº¦åçææç¶æåæ´è®°å½ |
| | | SELECT |
| | | DispatchOrdState, |
| | | DispatchOrdStartDate, |
| | | OA_latitude, |
| | | OA_longitude, |
| | | OA_address |
| | | FROM DispatchOrd_Running |
| | | WHERE DispatchOrdIDDt = 12345 |
| | | ORDER BY DispatchOrdStartDate DESC |
| | | ``` |
| | | |
| | | ### 3. ç»è®¡ä»æ¥ç¶æåæ´æ¬¡æ° |
| | | |
| | | ```sql |
| | | -- ç»è®¡ä»æ¥åç¶æçåæ´æ¬¡æ° |
| | | SELECT |
| | | DispatchOrdState, |
| | | CASE DispatchOrdState |
| | | WHEN 4 THEN 'å·²åºè½¦ï¼å»æ¥æ£è
éä¸ï¼' |
| | | WHEN 6 THEN 'å·²åºè½¦ï¼æå¡ä¸ï¼' |
| | | WHEN 7 THEN 'å·²éè¾¾ï¼åç¨ä¸ï¼' |
| | | WHEN 8 THEN 'å·²è¿å' |
| | | WHEN 10 THEN 'åæ¶' |
| | | ELSE 'å
¶ä»' |
| | | END AS StateName, |
| | | COUNT(*) AS ChangeCount |
| | | FROM DispatchOrd_Running |
| | | WHERE CONVERT(DATE, DispatchOrdStartDate) = CONVERT(DATE, GETDATE()) |
| | | GROUP BY DispatchOrdState |
| | | ORDER BY DispatchOrdState |
| | | ``` |
| | | |
| | | ## ä¹ãæ¶æä¼å¿ |
| | | |
| | | ### 1. å®å
¨è§£è¦ |
| | | - ä¸å¡é»è¾ä¸åæ¥é»è¾å离 |
| | | - ç¶æåæ´ä¸ä¾èµæ§ç³»ç»åæ¥ç»æ |
| | | - å¯ç¬ç«æµè¯åç»´æ¤ |
| | | |
| | | ### 2. 弿¥å¤ç |
| | | - ä¸é»å¡ä¸»ä¸å¡æµç¨ |
| | | - æé«ç³»ç»ååºé度 |
| | | - 容éè½å强 |
| | | |
| | | ### 3. èªå¨å |
| | | - æ éæå¨è§¦å |
| | | - 宿¶åæ¥ç¶æåæ´ |
| | | - åå°äººå·¥æä½ |
| | | |
| | | ### 4. å¯è¿½æº¯æ§ |
| | | - 宿´è®°å½æ¯æ¬¡ç¶æåæ´ |
| | | - å
å«GPSä½ç½®ä¿¡æ¯ |
| | | - 便äºé®é¢ææ¥å审计 |
| | | |
| | | ## åãæ³¨æäºé¡¹ |
| | | |
| | | ### 1. æ°æ®æºé
ç½® |
| | | |
| | | ç¡®ä¿ `LegacyTransferSyncMapper` 使ç¨SQL Serveræ°æ®æºï¼ |
| | | ```java |
| | | @DataSource(DataSourceType.SQLSERVER) |
| | | public interface LegacyTransferSyncMapper { |
| | | // ... |
| | | } |
| | | ``` |
| | | |
| | | ### 2. 弿¥çº¿ç¨æ± |
| | | |
| | | 弿¥å¤çä¾èµçº¿ç¨æ± é
ç½®ï¼AsyncConfig.javaï¼ï¼ |
| | | ```java |
| | | @Configuration |
| | | @EnableAsync |
| | | public class AsyncConfig { |
| | | @Bean(name = "taskExecutor") |
| | | public Executor taskExecutor() { |
| | | ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); |
| | | executor.setCorePoolSize(5); |
| | | executor.setMaxPoolSize(10); |
| | | executor.setQueueCapacity(100); |
| | | // ... |
| | | } |
| | | } |
| | | ``` |
| | | |
| | | ### 3. å¼å¸¸å¤ç |
| | | |
| | | çå¬å¨ä¸çå¼å¸¸ä¸ä¼å½±å主ä¸å¡ï¼ |
| | | - è®°å½è¯¦ç»æ¥å¿ |
| | | - 䏿åºå¼å¸¸ |
| | | - ä¸å½±åç¶æåæ´æä½ |
| | | |
| | | ### 4. æ§è½ä¼å |
| | | |
| | | - ä½¿ç¨ `@Async` 弿¥å¤ç |
| | | - åªåæ¥å¿
è¦çç¶æåæ´ |
| | | - æºè½è¿æ»¤ä¸éè¦åæ¥çä»»å¡ |
| | | |
| | | ## åä¸ãæµè¯éªè¯ |
| | | |
| | | ### 1. æµè¯æ¥éª¤ |
| | | |
| | | **æ¥éª¤1ï¼åå»ºå¹¶åæ¥è½¬è¿ä»»å¡** |
| | | ```java |
| | | // åå»ºæ¥æè½¬è¿ä»»å¡ |
| | | Long taskId = sysTaskService.insertSysTask(createVO); |
| | | |
| | | // ç¡®ä¿ä»»å¡å·²åæ¥å°æ§ç³»ç» |
| | | legacySystemSyncService.syncDispatchOrderToLegacy(taskId); |
| | | ``` |
| | | |
| | | **æ¥éª¤2ï¼åæ´ä»»å¡ç¶æ** |
| | | ```java |
| | | // åæ´ç¶æä¸º"åºåä¸" |
| | | sysTaskService.changeTaskStatus(taskId, TaskStatus.DEPARTING, "叿ºå·²åºå"); |
| | | ``` |
| | | |
| | | **æ¥éª¤3ï¼éªè¯SQL Serverè®°å½** |
| | | ```sql |
| | | -- æ¥è¯¢DispatchOrd_Running表 |
| | | SELECT * FROM DispatchOrd_Running |
| | | WHERE DispatchOrdIDDt = ( |
| | | SELECT legacy_dispatch_ord_id |
| | | FROM sys_task_emergency |
| | | WHERE task_id = ? |
| | | ) |
| | | ORDER BY DispatchOrdStartDate DESC |
| | | ``` |
| | | |
| | | ### 2. é¢æç»æ |
| | | |
| | | | æµè¯åºæ¯ | é¢æç»æ | |
| | | |---------|---------| |
| | | | æ¥æè½¬è¿ä»»å¡ç¶æåæ´ | æå
¥è®°å½å°DispatchOrd_Running | |
| | | | 鿥æè½¬è¿ä»»å¡ç¶æåæ´ | 䏿å
¥è®°å½ | |
| | | | æªåæ¥çä»»å¡ç¶æåæ´ | 䏿å
¥è®°å½ | |
| | | | ä¸éè¦åæ¥çç¶æï¼PENDINGï¼ | 䏿å
¥è®°å½ | |
| | | | æ§ç³»ç»åæ¥å·²ç¦ç¨ | 䏿å
¥è®°å½ | |
| | | |
| | | ## åäºãç¸å
³æä»¶æ¸
å |
| | | |
| | | ### æ°å¢æä»¶ |
| | | - `DispatchOrdRunningListener.java` - ç¶æåæ´çå¬å¨ |
| | | |
| | | ### ä¿®æ¹æä»¶ |
| | | - `LegacyTransferSyncMapper.java` - æ·»å insertDispatchOrdRunningæ¹æ³ |
| | | - `LegacyTransferSyncMapper.xml` - æ·»å æå
¥SQL |
| | | |
| | | ### ä¾èµæä»¶ï¼æ éä¿®æ¹ï¼ |
| | | - `SysTaskServiceImpl.java` - åå¸ç¶æåæ´äºä»¶ |
| | | - `TaskStatusChangedEvent.java` - ç¶æåæ´äºä»¶ |
| | | - `TaskStatusPushConverter.java` - ç¶æè½¬æ¢å·¥å
· |
| | | - `DispatchRunning.sql` - æ°æ®åºè¡¨ç»æå®ä¹ |
| | | |
| | | ## åä¸ãæ
éææ¥ |
| | | |
| | | ### é®é¢1ï¼ç¶æåæ´æ²¡æåæ¥å°æ§ç³»ç» |
| | | |
| | | **ææ¥æ¥éª¤**ï¼ |
| | | 1. æ£æ¥æ§ç³»ç»åæ¥æ¯å¦å¯ç¨ï¼`legacy.system.enabled=true` |
| | | 2. æ£æ¥ä»»å¡æ¯å¦ä¸ºæ¥æè½¬è¿ä»»å¡ |
| | | 3. æ£æ¥è°åº¦åæ¯å¦å·²åæ¥ï¼`legacy_dispatch_ord_id` ä¸ä¸ºç©º |
| | | 4. æ¥çæ¥å¿ç¡®è®¤æ¯å¦æå¼å¸¸ |
| | | 5. æ£æ¥ç¶ææ¯å¦éè¦åæ¥ï¼åèç¶ææ å°è¡¨ï¼ |
| | | |
| | | ### é®é¢2ï¼æ¥å¿ä¸åºç°å¼å¸¸ |
| | | |
| | | **常è§åå **ï¼ |
| | | - SQL Serverè¿æ¥å¤±è´¥ |
| | | - æ°æ®æºé
ç½®é误 |
| | | - åæ®µç±»åä¸å¹é
|
| | | |
| | | **è§£å³æ¹æ³**ï¼ |
| | | - æ£æ¥æ°æ®æºé
ç½® |
| | | - éªè¯SQL Serverè¿æ¥ |
| | | - æ¥ç详ç»é误æ¥å¿ |
| | | |
| | | ### é®é¢3ï¼æ§è½é®é¢ |
| | | |
| | | **ä¼å建议**ï¼ |
| | | - è°æ´çº¿ç¨æ± é
ç½® |
| | | - æ£æ¥SQL Serveræ§è½ |
| | | - ä¼åæ°æ®åºç´¢å¼ |
| | | |
| | | ## ååãæ»ç» |
| | | |
| | | æ¬åè½éè¿Springäºä»¶é©±å¨æºå¶ï¼å®ç°äºè½¬è¿ä»»å¡ç¶æåæ´è®°å½å°æ§ç³»ç»çèªå¨åæ¥ï¼å
·æä»¥ä¸ç¹ç¹ï¼ |
| | | |
| | | - â
**èªå¨å**ï¼ç¶æåæ´èªå¨åæ¥ï¼æ éæå¨æä½ |
| | | - â
**è§£è¦**ï¼ä¸å¡é»è¾ä¸åæ¥é»è¾å®å
¨å离 |
| | | - â
**弿¥**ï¼ä¸å½±å主ä¸å¡æ§è½ |
| | | - â
**宿´**ï¼è®°å½GPSä½ç½®ç详ç»ä¿¡æ¯ |
| | | - â
**å¯é **ï¼å®¹éå¤çï¼å¼å¸¸ä¸å½±å主æµç¨ |
| | | - â
**å¯è¿½æº¯**ï¼å®æ´çç¶æåæ´åå²è®°å½ |
| | |
| | | package com.ruoyi.web.controller.task; |
| | | |
| | | import java.util.List; |
| | | import javax.annotation.Resource; |
| | | import javax.servlet.http.HttpServletResponse; |
| | | |
| | | import com.ruoyi.system.service.*; |
| | | import org.springframework.beans.factory.annotation.Qualifier; |
| | | import org.springframework.security.access.prepost.PreAuthorize; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.web.bind.annotation.GetMapping; |
| | |
| | | import com.ruoyi.common.annotation.Log; |
| | | import com.ruoyi.common.core.controller.BaseController; |
| | | import com.ruoyi.common.core.domain.AjaxResult; |
| | | import com.ruoyi.common.core.domain.entity.SysUser; |
| | | import com.ruoyi.common.core.domain.entity.SysDept; |
| | | import com.ruoyi.common.enums.BusinessType; |
| | | import com.ruoyi.system.domain.SysTask; |
| | | import com.ruoyi.system.domain.SysTaskLog; |
| | |
| | | import com.ruoyi.system.domain.vo.TaskUpdateVO; |
| | | import com.ruoyi.system.domain.vo.TaskStatisticsVO; |
| | | import com.ruoyi.system.domain.enums.TaskStatus; |
| | | import com.ruoyi.system.service.ISysTaskService; |
| | | import com.ruoyi.system.service.IVehicleInfoService; |
| | | import com.ruoyi.common.utils.poi.ExcelUtil; |
| | | import com.ruoyi.common.core.page.TableDataInfo; |
| | | import com.ruoyi.common.utils.StringUtils; |
| | | |
| | | /** |
| | | * ä»»å¡ç®¡çController |
| | |
| | | |
| | | @Autowired |
| | | private IVehicleInfoService vehicleInfoService; |
| | | |
| | | @Autowired |
| | | private ISysUserService userService; |
| | | |
| | | @Autowired |
| | | private ISysDeptService deptService; |
| | | |
| | | |
| | | @Autowired |
| | | @Qualifier("tiandituMapService") |
| | | private IMapService mapService; |
| | | |
| | | /** |
| | | * æ¥è¯¢ä»»å¡ç®¡çå表ï¼åå°ç®¡çç«¯ï¼ |
| | |
| | | |
| | | /** |
| | | * æ¥è¯¢ä»»å¡å表ï¼APPç«¯ï¼ |
| | | * ä»
æ¾ç¤ºå½åç¨æ·ç¸å
³çä»»å¡ï¼ |
| | | * 1. å½åç¨æ·æå¨æºæçä»»å¡ |
| | | * 2. å½åç¨æ·å建çä»»å¡ |
| | | * 3. åé
ç»å½åç¨æ·çä»»å¡ |
| | | * æ ¹æ®ç¨æ·æéè¿åä¸åèå´çä»»å¡ï¼ |
| | | * 1. ææ¥çææå¨è¯¢åæéï¼canViewAllConsult='1'ï¼ï¼è¿åè¯¥ç¨æ·ç®¡çææåå
¬å¸ä¸çææä»»å¡å |
| | | * 2. æ æéï¼canViewAllConsult='0'ï¼ï¼åªè¿ååé
ç»è¯¥ç¨æ·çåæè¯¥ç¨æ·å建çå |
| | | */ |
| | | @GetMapping("/list") |
| | | public TableDataInfo appList(TaskQueryVO queryVO) { |
| | | // å¨å端èªå¨è·åå½åç¨æ·ä¿¡æ¯ï¼å®ç°ç»¼åæ¥è¯¢ |
| | | // è·åå½åç¨æ·ä¿¡æ¯ |
| | | Long currentUserId = getUserId(); |
| | | Long currentDeptId = getDeptId(); |
| | | SysUser currentUser = userService.selectUserById(currentUserId); |
| | | |
| | | // APP端强å¶ä½¿ç¨å½åç»å½ç¨æ·ä¿¡æ¯è¿è¡è¿æ»¤ |
| | | queryVO.setDeptId(currentDeptId); |
| | | queryVO.setCreatorId(currentUserId); |
| | | queryVO.setAssigneeId(currentUserId); |
| | | if (currentUser == null) { |
| | | return getDataTable(new java.util.ArrayList<>()); |
| | | } |
| | | |
| | | // å¤æç¨æ·æ¯å¦ææ¥çææå¨è¯¢åçæé |
| | | String canViewAllConsult = currentUser.getCanViewAllConsult(); |
| | | |
| | | if ("1".equals(canViewAllConsult)) { |
| | | // ææéï¼è¿åè¯¥ç¨æ·ç®¡çææåå
¬å¸ä¸çææä»»å¡å |
| | | // 1. è·åç¨æ·ç®¡ççåå
¬å¸å表 |
| | | List<SysDept> branchCompanies = deptService.computeBranchCompaniesForUser(currentUser); |
| | | |
| | | if (branchCompanies != null && !branchCompanies.isEmpty()) { |
| | | // 2. æåææåå
¬å¸ID |
| | | List<Long> deptIds = new java.util.ArrayList<>(); |
| | | for (SysDept dept : branchCompanies) { |
| | | deptIds.add(dept.getDeptId()); |
| | | } |
| | | |
| | | // 3. 设置æ¥è¯¢æ¡ä»¶ä¸ºåå
¬å¸IDå表ï¼SQLä¼èªå¨å
嫿æåé¨é¨ï¼ |
| | | queryVO.setDeptIds(deptIds); |
| | | // æ¸
空åå»ºäººåæ§è¡äººè¿æ»¤æ¡ä»¶ï¼è¿åè¿äºåå
¬å¸ä¸çææä»»å¡ |
| | | queryVO.setCreatorId(null); |
| | | queryVO.setAssigneeId(null); |
| | | } else { |
| | | // å¦ææ²¡ææ¾å°åå
¬å¸ï¼è¿å空å表 |
| | | return getDataTable(new java.util.ArrayList<>()); |
| | | } |
| | | } else { |
| | | // æ æéï¼åªè¿ååé
ç»è¯¥ç¨æ·çåæè¯¥ç¨æ·å建çå |
| | | // æ¸
空deptIdådeptIdsï¼ä½¿ç¨creatorIdåassigneeIdè¿è¡ORæ¥è¯¢ |
| | | queryVO.setDeptId(null); |
| | | queryVO.setDeptIds(null); |
| | | queryVO.setCreatorId(currentUserId); |
| | | queryVO.setAssigneeId(currentUserId); |
| | | } |
| | | |
| | | startPage(); |
| | | List<SysTask> list = sysTaskService.selectSysTaskList(queryVO); |
| | |
| | | |
| | | // 妿å
å«GPSä½ç½®ä¿¡æ¯ï¼ä½¿ç¨å¸¦ä½ç½®çæ¹æ³ |
| | | if (request.getLatitude() != null && request.getLongitude() != null) { |
| | | String address= mapService.reverseGeocoding(request.getLongitude(), request.getLatitude()); |
| | | request.setLocationAddress(address); |
| | | SysTaskLog locationLog = new SysTaskLog(); |
| | | locationLog.setLatitude(request.getLatitude()); |
| | | locationLog.setLongitude(request.getLongitude()); |
| | |
| | | locationLog.setAltitude(request.getAltitude()); |
| | | locationLog.setSpeed(request.getSpeed()); |
| | | locationLog.setHeading(request.getHeading()); |
| | | |
| | | |
| | | return toAjax(sysTaskService.changeTaskStatusWithLocation(taskId, newStatus, request.getRemark(), locationLog)); |
| | | } |
| | | |
| | | |
| | | return toAjax(sysTaskService.changeTaskStatus(taskId, newStatus, request.getRemark())); |
| | | } |
| | | |
| | |
| | | } |
| | | |
| | | /** |
| | | * æ£æ¥ä»»å¡æ¯å¦å¯ä»¥åºåï¼APPç«¯ï¼ |
| | | * æ£æ¥ï¼ |
| | | * 1. è½¦è¾æ¯å¦ææªå®æçä»»å¡ |
| | | * 2. æ§è¡äººåæ¯å¦ææªå®æçä»»å¡ |
| | | * |
| | | * @param taskId ä»»å¡ID |
| | | * @return æ ¡éªç»æ |
| | | */ |
| | | @GetMapping("/{taskId}/check-depart") |
| | | public AjaxResult checkTaskCanDepart(@PathVariable Long taskId) { |
| | | return sysTaskService.checkTaskCanDepart(taskId); |
| | | } |
| | | |
| | | /** |
| | | * åé
ä»»å¡è¯·æ±å¯¹è±¡ |
| | | */ |
| | | public static class AssignTaskRequest { |
| | |
| | | basename: i18n/messages |
| | | profiles: |
| | | # ç¯å¢ dev|test|prod |
| | | active: prod |
| | | active: dev |
| | | # æä»¶ä¸ä¼ |
| | | servlet: |
| | | multipart: |
| | |
| | | |
| | | /** 微信æµç§° */ |
| | | private String wechatNickname; |
| | | |
| | | /** æ¯å¦å¯æ¥çææå¨è¯¢åï¼0å¦ 1æ¯ï¼ */ |
| | | @Excel(name = "坿¥çææå¨è¯¢å", readConverterExp = "0=å¦,1=æ¯") |
| | | private String canViewAllConsult; |
| | | |
| | | |
| | | |
| | |
| | | this.wechatNickname = wechatNickname; |
| | | } |
| | | |
| | | public String getCanViewAllConsult() |
| | | { |
| | | return canViewAllConsult; |
| | | } |
| | | |
| | | public void setCanViewAllConsult(String canViewAllConsult) |
| | | { |
| | | this.canViewAllConsult = canViewAllConsult; |
| | | } |
| | | |
| | | |
| | | @Override |
| | |
| | | .append("openId", getOpenId()) |
| | | .append("unionId", getUnionId()) |
| | | .append("wechatNickname", getWechatNickname()) |
| | | .append("canViewAllConsult", getCanViewAllConsult()) |
| | | |
| | | .toString(); |
| | | } |
| | |
| | | |
| | | /** ç¨æ·å¯ç¨åå
¬å¸ç¼ç åè¡¨ï¼æ¥æºäºOA_User.OA_OrderClassï¼ */ |
| | | private String oaOrderClass; |
| | | |
| | | /** æ¯å¦å¯æ¥çææå¨è¯¢åï¼0å¦ 1æ¯ï¼ */ |
| | | private String canViewAllConsult; |
| | | |
| | | /** ç¨æ·æ§å«ï¼0=ç·,1=女,2=æªç¥ï¼ */ |
| | | private String sex; |
| | |
| | | { |
| | | this.oaOrderClass = oaOrderClass; |
| | | } |
| | | |
| | | public String getCanViewAllConsult() |
| | | { |
| | | return canViewAllConsult; |
| | | } |
| | | |
| | | public void setCanViewAllConsult(String canViewAllConsult) |
| | | { |
| | | this.canViewAllConsult = canViewAllConsult; |
| | | } |
| | | |
| | | @Override |
| | | public String toString() |
| | |
| | | ", email='" + email + '\'' + |
| | | ", phonenumber='" + phonenumber + '\'' + |
| | | ", oaOrderClass='" + oaOrderClass + '\'' + |
| | | ", canViewAllConsult='" + canViewAllConsult + '\'' + |
| | | '}'; |
| | | } |
| | | } |
| | |
| | | package com.ruoyi.system.domain.vo; |
| | | |
| | | import java.util.Date; |
| | | import java.util.List; |
| | | import com.fasterxml.jackson.annotation.JsonFormat; |
| | | import com.ruoyi.common.core.domain.BaseEntity; |
| | | |
| | |
| | | |
| | | /** å½å±é¨é¨ID */ |
| | | private Long deptId; |
| | | |
| | | /** å½å±é¨é¨IDå表ï¼ç¨äºæ¥è¯¢å¤ä¸ªåå
¬å¸çä»»å¡ï¼ */ |
| | | private List<Long> deptIds; |
| | | |
| | | /** 计åå¼å§æ¶é´-å¼å§ */ |
| | | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") |
| | |
| | | public void setDeptId(Long deptId) { |
| | | this.deptId = deptId; |
| | | } |
| | | |
| | | public List<Long> getDeptIds() { |
| | | return deptIds; |
| | | } |
| | | |
| | | public void setDeptIds(List<Long> deptIds) { |
| | | this.deptIds = deptIds; |
| | | } |
| | | |
| | | public Date getPlannedStartTimeBegin() { |
| | | return plannedStartTimeBegin; |
| | |
| | | package com.ruoyi.system.event; |
| | | |
| | | import lombok.Data; |
| | | |
| | | import java.math.BigDecimal; |
| | | import java.util.List; |
| | | |
| | | /** |
| | |
| | | * @author ruoyi |
| | | * @date 2025-10-25 |
| | | */ |
| | | |
| | | public class TaskStatusChangedEvent extends TaskEvent { |
| | | |
| | | private static final long serialVersionUID = 1L; |
| | |
| | | /** å建人ID */ |
| | | private Long creatorId; |
| | | |
| | | private Double longitude; |
| | | |
| | | /** 纬度 */ |
| | | private Double latitude; |
| | | |
| | | private String address; |
| | | |
| | | public TaskStatusChangedEvent(Object source, Long taskId, String taskCode, |
| | | String oldStatus, String newStatus, |
| | | String oldStatusDesc, String newStatusDesc, |
| | | List<Long> assigneeIds, Long creatorId) { |
| | | List<Long> assigneeIds, Long creatorId,Long operationId, Double longitude, |
| | | Double latitude,String address) { |
| | | super(source, taskId, taskCode); |
| | | this.oldStatus = oldStatus; |
| | | this.newStatus = newStatus; |
| | |
| | | this.newStatusDesc = newStatusDesc; |
| | | this.assigneeIds = assigneeIds; |
| | | this.creatorId = creatorId; |
| | | this.longitude = longitude; |
| | | this.latitude = latitude; |
| | | this.address = address; |
| | | this.setOperatorId(operationId); |
| | | } |
| | | |
| | | |
| | | |
| | | public Double getLongitude() { |
| | | return longitude; |
| | | } |
| | | public void setLongitude(Double longitude) { |
| | | this.longitude = longitude; |
| | | } |
| | | public Double getLatitude() { |
| | | return latitude; |
| | | } |
| | | public void setLatitude(Double latitude) { |
| | | this.latitude = latitude; |
| | | } |
| | | public String getAddress() { |
| | | return address; |
| | | } |
| | | public void setAddress(String address) { |
| | | this.address = address; |
| | | } |
| | | public String getOldStatus() { |
| | | return oldStatus; |
| | | } |
| New file |
| | |
| | | package com.ruoyi.system.listener; |
| | | |
| | | import com.ruoyi.common.config.LegacySystemConfig; |
| | | import com.ruoyi.common.core.domain.entity.SysUser; |
| | | import com.ruoyi.system.domain.SysTask; |
| | | import com.ruoyi.system.domain.SysTaskEmergency; |
| | | import com.ruoyi.system.domain.enums.TaskStatus; |
| | | import com.ruoyi.system.event.TaskStatusChangedEvent; |
| | | import com.ruoyi.system.mapper.LegacyTransferSyncMapper; |
| | | import com.ruoyi.system.mapper.SysTaskEmergencyMapper; |
| | | import com.ruoyi.system.mapper.SysTaskMapper; |
| | | import com.ruoyi.system.mapper.SysUserMapper; |
| | | import com.ruoyi.system.utils.TaskStatusPushConverter; |
| | | import org.slf4j.Logger; |
| | | import org.slf4j.LoggerFactory; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.context.event.EventListener; |
| | | import org.springframework.scheduling.annotation.Async; |
| | | import org.springframework.stereotype.Component; |
| | | |
| | | import java.util.Date; |
| | | |
| | | /** |
| | | * è°åº¦åç¶æåæ´è®°å½çå¬å¨ |
| | | * çå¬ä»»å¡ç¶æåæ´äºä»¶ï¼å¹¶å°ç¶æåæ´è®°å½åæ¥å°SQL ServerçDispatchOrd_Running表 |
| | | * |
| | | * @author ruoyi |
| | | * @date 2025-12-05 |
| | | */ |
| | | @Component |
| | | public class DispatchOrdRunningListener { |
| | | |
| | | private static final Logger log = LoggerFactory.getLogger(DispatchOrdRunningListener.class); |
| | | |
| | | @Autowired |
| | | private LegacySystemConfig legacyConfig; |
| | | |
| | | @Autowired |
| | | private SysTaskMapper sysTaskMapper; |
| | | |
| | | @Autowired |
| | | private SysTaskEmergencyMapper sysTaskEmergencyMapper; |
| | | |
| | | @Autowired |
| | | private LegacyTransferSyncMapper legacyTransferSyncMapper; |
| | | |
| | | @Autowired |
| | | private SysUserMapper sysUserMapper; |
| | | |
| | | /** |
| | | * çå¬ä»»å¡ç¶æåæ´äºä»¶ |
| | | * |
| | | * @param event ä»»å¡ç¶æåæ´äºä»¶ |
| | | */ |
| | | @Async |
| | | @EventListener |
| | | public void handleTaskStatusChangedEvent(TaskStatusChangedEvent event) { |
| | | try { |
| | | log.info("æ¶å°ä»»å¡ç¶æåæ´äºä»¶ï¼åå¤åæ¥å°DispatchOrd_Runningï¼ä»»å¡IDï¼{}ï¼æ§ç¶æï¼{}ï¼æ°ç¶æï¼{}", |
| | | event.getTaskId(), event.getOldStatus(), event.getNewStatus()); |
| | | |
| | | // æ£æ¥æ§ç³»ç»åæ¥æ¯å¦å¯ç¨ |
| | | if (!legacyConfig.isEnabled()) { |
| | | log.debug("æ§ç³»ç»åæ¥å·²ç¦ç¨ï¼è·³è¿DispatchOrd_Running忥ï¼ä»»å¡ID: {}", event.getTaskId()); |
| | | return; |
| | | } |
| | | |
| | | // æ¥è¯¢ä»»å¡ä¿¡æ¯ |
| | | SysTask task = sysTaskMapper.selectSysTaskByTaskId(event.getTaskId()); |
| | | if (task == null) { |
| | | log.error("ä»»å¡ä¸åå¨ï¼ä»»å¡ID: {}", event.getTaskId()); |
| | | return; |
| | | } |
| | | |
| | | // åªå¤çæ¥æè½¬è¿ä»»å¡ |
| | | if (!"EMERGENCY_TRANSFER".equals(task.getTaskType())) { |
| | | log.debug("鿥æè½¬è¿ä»»å¡ï¼è·³è¿DispatchOrd_Running忥ï¼ä»»å¡ID: {}", event.getTaskId()); |
| | | return; |
| | | } |
| | | |
| | | // æ¥è¯¢æ¥æè½¬è¿æ©å±ä¿¡æ¯ |
| | | SysTaskEmergency emergency = sysTaskEmergencyMapper.selectSysTaskEmergencyByTaskId(event.getTaskId()); |
| | | if (emergency == null) { |
| | | log.error("æ¥æè½¬è¿æ©å±ä¿¡æ¯ä¸åå¨ï¼ä»»å¡ID: {}", event.getTaskId()); |
| | | return; |
| | | } |
| | | |
| | | // å¿
须已ç»åæ¥è¿è°åº¦å |
| | | if (emergency.getLegacyDispatchOrdId() == null || emergency.getLegacyDispatchOrdId() <= 0) { |
| | | log.debug("è°åº¦åæªåæ¥å°æ§ç³»ç»ï¼è·³è¿DispatchOrd_Running忥ï¼ä»»å¡ID: {}", event.getTaskId()); |
| | | return; |
| | | } |
| | | |
| | | // è·åæ°ç³»ç»ç¶æ |
| | | TaskStatus newTaskStatus = TaskStatus.getByCode(event.getNewStatus()); |
| | | if (newTaskStatus == null) { |
| | | log.error("æ æçä»»å¡ç¶æï¼ä»»å¡ID: {}, ç¶æç : {}", event.getTaskId(), event.getNewStatus()); |
| | | return; |
| | | } |
| | | |
| | | SysUser user= sysUserMapper.selectUserById(event.getOperatorId()); |
| | | if(user==null){ |
| | | log.error("æä½äººä¸åå¨ï¼ä»»å¡ID: {}, æä½äººID: {}", event.getTaskId(), event.getOperatorId()); |
| | | return; |
| | | } |
| | | Integer oaUserId=user.getOaUserId(); |
| | | |
| | | // 转æ¢ä¸ºæ§ç³»ç»ç¶æç |
| | | Integer legacyStatusCode = TaskStatusPushConverter.convertToLegacyStatus(newTaskStatus); |
| | | if (legacyStatusCode == null) { |
| | | log.debug("ä»»å¡ç¶æä¸éè¦åæ¥å°æ§ç³»ç»ï¼ä»»å¡ID: {}, ç¶æ: {}", |
| | | event.getTaskId(), newTaskStatus.getInfo()); |
| | | return; |
| | | } |
| | | |
| | | // æå
¥ç¶æåæ´è®°å½å°DispatchOrd_Running表 |
| | | syncDispatchOrdRunning( |
| | | emergency.getLegacyDispatchOrdId(), |
| | | legacyStatusCode, |
| | | new Date(), // 使ç¨å½åæ¶é´ä½ä¸ºç¶æåæ´æ¶ |
| | | oaUserId.longValue(), |
| | | event.getLatitude(), |
| | | event.getLongitude(), |
| | | event.getAddress() |
| | | ); |
| | | |
| | | } catch (Exception e) { |
| | | log.error("å¤çä»»å¡ç¶æåæ´äºä»¶å¹¶åæ¥å°DispatchOrd_Running失败ï¼ä»»å¡ID: {}", event.getTaskId(), e); |
| | | // 䏿åºå¼å¸¸ï¼é¿å
å½±å主æµç¨ |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * åæ¥ç¶æåæ´è®°å½å°DispatchOrd_Running表 |
| | | * |
| | | * @param dispatchOrdId è°åº¦åID |
| | | * @param statusCode ç¶æç |
| | | * @param statusTime ç¶ææ¶é´ |
| | | * @param operatorId æä½äººID |
| | | * @param latitude 纬度 |
| | | * @param longitude ç»åº¦ |
| | | * @param address å°å |
| | | */ |
| | | private void syncDispatchOrdRunning(Long dispatchOrdId, Integer statusCode, |
| | | Date statusTime, Long operatorId, |
| | | Double latitude, Double longitude, String address) { |
| | | try { |
| | | // 夿æ¯å¦æGPSä¿¡æ¯ |
| | | boolean hasGps = (latitude != null && longitude != null); |
| | | if (hasGps) { |
| | | log.info("å¼å§åæ¥ç¶æåæ´è®°å½å°DispatchOrd_Runningï¼DispatchOrdID: {}, ç¶æç : {} ({}), GPS: [{}, {}]", |
| | | dispatchOrdId, statusCode, TaskStatusPushConverter.getLegacyStatusDescription(statusCode), |
| | | latitude, longitude); |
| | | } else { |
| | | log.info("å¼å§åæ¥ç¶æåæ´è®°å½å°DispatchOrd_Runningï¼DispatchOrdID: {}, ç¶æç : {} ({}), æ GPSä¿¡æ¯", |
| | | dispatchOrdId, statusCode, TaskStatusPushConverter.getLegacyStatusDescription(statusCode)); |
| | | } |
| | | |
| | | // è°ç¨Mapperæå
¥è®°å½ |
| | | int rows = legacyTransferSyncMapper.insertDispatchOrdRunning( |
| | | dispatchOrdId, |
| | | statusCode, |
| | | statusTime, |
| | | operatorId, |
| | | latitude, |
| | | longitude, |
| | | address |
| | | ); |
| | | |
| | | if (rows > 0) { |
| | | if (hasGps) { |
| | | log.info("ç¶æåæ´è®°å½å·²åæ¥å°DispatchOrd_Runningï¼DispatchOrdID: {}, ç¶æç : {} ({}), GPS: [{}, {}], å°å: {}", |
| | | dispatchOrdId, |
| | | statusCode, |
| | | TaskStatusPushConverter.getLegacyStatusDescription(statusCode), |
| | | latitude, |
| | | longitude, |
| | | address != null ? address : "æ "); |
| | | } else { |
| | | log.info("ç¶æåæ´è®°å½å·²åæ¥å°DispatchOrd_Runningï¼DispatchOrdID: {}, ç¶æç : {} ({}), æ GPSä¿¡æ¯", |
| | | dispatchOrdId, |
| | | statusCode, |
| | | TaskStatusPushConverter.getLegacyStatusDescription(statusCode)); |
| | | } |
| | | } else { |
| | | log.warn("åæ¥ç¶æåæ´è®°å½å¤±è´¥ï¼æªæå
¥æ°æ®ï¼DispatchOrdID: {}", dispatchOrdId); |
| | | } |
| | | |
| | | } catch (Exception e) { |
| | | log.error("åæ¥ç¶æåæ´è®°å½å°DispatchOrd_Runningå¼å¸¸ï¼DispatchOrdID: {}, ç¶æç : {}", |
| | | dispatchOrdId, statusCode, e); |
| | | // 䏿åºå¼å¸¸ï¼é¿å
å½±å主æµç¨ |
| | | } |
| | | } |
| | | } |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * çå¬ä»»å¡åé
äºä»¶ |
| | | * |
| | |
| | | * @return ç§å®¤åç§° |
| | | */ |
| | | String selectDepartmentNameByDeptID(@Param("deptID") String deptID); |
| | | |
| | | /** |
| | | * æå
¥è°åº¦åç¶æåæ´è®°å½å° DispatchOrd_Running 表 |
| | | * |
| | | * @param dispatchOrdID è°åº¦åID |
| | | * @param dispatchOrdState ç¶æç |
| | | * @param dispatchOrdStartDate ç¶ææ¶é´ |
| | | * @param dispatchOrdStartOA æä½ç¶æçOAç¨æ·ID |
| | | * @param oaLatitude æ´æ°ç¶ææ¶ç纬度 |
| | | * @param oaLongitude æ´æ°ç¶ææ¶çç»åº¦ |
| | | * @param oaAddress æ´æ°ç¶ææ¶çå°å |
| | | * @return å½±åè¡æ° |
| | | */ |
| | | int insertDispatchOrdRunning( |
| | | @Param("dispatchOrdID") Long dispatchOrdID, |
| | | @Param("dispatchOrdState") Integer dispatchOrdState, |
| | | @Param("dispatchOrdStartDate") java.util.Date dispatchOrdStartDate, |
| | | @Param("dispatchOrdStartOA") Long dispatchOrdStartOA, |
| | | @Param("oaLatitude") Double oaLatitude, |
| | | @Param("oaLongitude") Double oaLongitude, |
| | | @Param("oaAddress") String oaAddress |
| | | ); |
| | | } |
| | |
| | | */ |
| | | public boolean existsByLegacyDispatchOrdId(Long legacyDispatchOrdId); |
| | | |
| | | /** |
| | | * æ£æ¥ä»»å¡æ¯å¦å¯ä»¥åºå |
| | | * æ£æ¥ï¼ |
| | | * 1. è½¦è¾æ¯å¦ææªå®æçä»»å¡ |
| | | * 2. æ§è¡äººåæ¯å¦ææªå®æçä»»å¡ |
| | | * |
| | | * @param taskId ä»»å¡ID |
| | | * @return AjaxResult æ ¡éªç»æï¼å
å« valid å conflicts ä¿¡æ¯ |
| | | */ |
| | | public com.ruoyi.common.core.domain.AjaxResult checkTaskCanDepart(Long taskId); |
| | | |
| | | } |
| | |
| | | |
| | | @Autowired |
| | | private ITaskAttachmentService taskAttachmentService; |
| | | |
| | | |
| | | |
| | | /** |
| | | * åæ¥æ¥æè½¬è¿ä»»å¡å°æ§ç³»ç» |
| | |
| | | return null; |
| | | } |
| | | |
| | | |
| | | |
| | | // ====== åç½®æ ¡éªï¼ç¡®ä¿ä»»å¡æ°æ®å®æ´ ====== |
| | | |
| | | // 1. æ£æ¥æ¯å¦å·²åé
è½¦è¾ |
| | | List<SysTaskVehicle> taskVehicles = sysTaskVehicleMapper.selectSysTaskVehicleByTaskId(taskId); |
| | | if (taskVehicles == null || taskVehicles.isEmpty()) { |
| | | log.warn("任塿ªåé
车è¾ï¼è·³è¿è°åº¦å忥ï¼ä»»å¡ID: {}", taskId); |
| | | return null; |
| | | } |
| | | |
| | | // 2. æ£æ¥æ¯å¦å·²åé
æ§è¡äººå |
| | | List<SysTaskAssignee> taskAssignees = sysTaskAssigneeMapper.selectSysTaskAssigneeByTaskId(taskId); |
| | | if (taskAssignees == null || taskAssignees.isEmpty()) { |
| | | log.warn("任塿ªåé
æ§è¡äººåï¼è·³è¿è°åº¦å忥ï¼ä»»å¡ID: {}", taskId); |
| | | return null; |
| | | } |
| | | |
| | | // 3. æ£æ¥é¢çº¦æ¶é´æ¯å¦ææï¼å¿
须大äº1970å¹´ï¼ |
| | | if (task.getPlannedStartTime() == null) { |
| | | log.warn("任塿ªè®¾ç½®é¢çº¦æ¶é´ï¼è·³è¿è°åº¦å忥ï¼ä»»å¡ID: {}", taskId); |
| | | return null; |
| | | } |
| | | |
| | | // æ£æ¥é¢çº¦æ¶é´æ¯å¦å¤§äº1970-01-01ï¼æ¶é´æ³0对åº1970-01-01 00:00:00ï¼ |
| | | long timestamp1970 = 0L; |
| | | if (task.getPlannedStartTime().getTime() <= timestamp1970) { |
| | | log.warn("ä»»å¡é¢çº¦æ¶é´æ æï¼å°äºçäº1970å¹´ï¼ï¼è·³è¿è°åº¦å忥ï¼ä»»å¡ID: {}, é¢çº¦æ¶é´: {}", |
| | | taskId, task.getPlannedStartTime()); |
| | | return null; |
| | | } |
| | | |
| | | // 4. æ£æ¥è½¬åºå»é¢ä¿¡æ¯ |
| | | if (StringUtils.isEmpty(emergency.getHospitalOutName())) { |
| | | log.warn("任塿ªè®¾ç½®è½¬åºå»é¢ï¼è·³è¿è°åº¦å忥ï¼ä»»å¡ID: {}", taskId); |
| | | return null; |
| | | } |
| | | |
| | | if (StringUtils.isEmpty(emergency.getHospitalOutAddress())) { |
| | | log.warn("任塿ªè®¾ç½®è½¬åºå»é¢å°åï¼è·³è¿è°åº¦å忥ï¼ä»»å¡ID: {}", taskId); |
| | | return null; |
| | | } |
| | | |
| | | // 5. æ£æ¥è½¬å
¥å»é¢ä¿¡æ¯ |
| | | if (StringUtils.isEmpty(emergency.getHospitalInName())) { |
| | | log.warn("任塿ªè®¾ç½®è½¬å
¥å»é¢ï¼è·³è¿è°åº¦å忥ï¼ä»»å¡ID: {}", taskId); |
| | | return null; |
| | | } |
| | | |
| | | if (StringUtils.isEmpty(emergency.getHospitalInAddress())) { |
| | | log.warn("任塿ªè®¾ç½®è½¬å
¥å»é¢å°åï¼è·³è¿è°åº¦å忥ï¼ä»»å¡ID: {}", taskId); |
| | | return null; |
| | | } |
| | | |
| | | // 6. æ£æ¥æ£è
åºæ¬ä¿¡æ¯ |
| | | if (StringUtils.isEmpty(emergency.getPatientName())) { |
| | | log.warn("任塿ªè®¾ç½®æ£è
å§åï¼è·³è¿è°åº¦å忥ï¼ä»»å¡ID: {}", taskId); |
| | | return null; |
| | | } |
| | | |
| | | if (StringUtils.isEmpty(emergency.getPatientPhone())) { |
| | | log.warn("任塿ªè®¾ç½®æ£è
çµè¯ï¼è·³è¿è°åº¦å忥ï¼ä»»å¡ID: {}", taskId); |
| | | return null; |
| | | } |
| | | |
| | | log.info("任塿°æ®æ ¡éªéè¿ï¼å¼å§åæ¥è°åº¦åï¼ä»»å¡ID: {}", taskId); |
| | | |
| | | // æ´æ°åæ¥ç¶æä¸ºåæ¥ä¸ |
| | | emergency.setDispatchSyncStatus(1); |
| | |
| | | return false; |
| | | } |
| | | |
| | | log.info("å¼å§éæ°åæ¥è°åº¦åï¼ä»»å¡ID: {}, DispatchOrdID: {}", taskId, emergency.getLegacyDispatchOrdId()); |
| | | // ====== åç½®æ ¡éªï¼ç¡®ä¿ä»»å¡æ°æ®å®æ´ ====== |
| | | |
| | | // 1. æ£æ¥æ¯å¦å·²åé
è½¦è¾ |
| | | List<SysTaskVehicle> taskVehicles = sysTaskVehicleMapper.selectSysTaskVehicleByTaskId(taskId); |
| | | if (taskVehicles == null || taskVehicles.isEmpty()) { |
| | | log.warn("任塿ªåé
车è¾ï¼è·³è¿è°åº¦å鿰忥ï¼ä»»å¡ID: {}", taskId); |
| | | return false; |
| | | } |
| | | |
| | | // 2. æ£æ¥æ¯å¦å·²åé
æ§è¡äººå |
| | | List<SysTaskAssignee> taskAssignees = sysTaskAssigneeMapper.selectSysTaskAssigneeByTaskId(taskId); |
| | | if (taskAssignees == null || taskAssignees.isEmpty()) { |
| | | log.warn("任塿ªåé
æ§è¡äººåï¼è·³è¿è°åº¦å鿰忥ï¼ä»»å¡ID: {}", taskId); |
| | | return false; |
| | | } |
| | | |
| | | // 3. æ£æ¥é¢çº¦æ¶é´æ¯å¦ææ |
| | | if (task.getPlannedStartTime() == null || task.getPlannedStartTime().getTime() <= 0L) { |
| | | log.warn("ä»»å¡é¢çº¦æ¶é´æ æï¼è·³è¿è°åº¦å鿰忥ï¼ä»»å¡ID: {}", taskId); |
| | | return false; |
| | | } |
| | | |
| | | // 4. æ£æ¥è½¬åºå»é¢ä¿¡æ¯ |
| | | if (StringUtils.isEmpty(emergency.getHospitalOutName()) || StringUtils.isEmpty(emergency.getHospitalOutAddress())) { |
| | | log.warn("ä»»å¡è½¬åºå»é¢ä¿¡æ¯ä¸å®æ´ï¼è·³è¿è°åº¦å鿰忥ï¼ä»»å¡ID: {}", taskId); |
| | | return false; |
| | | } |
| | | |
| | | // 5. æ£æ¥è½¬å
¥å»é¢ä¿¡æ¯ |
| | | if (StringUtils.isEmpty(emergency.getHospitalInName()) || StringUtils.isEmpty(emergency.getHospitalInAddress())) { |
| | | log.warn("ä»»å¡è½¬å
¥å»é¢ä¿¡æ¯ä¸å®æ´ï¼è·³è¿è°åº¦å鿰忥ï¼ä»»å¡ID: {}", taskId); |
| | | return false; |
| | | } |
| | | |
| | | // 6. æ£æ¥æ£è
åºæ¬ä¿¡æ¯ |
| | | if (StringUtils.isEmpty(emergency.getPatientName()) || StringUtils.isEmpty(emergency.getPatientPhone())) { |
| | | log.warn("任塿£è
ä¿¡æ¯ä¸å®æ´ï¼è·³è¿è°åº¦å鿰忥ï¼ä»»å¡ID: {}", taskId); |
| | | return false; |
| | | } |
| | | |
| | | log.info("任塿°æ®æ ¡éªéè¿ï¼å¼å§éæ°åæ¥è°åº¦åï¼ä»»å¡ID: {}, DispatchOrdID: {}", taskId, emergency.getLegacyDispatchOrdId()); |
| | | |
| | | // æå»ºè¯·æ±åæ°ï¼ä½¿ç¨ç¸åçåæ°æå»ºæ¹æ³ï¼ |
| | | Map<String, String> params = buildDispatchOrderParams(task, emergency); |
| | |
| | | log.error("æå¡åIDä¸è½ä¸ºç©º"); |
| | | return false; |
| | | } |
| | | |
| | | // ç´æ¥æ¥è¯¢æå®ç转è¿åä¿¡æ¯ |
| | | List<Map<String, Object>> transferOrders = legacyTransferSyncMapper.selectTransferOrdersByIDs(serviceOrdID, dispatchOrdID); |
| | | |
| | | Map<String, Object> order = transferOrders.get(0); |
| | | |
| | | // æ£æ¥æ¯å¦å·²åæ¥ |
| | | if (isTransferOrderSynced(serviceOrdID, dispatchOrdID)) { |
| | | log.info("转è¿å已忥ï¼è·³è¿: ServiceOrdID={}, DispatchOrdID={}", serviceOrdID, dispatchOrdID); |
| | | updateTransferOrder(serviceOrdID, dispatchOrdID, order); |
| | | return true; |
| | | } |
| | | |
| | | // ç´æ¥æ¥è¯¢æå®ç转è¿åä¿¡æ¯ |
| | | List<Map<String, Object>> transferOrders = legacyTransferSyncMapper.selectTransferOrdersByIDs(serviceOrdID, dispatchOrdID); |
| | | |
| | | |
| | | if (transferOrders == null || transferOrders.isEmpty()) { |
| | | log.error("æªæ¥è¯¢å°å¯¹åºç转è¿åä¿¡æ¯: ServiceOrdID={}, DispatchOrdID={}", serviceOrdID, dispatchOrdID); |
| | | return false; |
| | | } |
| | | |
| | | Map<String, Object> order = transferOrders.get(0); |
| | | |
| | | |
| | | // 忥å个转è¿å |
| | | return syncSingleTransferOrder(serviceOrdID, dispatchOrdID, order); |
| | |
| | | String serviceOrdClass = getStringValue(order,"ServiceOrdClass"); |
| | | String serviceOrdNo = getStringValue(order,"ServiceOrdNo"); |
| | | |
| | | Integer oauserId=getIntegerValue(order,"ServiceOrd_NS_ID"); |
| | | /** |
| | | * å建人ID |
| | | */ |
| | | Integer oauserId=getIntegerValue(order,"ServiceOrd_CC_ID"); |
| | | SysUser sysUser=sysUserService.selectUserByOaUserId(oauserId); |
| | | Long taskCreatorId=sysUser==null?null:sysUser.getUserId(); |
| | | String createUserName=sysUser==null?"system":sysUser.getUserName(); |
| | |
| | | hospitalInInfo.setName(hospitalInName); |
| | | } |
| | | } |
| | | String DispatchOrdTraEnd = getStringValue(order, "DispatchOrdTraEnd"); |
| | | if(DispatchOrdTraEnd!= null){ |
| | | hospitalInInfo.setAddress(DispatchOrdTraEnd); |
| | | String serviceOrdTraEnd = getStringValue(order, "ServiceOrdTraEnd"); |
| | | if(serviceOrdTraEnd!= null){ |
| | | hospitalInInfo.setAddress(serviceOrdTraEnd); |
| | | } |
| | | //转å
¥åºä½ |
| | | String serviceOrdPtInServices =getStringValue(order, "ServiceOrdPtInServices"); |
| | |
| | | // è®¾ç½®ä»·æ ¼åè·ç¦»ä¿¡æ¯ |
| | | createTaskVo.setPrice(getBigDecimalValue(order, "ServiceOrdTraTxnPrice")); |
| | | // è·ç¦»ä¿¡æ¯éè¦ä»å
¶ä»åæ®µè®¡ç®æè·å |
| | | |
| | | // 设置æ§è¡äººä¿¡æ¯ |
| | | List<TaskCreateVO.AssigneeInfo> assignees = queryAssignees(dispatchOrdID); |
| | | createTaskVo.setAssignees(assignees); |
| | | if(!assignees.isEmpty()){ |
| | | createTaskVo.setAssigneeId(assignees.get(0).getUserId()); |
| | | |
| | | if(dispatchOrdID!=null) { |
| | | // 设置æ§è¡äººä¿¡æ¯ |
| | | List<TaskCreateVO.AssigneeInfo> assignees = queryAssignees(dispatchOrdID); |
| | | createTaskVo.setAssignees(assignees); |
| | | if (!assignees.isEmpty()) { |
| | | createTaskVo.setAssigneeId(assignees.get(0).getUserId()); |
| | | } |
| | | } |
| | | |
| | | // 设置车è¾ä¿¡æ¯ |
| | | // 车è¾IDéè¦æ ¹æ®DispatchOrdCarIDæ¥è¯¢è·å |
| | | String carID = getStringValue(order, "DispatchOrdCarID"); |
| | |
| | | * @return ç»æ |
| | | */ |
| | | @Override |
| | | @Transactional |
| | | public int changeTaskStatus(Long taskId, TaskStatus newStatus, String remark) { |
| | | return changeTaskStatusWithLocation(taskId, newStatus, remark, null); |
| | | } |
| | |
| | | * @return ç»æ |
| | | */ |
| | | @Override |
| | | @Transactional |
| | | public int changeTaskStatusWithLocation(Long taskId, TaskStatus newStatus, String remark, SysTaskLog locationLog) { |
| | | SysTask oldTask = sysTaskMapper.selectSysTaskByTaskId(taskId); |
| | | if (oldTask == null) { |
| | |
| | | .map(SysTaskAssignee::getUserId) |
| | | .collect(Collectors.toList()); |
| | | } |
| | | |
| | | Long userId=SecurityUtils.getUserId(); |
| | | Double lng=locationLog==null?null: locationLog.getLongitude(); |
| | | Double lat=locationLog==null?null: locationLog.getLatitude(); |
| | | String address=locationLog==null?null: locationLog.getLocationAddress(); |
| | | eventPublisher.publishEvent(new TaskStatusChangedEvent( |
| | | this, |
| | | oldTask.getTaskId(), |
| | |
| | | oldTaskStatus.getInfo(), |
| | | newStatus.getInfo(), |
| | | assigneeIds, |
| | | oldTask.getCreatorId() |
| | | oldTask.getCreatorId(), |
| | | userId, |
| | | lng, lat, |
| | | address |
| | | |
| | | )); |
| | | } |
| | | |
| | |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * æ£æ¥ä»»å¡æ¯å¦å¯ä»¥åºå |
| | | * æ£æ¥ï¼ |
| | | * 1. è½¦è¾æ¯å¦ææªå®æçä»»å¡ |
| | | * 2. æ§è¡äººåæ¯å¦ææªå®æçä»»å¡ |
| | | * |
| | | * @param taskId ä»»å¡ID |
| | | * @return AjaxResult æ ¡éªç»æ |
| | | */ |
| | | @Override |
| | | public com.ruoyi.common.core.domain.AjaxResult checkTaskCanDepart(Long taskId) { |
| | | // è·åä»»å¡è¯¦æ
|
| | | SysTask task = this.getTaskDetail(taskId); |
| | | if (task == null) { |
| | | return com.ruoyi.common.core.domain.AjaxResult.error("ä»»å¡ä¸åå¨"); |
| | | } |
| | | |
| | | List<Map<String, Object>> conflicts = new ArrayList<>(); |
| | | |
| | | // 1. æ£æ¥è½¦è¾æ¯å¦ææªå®æçä»»å¡ |
| | | List<SysTaskVehicle> taskVehicles = task.getAssignedVehicles(); |
| | | if (taskVehicles != null && !taskVehicles.isEmpty()) { |
| | | for (SysTaskVehicle taskVehicle : taskVehicles) { |
| | | Long vehicleId = taskVehicle.getVehicleId(); |
| | | List<SysTask> vehicleActiveTasks = this.checkVehicleActiveTasks(vehicleId); |
| | | |
| | | // è¿æ»¤æå½å任塿¬èº« |
| | | vehicleActiveTasks = vehicleActiveTasks.stream() |
| | | .filter(t -> !t.getTaskId().equals(taskId)) |
| | | .collect(Collectors.toList()); |
| | | |
| | | if (!vehicleActiveTasks.isEmpty()) { |
| | | for (SysTask activeTask : vehicleActiveTasks) { |
| | | Map<String, Object> conflict = new HashMap<>(); |
| | | conflict.put("type", "vehicle"); |
| | | conflict.put("vehicleNo", taskVehicle.getVehicleNo()); |
| | | conflict.put("taskId", activeTask.getTaskId()); |
| | | conflict.put("taskCode", activeTask.getTaskCode()); |
| | | conflict.put("taskStatus", activeTask.getTaskStatus()); |
| | | conflict.put("message", String.format("è½¦è¾ %s å°ææªå®æçä»»å¡ %sï¼è¯·å
宿", |
| | | taskVehicle.getVehicleNo(), activeTask.getTaskCode())); |
| | | conflicts.add(conflict); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | // 2. æ£æ¥æ§è¡äººåæ¯å¦ææªå®æçä»»å¡ |
| | | List<SysTaskAssignee> assignees = task.getAssignees(); |
| | | if (assignees != null && !assignees.isEmpty()) { |
| | | for (SysTaskAssignee assignee : assignees) { |
| | | Long userId = assignee.getUserId(); |
| | | |
| | | // æ¥è¯¢è¯¥æ§è¡äººçæææ£å¨è¿è¡ä¸çä»»å¡ï¼æé¤PENDINGãCOMPLETEDãCANCELLEDï¼ |
| | | List<SysTask> userActiveTasks = this.selectMyTasks(userId).stream() |
| | | .filter(t -> !TaskStatus.PENDING.getCode().equals(t.getTaskStatus()) |
| | | && !TaskStatus.COMPLETED.getCode().equals(t.getTaskStatus()) |
| | | && !TaskStatus.CANCELLED.getCode().equals(t.getTaskStatus()) |
| | | && !t.getTaskId().equals(taskId)) // è¿æ»¤æå½åä»»å¡ |
| | | .collect(Collectors.toList()); |
| | | |
| | | if (!userActiveTasks.isEmpty()) { |
| | | for (SysTask activeTask : userActiveTasks) { |
| | | Map<String, Object> conflict = new HashMap<>(); |
| | | conflict.put("type", "assignee"); |
| | | conflict.put("userName", assignee.getUserName()); |
| | | conflict.put("taskId", activeTask.getTaskId()); |
| | | conflict.put("taskCode", activeTask.getTaskCode()); |
| | | conflict.put("taskStatus", activeTask.getTaskStatus()); |
| | | conflict.put("message", String.format("æ§è¡äºº %s å°ææ£å¨è¿è¡ä¸çä»»å¡ %sï¼è¯·å
宿", |
| | | assignee.getUserName(), activeTask.getTaskCode())); |
| | | conflicts.add(conflict); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | // è¿åç»æ |
| | | Map<String, Object> result = new HashMap<>(); |
| | | result.put("valid", conflicts.isEmpty()); |
| | | result.put("conflicts", conflicts); |
| | | |
| | | return com.ruoyi.common.core.domain.AjaxResult.success(result); |
| | | } |
| | | |
| | | } |
| | |
| | | { |
| | | existingUser.setOaOrderClass(dto.getOaOrderClass()); |
| | | } |
| | | if (StringUtils.isNotEmpty(dto.getCanViewAllConsult())) |
| | | { |
| | | existingUser.setCanViewAllConsult(dto.getCanViewAllConsult()); |
| | | } |
| | | sysUserMapper.updateUser(existingUser); |
| | | } |
| | | |
| | |
| | | { |
| | | newUser.setOaOrderClass(dto.getOaOrderClass()); |
| | | } |
| | | if (StringUtils.isNotEmpty(dto.getCanViewAllConsult())) |
| | | { |
| | | newUser.setCanViewAllConsult(dto.getCanViewAllConsult()); |
| | | } |
| | | |
| | | if (deptId != null) |
| | | { |
| | |
| | | <result property="Old_ServiceOrdID_TXT" column="Old_ServiceOrdID_TXT" /> |
| | | <result property="ServiceOrdTraDistance" column="ServiceOrdTraDistance" /> |
| | | <result property="ServiceOrdApptDate" column="ServiceOrdApptDate" /> |
| | | <result property="DispatchOrdState" column="DispatchOrdState" /> |
| | | </resultMap> |
| | | |
| | | <!-- æ§è¡äººç»ææ å° --> |
| | |
| | | b.DispatchOrdActualDate, |
| | | b.DispatchOrdReturnDate, |
| | | b.DispatchOrdTraEnd, |
| | | b.DispatchOrdState, |
| | | b.DispatchOrdID, |
| | | b.DispatchOrdCarID, |
| | | a.ServiceOrdPtServices, |
| | | a.ServiceOrdPtInServices, |
| | | a.ServiceOrdPtName |
| | | FROM ServiceOrder as a |
| | | INNER JOIN DispatchOrd b on a.ServiceOrdID = b.ServiceOrdIDDt |
| | | WHERE a.ServiceOrdState = 3 |
| | | left JOIN DispatchOrd b on a.ServiceOrdID = b.ServiceOrdIDDt |
| | | WHERE a.ServiceOrdState <= 3 |
| | | AND a.ServiceOrd_CC_Time > #{startDate} |
| | | AND b.DispatchOrdState != 0 |
| | | |
| | | </select> |
| | | |
| | | <!-- æ ¹æ®æå¡åIDåè°åº¦åIDæ¥è¯¢è½¬è¿åæ°æ® --> |
| | |
| | | b.DispatchOrdCarID, |
| | | a.ServiceOrdPtServices, |
| | | a.ServiceOrdPtInServices, |
| | | a.ServiceOrdPtName |
| | | a.ServiceOrdPtName, |
| | | b.DispatchOrdState |
| | | FROM ServiceOrder as a |
| | | INNER JOIN DispatchOrd b on a.ServiceOrdID = b.ServiceOrdIDDt |
| | | left JOIN DispatchOrd b on a.ServiceOrdID = b.ServiceOrdIDDt |
| | | WHERE a.ServiceOrdID = #{serviceOrdID} |
| | | AND b.DispatchOrdID = #{dispatchOrdID} |
| | | AND a.ServiceOrdState = 3 |
| | | AND b.DispatchOrdState != 0 |
| | | AND a.ServiceOrdState <=3 |
| | | |
| | | </select> |
| | | |
| | | <!-- æ ¹æ®æå¡åIDæ¥è¯¢ç
æ
ä¿¡æ¯ --> |
| | |
| | | WHERE vID = #{deptID} AND vtitle = 'HospitalDepartment' |
| | | </select> |
| | | |
| | | <!-- æå
¥è°åº¦åç¶æåæ´è®°å½å° DispatchOrd_Running 表 --> |
| | | <insert id="insertDispatchOrdRunning"> |
| | | INSERT INTO DispatchOrd_Running ( |
| | | DispatchOrdIDDt, |
| | | DispatchOrdState, |
| | | DispatchOrdStartDate, |
| | | DispatchOrdStartOA |
| | | <if test="oaLatitude != null">,OA_latitude</if> |
| | | <if test="oaLongitude != null">,OA_longitude</if> |
| | | <if test="oaAddress != null and oaAddress != ''">,OA_address</if> |
| | | ) VALUES ( |
| | | #{dispatchOrdID}, |
| | | #{dispatchOrdState}, |
| | | #{dispatchOrdStartDate}, |
| | | #{dispatchOrdStartOA} |
| | | <if test="oaLatitude != null">,#{oaLatitude}</if> |
| | | <if test="oaLongitude != null">,#{oaLongitude}</if> |
| | | <if test="oaAddress != null and oaAddress != ''">,#{oaAddress}</if> |
| | | ) |
| | | </insert> |
| | | |
| | | </mapper> |
| | |
| | | <if test="taskStatus != null and taskStatus != ''"> and t.task_status = #{taskStatus}</if> |
| | | <if test="vehicleNo != null and vehicleNo != ''"> and v.vehicle_no like concat('%', #{vehicleNo}, '%')</if> |
| | | <!-- ç»¼åæ¥è¯¢ï¼å½åç¨æ·æå¨æºæ OR å½åç¨æ·å建 OR åé
ç»å½åç¨æ· --> |
| | | <if test="(creatorId != null and creatorId != 0) or (assigneeId != null and assigneeId != 0) or (deptId != null and deptId != 0)"> |
| | | <if test="(creatorId != null and creatorId != 0) or (assigneeId != null and assigneeId != 0) or (deptId != null and deptId != 0) or (deptIds != null and deptIds.size() > 0)"> |
| | | and ( |
| | | <if test="deptId != null and deptId != 0">t.dept_id = #{deptId}</if> |
| | | <if test="creatorId != null and creatorId != 0"> |
| | | <!-- æ¥è¯¢æå®åå
¬å¸åå
¶ææåé¨é¨çä»»å¡ --> |
| | | <if test="deptId != null and deptId != 0"> |
| | | (t.dept_id = #{deptId} OR t.dept_id IN ( |
| | | SELECT dept_id FROM sys_dept |
| | | WHERE del_flag = '0' AND find_in_set(#{deptId}, ancestors) |
| | | )) |
| | | </if> |
| | | <!-- æ¥è¯¢å¤ä¸ªåå
¬å¸åå
¶ææåé¨é¨çä»»å¡ --> |
| | | <if test="deptIds != null and deptIds.size() > 0"> |
| | | <if test="deptId != null and deptId != 0"> or </if> |
| | | ( |
| | | <foreach collection="deptIds" item="branchDeptId" separator=" OR "> |
| | | (t.dept_id = #{branchDeptId} OR t.dept_id IN ( |
| | | SELECT dept_id FROM sys_dept |
| | | WHERE del_flag = '0' AND find_in_set(#{branchDeptId}, ancestors) |
| | | )) |
| | | </foreach> |
| | | ) |
| | | </if> |
| | | <if test="creatorId != null and creatorId != 0"> |
| | | <if test="(deptId != null and deptId != 0) or (deptIds != null and deptIds.size() > 0)"> or </if> |
| | | t.creator_id = #{creatorId} |
| | | </if> |
| | | <if test="assigneeId != null and assigneeId != 0"> |
| | | <if test="(deptId != null and deptId != 0) or (creatorId != null and creatorId != 0)"> or </if> |
| | | t.assignee_id = #{assigneeId} |
| | | <if test="(deptId != null and deptId != 0) or (deptIds != null and deptIds.size() > 0) or (creatorId != null and creatorId != 0)"> or </if> |
| | | t.task_id IN ( |
| | | SELECT task_id FROM sys_task_assignee WHERE user_id = #{assigneeId} |
| | | ) |
| | | </if> |
| | | ) |
| | | </if> |
| | |
| | | |
| | | <select id="selectMyTasks" parameterType="Long" resultMap="SysTaskResult"> |
| | | <include refid="selectSysTaskVo"/> |
| | | where t.del_flag = '0' and (t.creator_id = #{userId} or t.assignee_id = #{userId}) |
| | | where t.del_flag = '0' and ( |
| | | t.creator_id = #{userId} |
| | | OR t.task_id IN ( |
| | | SELECT task_id FROM sys_task_assignee WHERE user_id = #{userId} |
| | | ) |
| | | ) |
| | | order by |
| | | CASE t.task_status |
| | | WHEN 'PENDING' THEN 1 |
| | |
| | | <result property="openId" column="open_id" /> |
| | | <result property="unionId" column="union_id" /> |
| | | <result property="wechatNickname" column="wechat_nickname" /> |
| | | <result property="canViewAllConsult" column="can_view_all_consult" /> |
| | | <association property="dept" javaType="SysDept" resultMap="deptResult" /> |
| | | <collection property="roles" javaType="java.util.List" resultMap="RoleResult" /> |
| | | </resultMap> |
| | |
| | | </resultMap> |
| | | |
| | | <sql id="selectUserVo"> |
| | | select u.user_id, u.dept_id, u.user_name,u.oa_user_id, u.oa_order_class, u.nick_name, u.email, u.avatar, u.phonenumber, u.password, u.sex, u.status, u.del_flag, u.login_ip, u.login_date, u.oa_user_id, u.create_by, u.create_time, u.remark,u.open_id,u.union_id,u.wechat_nickname, |
| | | select u.user_id, u.dept_id, u.user_name,u.oa_user_id, u.oa_order_class, u.nick_name, u.email, u.avatar, u.phonenumber, u.password, u.sex, u.status, u.del_flag, u.login_ip, u.login_date, u.oa_user_id, u.create_by, u.create_time, u.remark,u.open_id,u.union_id,u.wechat_nickname,u.can_view_all_consult, |
| | | d.dept_id, d.parent_id, d.ancestors, d.dept_name, d.order_num, d.leader, d.status as dept_status, |
| | | r.role_id, r.role_name, r.role_key, r.role_sort, r.data_scope, r.status as role_status |
| | | from sys_user u |
| | |
| | | <if test="status != null and status != ''">status,</if> |
| | | <if test="oaUserId != null">oa_user_id,</if> |
| | | <if test="oaOrderClass != null and oaOrderClass != ''">oa_order_class,</if> |
| | | <if test="canViewAllConsult != null and canViewAllConsult != ''">can_view_all_consult,</if> |
| | | <if test="createBy != null and createBy != ''">create_by,</if> |
| | | <if test="remark != null and remark != ''">remark,</if> |
| | | create_time |
| | |
| | | <if test="status != null and status != ''">#{status},</if> |
| | | <if test="oaUserId != null">#{oaUserId},</if> |
| | | <if test="oaOrderClass != null and oaOrderClass != ''">#{oaOrderClass},</if> |
| | | <if test="canViewAllConsult != null and canViewAllConsult != ''">#{canViewAllConsult},</if> |
| | | <if test="createBy != null and createBy != ''">#{createBy},</if> |
| | | <if test="remark != null and remark != ''">#{remark},</if> |
| | | sysdate() |
| | |
| | | <if test="status != null and status != ''">status = #{status},</if> |
| | | <if test="oaUserId != null">oa_user_id = #{oaUserId},</if> |
| | | <if test="oaOrderClass != null">oa_order_class = #{oaOrderClass},</if> |
| | | <if test="canViewAllConsult != null and canViewAllConsult != ''">can_view_all_consult = #{canViewAllConsult},</if> |
| | | <if test="openId != null and openId != ''">open_id = #{openId},</if> |
| | | <if test="unionId != null and unionId != ''">union_id = #{unionId},</if> |
| | | <if test="loginIp != null and loginIp != ''">login_ip = #{loginIp},</if> |
| | |
| | | <result property="email" column="email" /> |
| | | <result property="phonenumber" column="phonenumber" /> |
| | | <result property="oaOrderClass" column="OA_OrderClass" /> |
| | | <result property="canViewAllConsult" column="can_view_all_consult" /> |
| | | </resultMap> |
| | | |
| | | <!-- æ¥è¯¢SQL Serverä¸çOAç¨æ·å表 --> |
| | |
| | | OA_gender AS sex, |
| | | OA_email AS email, |
| | | OA_mobile AS phonenumber, |
| | | OA_OrderClass AS OA_OrderClass |
| | | OA_OrderClass AS OA_OrderClass, |
| | | CASE |
| | | WHEN OA_Power LIKE '%,020112,%' THEN '1' |
| | | ELSE '0' |
| | | END AS can_view_all_consult |
| | | FROM OA_User |
| | | WHERE OA_User IS NOT NULL |
| | | AND OA_Name IS NOT NULL |
| | |
| | | </el-row> |
| | | <el-row> |
| | | <el-col :span="12"> |
| | | <el-form-item label="æ¥çææå¨è¯¢å"> |
| | | <el-radio-group v-model="form.canViewAllConsult"> |
| | | <el-radio label="0">å¦</el-radio> |
| | | <el-radio label="1">æ¯</el-radio> |
| | | </el-radio-group> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å²ä½"> |
| | | <el-select v-model="form.postIds" multiple placeholder="è¯·éæ©å²ä½"> |
| | | <el-option v-for="item in postOptions" :key="item.postId" :label="item.postName" :value="item.postId" :disabled="item.status == 1" ></el-option> |
| | |
| | | status: "0", |
| | | remark: undefined, |
| | | postIds: [], |
| | | roleIds: [] |
| | | roleIds: [], |
| | | canViewAllConsult: "0" |
| | | }; |
| | | this.resetForm("form"); |
| | | }, |
| New file |
| | |
| | | create table DispatchOrd_Running( |
| | | id int comment "èªå¢ä¸»é®", |
| | | DispatchOrdIDDt bigint comment 'è°åº¦åID', |
| | | DispatchOrdState int comment 'ç¶æ', |
| | | DispatchOrdStartDate datetime comment 'ç¶ææ¶é´', |
| | | DispatchOrdStartOA int comment 'æä½ç¶æçOAç¨æ·ID', |
| | | OA_latitude float comment 'æ´æ°ç¶ææ¶ç纬度', |
| | | OA_longitude float comment 'æ´æ°ç¶ææ¶çç»åº¦', |
| | | OA_address nvarchar(400) comment 'æ´æ°ç¶ææ¶çå°å' |
| | | ) |
| New file |
| | |
| | | -- æ·»å sys_userè¡¨åæ®µï¼æ¯å¦å¯ä»¥æ¥ç管çé¨é¨çææå¨è¯¢å |
| | | -- æ§è¡æ¶é´: 2025-12-04 |
| | | -- åè½è¯´æ: ç¨äºæ è¯ç¨æ·æ¯å¦æ¥ææ¥çå
¶ç®¡çé¨é¨ææå¨è¯¢åçæé |
| | | |
| | | -- æ·»å åæ®µ |
| | | ALTER TABLE `sys_user` ADD COLUMN `can_view_all_consult` CHAR(1) DEFAULT '0' COMMENT 'æ¯å¦å¯æ¥çææå¨è¯¢åï¼0å¦ 1æ¯ï¼' AFTER `wechat_nickname`; |
| | | |
| | | -- 说æ |
| | | -- 1. can_view_all_consult: æ è¯ç¨æ·æ¯å¦å¯ä»¥æ¥ç管çé¨é¨çææå¨è¯¢å |
| | | -- 2. é»è®¤å¼ä¸º '0'ï¼å¦ï¼ï¼è¡¨ç¤ºæ®éç¨æ· |
| | | -- 3. å¼ä¸º '1'ï¼æ¯ï¼è¡¨ç¤ºè¯¥ç¨æ·ææ¥çææå¨è¯¢åçæé |
| | | -- 4. 该æéä¸OAç³»ç»ä¸çOA_Poweråæ®µå
³èï¼å
å«',020112,'è¡¨ç¤ºæ¥æè¯¥æé |