From fd047fa7234dc11643dab8ecbf38e8d7a8ba0854 Mon Sep 17 00:00:00 2001
From: wlzboy <66905212@qq.com>
Date: 星期六, 22 十一月 2025 23:48:12 +0800
Subject: [PATCH] feat:修改任务
---
app/mixins/distanceCalculator.js | 141 +
app/api/task.js | 2
app/pages/task/edit-welfare.vue | 569 +++++
app/pages/task/edit-emergency.vue | 1015 +++++++++
app/pages.json | 15
app/components/OrganizationSelector.vue | 215 ++
app/pages/task/create-emergency.vue | 1177 ----------
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTaskServiceImpl.java | 164 +
/dev/null | 113 -
app/components/HospitalSelector.vue | 586 +++++
app/pages/task/create-normal.vue | 451 +++-
app/components/DiseaseSelector.vue | 471 ++++
ruoyi-system/src/main/resources/areacode.json | 0
app/pages/task/edit.vue | 520 ++++
ruoyi-system/src/main/resources/mapper/system/SysTaskMapper.xml | 8
ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/TaskUpdateVO.java | 326 +++
app/components/VehicleSelector.vue | 214 ++
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/VehicleGpsController.java | 55
app/components/TaskTypeSelector.vue | 181 +
app/api/map.js | 4
app/pages/task/detail.vue | 91
21 files changed, 4,952 insertions(+), 1,366 deletions(-)
diff --git a/app/api/map.js b/app/api/map.js
index bf9cc31..163ff1d 100644
--- a/app/api/map.js
+++ b/app/api/map.js
@@ -249,7 +249,7 @@
})
}
-// 澶╁湴鍥惧湴鍧�鎼滅储鎻愮ずAPI锛堣緭鍏ヨ仈鎯筹級
+// 澶╁湴鍥炬櫘閫氭悳绱㈡湇鍔PI锛堝湴鍧�鎼滅储锛�
export function tiandituPlaceSuggestion(keyWord, region, city, count) {
// 鍙傛暟楠岃瘉
if (!keyWord) {
@@ -266,4 +266,4 @@
count: count || 10
}
})
-}
\ No newline at end of file
+}
diff --git a/app/api/task.js b/app/api/task.js
index 3121d97..258c34e 100644
--- a/app/api/task.js
+++ b/app/api/task.js
@@ -26,7 +26,7 @@
export function updateTask(data) {
return request({
- url: '/task/' + data.taskId,
+ url: '/task',
method: 'put',
data: data
})
diff --git a/app/components/DiseaseSelector.vue b/app/components/DiseaseSelector.vue
new file mode 100644
index 0000000..f61cb6a
--- /dev/null
+++ b/app/components/DiseaseSelector.vue
@@ -0,0 +1,471 @@
+<template>
+ <view class="disease-selector">
+ <view class="form-item">
+ <view class="form-label" :class="{ required: required }" v-if="showLabel">{{ label }}</view>
+ <view class="disease-container">
+ <view class="disease-tags" v-if="selectedDiseases.length > 0">
+ <view
+ class="disease-tag"
+ v-for="(disease, index) in selectedDiseases"
+ :key="index"
+ >
+ <text class="disease-name">{{ disease.icdName }}</text>
+ <uni-icons
+ type="closeempty"
+ size="16"
+ color="#fff"
+ @click="removeDisease(index)"
+ ></uni-icons>
+ </view>
+ </view>
+ <view class="add-disease-btn" @click="showSelector">
+ <uni-icons type="plusempty" size="20" color="#007AFF"></uni-icons>
+ <text>娣诲姞鐥呮儏</text>
+ </view>
+ <textarea
+ v-if="showOtherDescription"
+ class="form-textarea"
+ placeholder="鍏朵粬鐥呮儏鎻忚堪锛堥�夊~锛�"
+ :value="otherDescription"
+ @input="onOtherDescriptionInput"
+ style="margin-top: 20rpx;"
+ />
+ </view>
+ </view>
+
+ <!-- 鐥呮儏閫夋嫨寮圭獥 -->
+ <uni-popup ref="diseasePopup" type="bottom" :safe-area="true">
+ <view class="disease-selector-popup">
+ <view class="popup-header">
+ <view class="popup-title">閫夋嫨鐥呮儏锛圛CD-10锛�</view>
+ <view class="popup-close" @click="closeSelector">
+ <uni-icons type="closeempty" size="24" color="#333"></uni-icons>
+ </view>
+ </view>
+
+ <view class="search-box">
+ <uni-icons type="search" size="18" color="#999"></uni-icons>
+ <input
+ class="search-input"
+ placeholder="鎼滅储鐤剧梾鍚嶇О銆佺紪鐮佹垨鍔╄鐮�"
+ v-model="diseaseSearchKeyword"
+ @input="onDiseaseSearch"
+ />
+ </view>
+
+ <scroll-view class="disease-list-popup" scroll-y="true">
+ <view
+ class="disease-item-popup"
+ v-for="disease in diseaseSearchResults"
+ :key="disease.id"
+ @click="toggleDiseaseSelection(disease)"
+ >
+ <view class="disease-info">
+ <view class="disease-name-row">
+ <text class="disease-name">{{ disease.icdName }}</text>
+ <text class="disease-code">[{{ disease.icdCode }}]</text>
+ </view>
+ <view class="disease-detail-row" v-if="disease.sm">
+ <text class="disease-desc">{{ disease.sm }}</text>
+ </view>
+ </view>
+ <uni-icons
+ v-if="isDiseaseSelected(disease.id)"
+ type="checkmarkempty"
+ size="24"
+ color="#007AFF"
+ ></uni-icons>
+ <view v-else class="checkbox-empty"></view>
+ </view>
+
+ <view class="no-data" v-if="diseaseSearchResults.length === 0">
+ <uni-icons type="info" size="40" color="#ccc"></uni-icons>
+ <text>{{ diseaseSearchKeyword ? '鏈壘鍒扮浉鍏崇柧鐥�' : '鏆傛棤鐥呮儏鏁版嵁' }}</text>
+ </view>
+ </scroll-view>
+
+ <view class="popup-footer">
+ <button class="cancel-btn" @click="closeSelector">鍙栨秷</button>
+ <button class="confirm-btn" @click="confirmSelection">纭畾(宸查�墈{ tempSelectedDiseases.length }})</button>
+ </view>
+ </view>
+ </uni-popup>
+ </view>
+</template>
+
+<script>
+import uniPopup from '@/uni_modules/uni-popup/components/uni-popup/uni-popup.vue'
+import { searchIcd10 } from "@/api/icd10"
+
+export default {
+ name: 'DiseaseSelector',
+ components: {
+ uniPopup
+ },
+ props: {
+ // 鏍囩鏂囨湰
+ label: {
+ type: String,
+ default: '鐥呮儏'
+ },
+ // 鏄惁鏄剧ず鏍囩
+ showLabel: {
+ type: Boolean,
+ default: true
+ },
+ // 鏄惁蹇呭~
+ required: {
+ type: Boolean,
+ default: false
+ },
+ // 宸查�夋嫨鐨勭梾鎯呭垪琛�
+ value: {
+ type: Array,
+ default: () => []
+ },
+ // 鍏朵粬鐥呮儏鎻忚堪
+ otherDescription: {
+ type: String,
+ default: ''
+ },
+ // 鏄惁鏄剧ず鍏朵粬鐥呮儏鎻忚堪妗�
+ showOtherDescription: {
+ type: Boolean,
+ default: true
+ }
+ },
+ data() {
+ return {
+ selectedDiseases: [],
+ tempSelectedDiseases: [],
+ diseaseSearchKeyword: '',
+ diseaseSearchResults: [],
+ diseaseSearchTimer: null
+ }
+ },
+ watch: {
+ value: {
+ immediate: true,
+ handler(newVal) {
+ if (newVal && Array.isArray(newVal)) {
+ this.selectedDiseases = [...newVal]
+ }
+ }
+ }
+ },
+ methods: {
+ // 鏄剧ず鐥呮儏閫夋嫨寮圭獥
+ showSelector() {
+ // 鍒濆鍖栦复鏃堕�夋嫨鍒楄〃锛堝鍒跺綋鍓嶅凡閫夋嫨鐨勭梾鎯咃級
+ this.tempSelectedDiseases = [...this.selectedDiseases]
+ this.diseaseSearchKeyword = ''
+ // 榛樿鍔犺浇鎵�鏈夌梾鎯�
+ this.loadAllDiseases()
+ this.$refs.diseasePopup.open()
+ },
+
+ // 鍏抽棴鐥呮儏閫夋嫨寮圭獥
+ closeSelector() {
+ this.$refs.diseasePopup.close()
+ this.diseaseSearchKeyword = ''
+ this.diseaseSearchResults = []
+ this.tempSelectedDiseases = []
+ },
+
+ // 鐥呮儏鎼滅储
+ onDiseaseSearch(e) {
+ const keyword = e.detail.value
+ this.diseaseSearchKeyword = keyword
+
+ // 闃叉姈澶勭悊
+ if (this.diseaseSearchTimer) {
+ clearTimeout(this.diseaseSearchTimer)
+ }
+
+ // 濡傛灉鍏抽敭璇嶄负绌猴紝鍔犺浇鎵�鏈夌梾鎯�
+ if (!keyword || keyword.trim() === '') {
+ this.loadAllDiseases()
+ return
+ }
+
+ // 鏈夊叧閿瘝鏃惰繘琛屾悳绱�
+ this.diseaseSearchTimer = setTimeout(() => {
+ this.searchDiseaseByKeyword(keyword)
+ }, 300)
+ },
+
+ // 鍔犺浇鎵�鏈夌梾鎯咃紙榛樿鏄剧ず锛�
+ loadAllDiseases() {
+ searchIcd10('').then(response => {
+ this.diseaseSearchResults = response.data || []
+ }).catch(error => {
+ console.error('鍔犺浇鐥呮儏鍒楄〃澶辫触:', error)
+ this.diseaseSearchResults = []
+ })
+ },
+
+ // 鏍规嵁鍏抽敭璇嶆悳绱㈢梾鎯�
+ searchDiseaseByKeyword(keyword) {
+ searchIcd10(keyword).then(response => {
+ this.diseaseSearchResults = response.data || []
+ }).catch(error => {
+ console.error('鎼滅储鐥呮儏澶辫触:', error)
+ this.diseaseSearchResults = []
+ })
+ },
+
+ // 鍒囨崲鐥呮儏閫変腑鐘舵��
+ toggleDiseaseSelection(disease) {
+ const index = this.tempSelectedDiseases.findIndex(d => d.id === disease.id)
+
+ if (index > -1) {
+ // 宸查�変腑锛岀Щ闄�
+ this.tempSelectedDiseases.splice(index, 1)
+ } else {
+ // 鏈�変腑锛屾坊鍔�
+ this.tempSelectedDiseases.push({
+ id: disease.id,
+ icdCode: disease.icdCode,
+ icdName: disease.icdName,
+ sm: disease.sm
+ })
+ }
+ },
+
+ // 鍒ゆ柇鐥呮儏鏄惁宸查�変腑
+ isDiseaseSelected(diseaseId) {
+ return this.tempSelectedDiseases.some(d => d.id === diseaseId)
+ },
+
+ // 纭鐥呮儏閫夋嫨
+ confirmSelection() {
+ // 灏嗕复鏃堕�夋嫨鐨勭梾鎯呭鍒跺埌姝e紡鍒楄〃
+ this.selectedDiseases = [...this.tempSelectedDiseases]
+ this.$emit('input', this.selectedDiseases)
+ this.$emit('change', this.selectedDiseases)
+ this.closeSelector()
+ },
+
+ // 绉婚櫎鐥呮儏
+ removeDisease(index) {
+ this.selectedDiseases.splice(index, 1)
+ this.$emit('input', this.selectedDiseases)
+ this.$emit('change', this.selectedDiseases)
+ },
+
+ // 鍏朵粬鐥呮儏鎻忚堪杈撳叆
+ onOtherDescriptionInput(e) {
+ const value = e.detail.value
+ this.$emit('update:otherDescription', value)
+ this.$emit('other-description-change', value)
+ }
+ }
+}
+</script>
+
+<style lang="scss" scoped>
+.disease-selector {
+ .form-item {
+ margin-bottom: 40rpx;
+
+ .form-label {
+ font-size: 28rpx;
+ margin-bottom: 15rpx;
+ color: #333;
+
+ &.required::before {
+ content: '*';
+ color: #ff4d4f;
+ margin-right: 4rpx;
+ font-weight: bold;
+ }
+ }
+
+ .disease-container {
+ .disease-tags {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 15rpx;
+ margin-bottom: 20rpx;
+
+ .disease-tag {
+ display: flex;
+ align-items: center;
+ padding: 10rpx 20rpx;
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+ border-radius: 30rpx;
+
+ .disease-name {
+ font-size: 26rpx;
+ color: white;
+ margin-right: 10rpx;
+ }
+ }
+ }
+
+ .add-disease-btn {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ padding: 20rpx;
+ border: 1rpx dashed #007AFF;
+ border-radius: 10rpx;
+ color: #007AFF;
+ font-size: 28rpx;
+
+ text {
+ margin-left: 10rpx;
+ }
+ }
+
+ .form-textarea {
+ width: 100%;
+ min-height: 150rpx;
+ padding: 20rpx;
+ border: 1rpx solid #eee;
+ border-radius: 10rpx;
+ font-size: 28rpx;
+ }
+ }
+ }
+}
+
+// 鐥呮儏閫夋嫨寮圭獥鏍峰紡
+.disease-selector-popup {
+ background-color: white;
+ border-radius: 20rpx 20rpx 0 0;
+ max-height: 80vh;
+ display: flex;
+ flex-direction: column;
+
+ .popup-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 30rpx;
+ border-bottom: 1rpx solid #f0f0f0;
+ flex-shrink: 0;
+
+ .popup-title {
+ font-size: 32rpx;
+ font-weight: bold;
+ color: #333;
+ }
+
+ .popup-close {
+ padding: 10rpx;
+ }
+ }
+
+ .search-box {
+ display: flex;
+ align-items: center;
+ margin: 20rpx 30rpx;
+ padding: 15rpx 20rpx;
+ background-color: #f5f5f5;
+ border-radius: 10rpx;
+ flex-shrink: 0;
+
+ .search-input {
+ flex: 1;
+ margin-left: 10rpx;
+ font-size: 28rpx;
+ }
+ }
+
+ .disease-list-popup {
+ flex: 1;
+ overflow-y: auto;
+ padding: 0 30rpx;
+
+ .disease-item-popup {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 25rpx 20rpx;
+ border-bottom: 1rpx solid #f0f0f0;
+
+ &:active {
+ background-color: #f5f5f5;
+ }
+
+ .disease-info {
+ flex: 1;
+
+ .disease-name-row {
+ display: flex;
+ align-items: center;
+ margin-bottom: 8rpx;
+
+ .disease-name {
+ font-size: 30rpx;
+ font-weight: bold;
+ color: #333;
+ margin-right: 15rpx;
+ }
+
+ .disease-code {
+ font-size: 24rpx;
+ color: #007AFF;
+ background-color: #e6f2ff;
+ padding: 4rpx 12rpx;
+ border-radius: 6rpx;
+ }
+ }
+
+ .disease-detail-row {
+ .disease-desc {
+ font-size: 24rpx;
+ color: #999;
+ line-height: 1.5;
+ }
+ }
+ }
+
+ .checkbox-empty {
+ width: 40rpx;
+ height: 40rpx;
+ border: 2rpx solid #ddd;
+ border-radius: 50%;
+ }
+ }
+
+ .no-data {
+ text-align: center;
+ padding: 100rpx 0;
+ color: #999;
+
+ text {
+ display: block;
+ margin-top: 20rpx;
+ font-size: 28rpx;
+ }
+ }
+ }
+
+ .popup-footer {
+ display: flex;
+ padding: 20rpx 30rpx;
+ border-top: 1rpx solid #f0f0f0;
+ gap: 20rpx;
+ flex-shrink: 0;
+
+ button {
+ flex: 1;
+ height: 80rpx;
+ border-radius: 10rpx;
+ font-size: 30rpx;
+ }
+
+ .cancel-btn {
+ background-color: #f5f5f5;
+ color: #666;
+ }
+
+ .confirm-btn {
+ background-color: #007AFF;
+ color: white;
+ }
+ }
+}
+</style>
diff --git a/app/components/HospitalSelector.vue b/app/components/HospitalSelector.vue
new file mode 100644
index 0000000..77ff0f3
--- /dev/null
+++ b/app/components/HospitalSelector.vue
@@ -0,0 +1,586 @@
+<template>
+ <view class="hospital-selector">
+ <view class="form-item">
+ <view class="form-label" :class="{ required: required }" v-if="showLabel">{{ label }}</view>
+ <view class="hospital-search-container">
+ <input
+ class="form-input"
+ :placeholder="placeholder"
+ v-model="searchKeyword"
+ @input="onSearch"
+ @focus="onFocus"
+ />
+ <view class="search-results" v-if="showResults && searchResults.length > 0">
+ <view
+ class="search-result-item"
+ v-for="hospital in searchResults"
+ :key="hospital.hospId"
+ @click="selectHospital(hospital)"
+ >
+ <view class="hospital-name">
+ {{ hospital.hospName }}
+ <text class="hospital-short" v-if="hospital.hospShort">{{ hospital.hospShort }}</text>
+ </view>
+ <view class="hospital-address">{{ buildFullAddress(hospital) }}</view>
+ </view>
+ </view>
+ </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 === '瀹朵腑'">
+ <input
+ class="form-input"
+ placeholder="璇疯緭鍏ヨ缁嗗湴鍧�"
+ :value="addressValue"
+ @input="onAddressInput"
+ @focus="onAddressFocus"
+ />
+ <view class="address-suggestions" v-if="showAddressSuggestions && addressSuggestions.length > 0">
+ <view
+ class="address-suggestion-item"
+ v-for="(item, index) in addressSuggestions"
+ :key="index"
+ @click="selectAddressSuggestion(item)"
+ >
+ <view class="suggestion-name">{{ item.name }}</view>
+ <view class="suggestion-address">{{ item.district }}{{ item.address }}</view>
+ </view>
+ </view>
+ </view>
+ <view v-else class="form-input picker-input disabled">
+ {{ addressValue || '閫夋嫨鍖婚櫌鍚庤嚜鍔ㄥ~鍏�' }}
+ </view>
+ </view>
+ </view>
+</template>
+
+<script>
+import { searchHospitals } from "@/api/hospital"
+import { baiduPlaceSuggestion } from "@/api/map"
+
+export default {
+ name: 'HospitalSelector',
+ props: {
+ // 鏍囩鏂囨湰
+ label: {
+ type: String,
+ default: '鍖婚櫌鍚嶇О'
+ },
+ // 鏄惁鏄剧ず鏍囩
+ showLabel: {
+ type: Boolean,
+ default: true
+ },
+ // 鏄惁蹇呭~
+ required: {
+ type: Boolean,
+ default: false
+ },
+ // 鍦板潃鏍囩
+ addressLabel: {
+ type: String,
+ default: '鍖婚櫌鍦板潃'
+ },
+ // 鍗犱綅绗�
+ placeholder: {
+ type: String,
+ default: '璇疯緭鍏ュ尰闄㈠悕绉版垨鍦板潃鎼滅储'
+ },
+ // 褰撳墠閫変腑鐨勫尰闄俊鎭�
+ value: {
+ type: Object,
+ default: () => ({
+ id: null,
+ name: '',
+ department: '',
+ departmentId: null,
+ bedNumber: '',
+ 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],
+ default: null
+ },
+ // 褰撳墠鍖哄煙锛堢敤浜庡湴鍧�鎼滅储锛�
+ region: {
+ type: String,
+ default: '骞垮窞'
+ }
+ },
+ data() {
+ return {
+ searchKeyword: '',
+ searchResults: [],
+ showResults: false,
+ searchTimer: null,
+ selectedHospitalName: '',
+ // 鍦板潃寤鸿鐩稿叧
+ addressSuggestions: [],
+ showAddressSuggestions: false,
+ addressSearchTimer: null,
+ // 榛樿鍖婚櫌鍒楄〃锛堢敤浜庨娆″姞杞斤級
+ defaultHospitals: [],
+ hasLoadedDefault: false // 鏍囪鏄惁宸插姞杞借繃榛樿鍒楄〃
+ }
+ },
+ computed: {
+ addressValue() {
+ return this.value.address || ''
+ },
+ departmentValue() {
+ return this.value.department || ''
+ },
+ bedNumberValue() {
+ return this.value.bedNumber || ''
+ }
+ },
+ watch: {
+ 'value.name': {
+ immediate: true,
+ handler(newVal) {
+ if (newVal) {
+ this.searchKeyword = newVal
+ this.selectedHospitalName = newVal
+ }
+ }
+ },
+ // 鐩戝惉 deptId 鍙樺寲锛屾竻闄ゅ凡鍔犺浇鐨勯粯璁ゅ垪琛紙浣嗕笉鑷姩鍔犺浇锛�
+ deptId(newVal, oldVal) {
+ if (newVal !== oldVal && newVal) {
+ this.hasLoadedDefault = false
+ this.defaultHospitals = []
+ // 涓嶈嚜鍔ㄥ姞杞斤紝绛夊緟鐢ㄦ埛鐐瑰嚮杈撳叆妗嗘椂鍐嶅姞杞�
+ }
+ }
+ },
+ methods: {
+ // 鎼滅储杈撳叆鐩戝惉
+ onSearch(e) {
+ const keyword = e.detail.value
+ this.searchKeyword = keyword
+
+ if (this.searchTimer) {
+ clearTimeout(this.searchTimer)
+ }
+
+ if (!keyword || keyword.trim() === '') {
+ // 鍏抽敭璇嶄负绌烘椂锛屾樉绀洪粯璁ゅ尰闄㈠垪琛�
+ if (this.defaultHospitals.length > 0) {
+ this.searchResults = this.defaultHospitals
+ this.showResults = true
+ } else {
+ this.searchResults = []
+ this.showResults = false
+ }
+ return
+ }
+
+ // 闃叉姈澶勭悊
+ this.searchTimer = setTimeout(() => {
+ this.searchHospital(keyword)
+ }, 300)
+ },
+
+ // 鎼滅储鍖婚櫌
+ searchHospital(keyword) {
+ searchHospitals(keyword, this.deptId).then(response => {
+ this.searchResults = response.data || []
+ this.showResults = true
+ }).catch(error => {
+ console.error('鎼滅储鍖婚櫌澶辫触:', error)
+ this.searchResults = []
+ })
+ },
+
+ // 杈撳叆妗嗚幏寰楃劍鐐�
+ onFocus() {
+ // 濡傛灉宸茬粡鏈夋悳绱㈢粨鏋滐紝鐩存帴鏄剧ず
+ if (this.searchResults.length > 0) {
+ this.showResults = true
+ return
+ }
+
+ // 濡傛灉杩樻病鏈夊姞杞借繃榛樿鍖婚櫌鍒楄〃锛屽垯鍔犺浇
+ if (!this.hasLoadedDefault) {
+ this.loadDefaultHospitals()
+ } else if (this.defaultHospitals.length > 0) {
+ // 濡傛灉宸茬粡鍔犺浇杩囷紝鐩存帴鏄剧ず榛樿鍒楄〃
+ this.searchResults = this.defaultHospitals
+ this.showResults = true
+ }
+ },
+
+ // 鍔犺浇榛樿鍖婚櫌鍒楄〃
+ loadDefaultHospitals() {
+ searchHospitals('', this.deptId).then(response => {
+ this.defaultHospitals = response.data || []
+ this.searchResults = this.defaultHospitals
+ this.showResults = true
+ this.hasLoadedDefault = true
+ console.log('鍔犺浇榛樿鍖婚櫌鍒楄〃锛屾暟閲�:', this.defaultHospitals.length)
+ }).catch(error => {
+ console.error('鍔犺浇榛樿鍖婚櫌鍒楄〃澶辫触:', error)
+ this.defaultHospitals = []
+ })
+ },
+
+ // 閫夋嫨鍖婚櫌
+ selectHospital(hospital) {
+ this.selectedHospitalName = hospital.hospName
+ this.searchKeyword = hospital.hospName
+
+ 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.searchResults = []
+
+ // 瑙﹀彂鏇存柊浜嬩欢
+ this.$emit('input', hospitalData)
+ this.$emit('change', hospitalData)
+ },
+
+ // 鍚堝苟鍖婚櫌鍦板潃锛堢渷 + 甯� + 鍖� + 璇︾粏鍦板潃锛�
+ buildFullAddress(hospital) {
+ const parts = []
+ if (hospital.hopsProvince) {
+ parts.push(hospital.hopsProvince)
+ }
+ if (hospital.hopsCity) {
+ parts.push(hospital.hopsCity)
+ }
+ if (hospital.hopsArea) {
+ parts.push(hospital.hopsArea)
+ }
+ if (hospital.hospAddress) {
+ parts.push(hospital.hospAddress)
+ }
+ return parts.join('')
+ },
+
+ // 鍦板潃杈撳叆锛堜粎鍦ㄩ�夋嫨鈥滃涓�濇椂鍙敤锛�
+ onAddressInput(e) {
+ const address = e.detail.value
+ this.$emit('input', {
+ ...this.value,
+ address: address
+ })
+ this.$emit('address-change', address)
+
+ // 闃叉姈澶勭悊鍦板潃鎼滅储
+ if (this.addressSearchTimer) {
+ clearTimeout(this.addressSearchTimer)
+ }
+
+ if (!address || address.trim() === '') {
+ this.addressSuggestions = []
+ this.showAddressSuggestions = false
+ return
+ }
+
+ this.addressSearchTimer = setTimeout(() => {
+ this.searchAddress(address)
+ }, 300)
+ },
+
+ // 鎼滅储鍦板潃寤鸿
+ searchAddress(query) {
+ baiduPlaceSuggestion(query, this.region).then(response => {
+ if (response.code === 200 && response.data) {
+ this.addressSuggestions = response.data
+ this.showAddressSuggestions = true
+ } else {
+ this.addressSuggestions = []
+ this.showAddressSuggestions = false
+ }
+ }).catch(error => {
+ console.error('鎼滅储鍦板潃澶辫触:', error)
+ this.addressSuggestions = []
+ this.showAddressSuggestions = false
+ })
+ },
+
+ // 鍦板潃杈撳叆妗嗚幏寰楃劍鐐�
+ onAddressFocus() {
+ if (this.addressValue && this.addressSuggestions.length > 0) {
+ this.showAddressSuggestions = true
+ }
+ },
+
+ // 閫夋嫨鍦板潃寤鸿
+ selectAddressSuggestion(item) {
+ const fullAddress = item.district + item.address
+ this.$emit('input', {
+ ...this.value,
+ address: fullAddress
+ })
+ this.$emit('address-selected', {
+ address: fullAddress,
+ location: item.location
+ })
+
+ this.showAddressSuggestions = false
+ this.addressSuggestions = []
+ },
+
+ // 绉戝閫夋嫨鍙樺寲锛坧icker锛�
+ 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)
+ }
+ }
+}
+</script>
+
+<style lang="scss" scoped>
+.hospital-selector {
+ .form-item {
+ margin-bottom: 40rpx;
+
+ .form-label {
+ font-size: 28rpx;
+ margin-bottom: 15rpx;
+ color: #333;
+
+ &.required::before {
+ content: '*';
+ color: #ff0000;
+ margin-right: 5rpx;
+ }
+ }
+
+ .hospital-search-container {
+ position: relative;
+
+ .form-input {
+ width: 100%;
+ height: 70rpx;
+ padding: 0 20rpx;
+ border: 1rpx solid #eee;
+ border-radius: 10rpx;
+ font-size: 28rpx;
+ box-sizing: border-box;
+ }
+
+ .search-results {
+ position: absolute;
+ top: 75rpx;
+ left: 0;
+ right: 0;
+ max-height: 400rpx;
+ overflow-y: auto;
+ background-color: white;
+ border: 1rpx solid #eee;
+ border-radius: 10rpx;
+ box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.1);
+ z-index: 100;
+
+ .search-result-item {
+ padding: 20rpx;
+ border-bottom: 1rpx solid #f0f0f0;
+
+ &:last-child {
+ border-bottom: none;
+ }
+
+ &:active {
+ background-color: #f5f5f5;
+ }
+
+ .hospital-name {
+ font-size: 28rpx;
+ color: #333;
+ margin-bottom: 8rpx;
+
+ .hospital-short {
+ margin-left: 10rpx;
+ font-size: 24rpx;
+ color: #999;
+ }
+ }
+
+ .hospital-address {
+ font-size: 24rpx;
+ color: #999;
+ }
+ }
+ }
+ }
+
+ .address-input-container {
+ position: relative;
+
+ .form-input {
+ width: 100%;
+ height: 70rpx;
+ padding: 0 20rpx;
+ border: 1rpx solid #eee;
+ border-radius: 10rpx;
+ font-size: 28rpx;
+ box-sizing: border-box;
+ }
+
+ .address-suggestions {
+ position: absolute;
+ top: 75rpx;
+ left: 0;
+ right: 0;
+ max-height: 400rpx;
+ overflow-y: auto;
+ background-color: white;
+ border: 1rpx solid #eee;
+ border-radius: 10rpx;
+ box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.1);
+ z-index: 100;
+
+ .address-suggestion-item {
+ padding: 20rpx;
+ border-bottom: 1rpx solid #f0f0f0;
+
+ &:last-child {
+ border-bottom: none;
+ }
+
+ &:active {
+ background-color: #f5f5f5;
+ }
+
+ .suggestion-name {
+ font-size: 28rpx;
+ color: #333;
+ margin-bottom: 8rpx;
+ }
+
+ .suggestion-address {
+ font-size: 24rpx;
+ color: #999;
+ }
+ }
+ }
+ }
+
+ .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>
diff --git a/app/components/OrganizationSelector.vue b/app/components/OrganizationSelector.vue
new file mode 100644
index 0000000..9371f8f
--- /dev/null
+++ b/app/components/OrganizationSelector.vue
@@ -0,0 +1,215 @@
+<template>
+ <view class="organization-selector">
+ <view class="form-label" :class="{ required: required }" v-if="showLabel">{{ label }}</view>
+ <picker
+ mode="selector"
+ :range="organizations"
+ :value="selectedIndex"
+ @change="onOrganizationChange"
+ :disabled="disabled"
+ >
+ <view class="form-input picker-input" :class="{ disabled: disabled }">
+ {{ displayText }}
+ <uni-icons type="arrowright" size="16" color="#999"></uni-icons>
+ </view>
+ </picker>
+ </view>
+</template>
+
+<script>
+import { listBranchCompany } from "@/api/system/dept"
+import { mapState } from 'vuex'
+
+export default {
+ name: 'OrganizationSelector',
+ props: {
+ // 鏍囩鏂囨湰
+ label: {
+ type: String,
+ default: '褰掑睘鏈烘瀯'
+ },
+ // 鏄惁鏄剧ず鏍囩
+ showLabel: {
+ type: Boolean,
+ default: true
+ },
+ // 鏄惁蹇呭~
+ required: {
+ type: Boolean,
+ default: false
+ },
+ // 褰撳墠閫変腑鐨勫綊灞炴満鏋処D
+ value: {
+ type: [Number, String],
+ default: null
+ },
+ // 鍗犱綅绗�
+ placeholder: {
+ type: String,
+ default: '璇烽�夋嫨褰掑睘鏈烘瀯'
+ },
+ // 鏄惁绂佺敤
+ disabled: {
+ type: Boolean,
+ default: false
+ },
+ // 鏄惁鑷姩閫夋嫨褰撳墠鐢ㄦ埛鐨勫垎鍏徃
+ autoSelectUserDept: {
+ type: Boolean,
+ default: true
+ }
+ },
+ data() {
+ return {
+ organizations: [],
+ organizationOptions: [],
+ selectedIndex: -1
+ }
+ },
+ computed: {
+ ...mapState({
+ currentUser: state => ({
+ branchCompanyId: state.user.branchCompanyId,
+ branchCompanyName: state.user.branchCompanyName
+ })
+ }),
+ displayText() {
+ if (this.selectedIndex >= 0 && this.selectedIndex < this.organizations.length) {
+ return this.organizations[this.selectedIndex]
+ }
+ return this.placeholder
+ }
+ },
+ watch: {
+ value: {
+ immediate: true,
+ handler(newVal) {
+ if (newVal && this.organizationOptions.length > 0) {
+ const index = this.organizationOptions.findIndex(org => org.deptId === newVal)
+ this.selectedIndex = index
+ }
+ }
+ }
+ },
+ mounted() {
+ this.loadOrganizations()
+ },
+ methods: {
+ // 鍔犺浇鍒嗗叕鍙告暟鎹紙parent_id=100鐨勯儴闂級
+ loadOrganizations() {
+ return listBranchCompany().then(response => {
+ // console.log('鍔犺浇鍒嗗叕鍙告暟鎹�:', response.data);
+ const list = response.data || []
+ // 杩囨护鍑� parent_id = 100 鐨勯儴闂紙鍒嗗叕鍙革級
+ this.organizationOptions = list.filter(dept => dept.parentId == "100")
+ // 鐢熸垚picker鐨勬暟鎹簮锛堝彧鏄剧ず鍚嶇О锛�
+ this.organizations = this.organizationOptions.map(dept => dept.deptName)
+
+ // 鑷姩閫夋嫨鐢ㄦ埛鐨勫垎鍏徃
+ if (this.autoSelectUserDept && !this.value && this.currentUser.branchCompanyName) {
+ this.selectUserBranchCompany()
+ } else if (this.value) {
+ // 濡傛灉鏈変紶鍏ョ殑value锛岃缃�変腑绱㈠紩
+ const index = this.organizationOptions.findIndex(org => org.deptId === this.value)
+ this.selectedIndex = index
+ }
+
+ return this.organizationOptions
+ }).catch(error => {
+ console.error('鍔犺浇鍒嗗叕鍙告暟鎹け璐�:', error)
+ this.organizations = []
+ this.organizationOptions = []
+ return []
+ })
+ },
+
+ // 閫夋嫨鐢ㄦ埛鎵�灞炵殑鍒嗗叕鍙�
+ selectUserBranchCompany() {
+ if (!this.currentUser.branchCompanyName) {
+ return
+ }
+
+ const index = this.organizationOptions.findIndex(
+ dept => dept.deptName === this.currentUser.branchCompanyName
+ )
+
+ if (index !== -1) {
+ this.selectedIndex = index
+ this.emitChange(this.organizationOptions[index])
+ }
+ },
+
+ // 褰掑睘鏈烘瀯閫夋嫨鍙樺寲
+ onOrganizationChange(e) {
+ const index = e.detail.value
+ this.selectedIndex = index
+ const selectedOrg = this.organizationOptions[index]
+ this.emitChange(selectedOrg)
+ },
+
+ // 瑙﹀彂浜嬩欢
+ emitChange(organization) {
+ if (organization) {
+ // 鎻愬彇鍦板煙鍏抽敭璇嶏紙鍘婚櫎"鍒嗗叕鍙�"銆�"鎬诲叕鍙�"銆�"鎬婚儴"鍚庣紑锛�
+ const region = organization.deptName.replace(/(鍒嗗叕鍙竱鎬诲叕鍙竱鎬婚儴)$/g, '').trim()
+
+ this.$emit('input', organization.deptId)
+ this.$emit('change', {
+ deptId: organization.deptId,
+ deptName: organization.deptName,
+ serviceOrderClass: organization.serviceOrderClass || '',
+ region: region
+ })
+ }
+ },
+
+ // 閲嶆柊鍔犺浇褰掑睘鏈烘瀯鍒楄〃锛堜緵澶栭儴璋冪敤锛�
+ reload() {
+ return this.loadOrganizations()
+ },
+
+ // 鑾峰彇褰撳墠閫変腑鐨勭粍缁囦俊鎭紙渚涘閮ㄨ皟鐢級
+ getSelectedOrganization() {
+ if (this.selectedIndex >= 0 && this.selectedIndex < this.organizationOptions.length) {
+ return this.organizationOptions[this.selectedIndex]
+ }
+ return null
+ }
+ }
+}
+</script>
+
+<style lang="scss" scoped>
+.organization-selector {
+ .form-label {
+ font-size: 28rpx;
+ margin-bottom: 15rpx;
+ color: #333;
+
+ &.required::before {
+ content: '*';
+ color: #ff0000;
+ margin-right: 5rpx;
+ }
+ }
+
+ .form-input {
+ height: 70rpx;
+ padding: 0 20rpx;
+ border: 1rpx solid #eee;
+ border-radius: 10rpx;
+ font-size: 28rpx;
+
+ &.picker-input {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ }
+
+ &.disabled {
+ background-color: #f5f5f5;
+ color: #999;
+ }
+ }
+}
+</style>
diff --git a/app/components/TaskTypeSelector.vue b/app/components/TaskTypeSelector.vue
new file mode 100644
index 0000000..b821c68
--- /dev/null
+++ b/app/components/TaskTypeSelector.vue
@@ -0,0 +1,181 @@
+<template>
+ <view class="task-type-selector">
+ <view class="form-label" v-if="label">{{ label }}</view>
+ <picker
+ mode="selector"
+ :range="taskTypeLabels"
+ :value="selectedIndex"
+ @change="onTaskTypeChange"
+ :disabled="disabled"
+ >
+ <view class="form-input picker-input" :class="{ disabled: disabled }">
+ {{ displayText }}
+ <uni-icons type="arrowright" size="16" color="#999"></uni-icons>
+ </view>
+ </picker>
+ </view>
+</template>
+
+<script>
+import { getDicts } from "@/api/dict"
+
+export default {
+ name: 'TaskTypeSelector',
+ props: {
+ // 鏍囩鏂囨湰
+ label: {
+ type: String,
+ default: '浠诲姟绫诲瀷'
+ },
+ // 褰撳墠閫変腑鐨勪换鍔$被鍨嬪��
+ value: {
+ type: String,
+ default: ''
+ },
+ // 瀛楀吀绫诲瀷锛坰ys_task_type锛�
+ dictType: {
+ type: String,
+ default: 'sys_task_type'
+ },
+ // 鍗犱綅绗�
+ placeholder: {
+ type: String,
+ default: '璇烽�夋嫨浠诲姟绫诲瀷'
+ },
+ // 鏄惁绂佺敤
+ disabled: {
+ type: Boolean,
+ default: false
+ },
+ // 杩囨护鏉′欢锛堝彲閫夛級- 鍙樉绀虹壒瀹氱殑浠诲姟绫诲瀷
+ filter: {
+ type: Array,
+ default: () => []
+ }
+ },
+ data() {
+ return {
+ taskTypeOptions: [],
+ taskTypeLabels: [],
+ selectedIndex: -1
+ }
+ },
+ computed: {
+ displayText() {
+ if (this.selectedIndex >= 0 && this.selectedIndex < this.taskTypeLabels.length) {
+ return this.taskTypeLabels[this.selectedIndex]
+ }
+ return this.placeholder
+ }
+ },
+ watch: {
+ value: {
+ immediate: true,
+ handler(newVal) {
+ if (newVal && this.taskTypeOptions.length > 0) {
+ const index = this.taskTypeOptions.findIndex(item => item.value === newVal)
+ this.selectedIndex = index
+ }
+ }
+ }
+ },
+ mounted() {
+ this.loadTaskTypes()
+ },
+ methods: {
+ // 鍔犺浇浠诲姟绫诲瀷瀛楀吀
+ loadTaskTypes() {
+ return getDicts(this.dictType).then(response => {
+ const dictData = response.data || []
+ let options = dictData.map(item => ({
+ label: item.dictLabel,
+ value: item.dictValue
+ }))
+
+ // 濡傛灉鏈夎繃婊ゆ潯浠讹紝鍙繚鐣欐寚瀹氱殑绫诲瀷
+ if (this.filter && this.filter.length > 0) {
+ options = options.filter(item => this.filter.includes(item.value))
+ }
+
+ this.taskTypeOptions = options
+ this.taskTypeLabels = options.map(item => item.label)
+
+ // 濡傛灉鏈夐璁惧�硷紝璁剧疆閫変腑绱㈠紩
+ if (this.value) {
+ const index = this.taskTypeOptions.findIndex(item => item.value === this.value)
+ this.selectedIndex = index
+ }
+
+ return options
+ }).catch(error => {
+ console.error('鍔犺浇浠诲姟绫诲瀷瀛楀吀澶辫触:', error)
+ // 浣跨敤榛樿鍊�
+ this.taskTypeOptions = [
+ { label: '缁翠慨淇濆吇', value: 'MAINTENANCE' },
+ { label: '鍔犳补浠诲姟', value: 'FUEL' },
+ { label: '鍏朵粬', value: 'OTHER' }
+ ]
+ this.taskTypeLabels = this.taskTypeOptions.map(item => item.label)
+ return this.taskTypeOptions
+ })
+ },
+
+ // 浠诲姟绫诲瀷閫夋嫨鍙樺寲
+ onTaskTypeChange(e) {
+ const index = e.detail.value
+ this.selectedIndex = index
+ const selectedOption = this.taskTypeOptions[index]
+
+ if (selectedOption) {
+ this.$emit('input', selectedOption.value)
+ this.$emit('change', {
+ value: selectedOption.value,
+ label: selectedOption.label
+ })
+ }
+ },
+
+ // 閲嶆柊鍔犺浇浠诲姟绫诲瀷锛堜緵澶栭儴璋冪敤锛�
+ reload() {
+ return this.loadTaskTypes()
+ },
+
+ // 鑾峰彇褰撳墠閫変腑鐨勪换鍔$被鍨嬪璞�
+ getSelected() {
+ if (this.selectedIndex >= 0 && this.selectedIndex < this.taskTypeOptions.length) {
+ return this.taskTypeOptions[this.selectedIndex]
+ }
+ return null
+ }
+ }
+}
+</script>
+
+<style lang="scss" scoped>
+.task-type-selector {
+ .form-label {
+ font-size: 28rpx;
+ margin-bottom: 15rpx;
+ color: #333;
+ }
+
+ .form-input {
+ height: 70rpx;
+ padding: 0 20rpx;
+ border: 1rpx solid #eee;
+ border-radius: 10rpx;
+ font-size: 28rpx;
+
+ &.picker-input {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ }
+
+ &.disabled {
+ background-color: #f5f5f5;
+ color: #999;
+ }
+ }
+}
+</style>
diff --git a/app/components/VehicleSelector.vue b/app/components/VehicleSelector.vue
new file mode 100644
index 0000000..c52797a
--- /dev/null
+++ b/app/components/VehicleSelector.vue
@@ -0,0 +1,214 @@
+<template>
+ <view class="vehicle-selector">
+ <view class="form-label" v-if="label">{{ label }}</view>
+ <picker
+ mode="selector"
+ :range="vehicles"
+ :value="selectedIndex"
+ @change="onVehicleChange"
+ :disabled="disabled"
+ >
+ <view class="form-input picker-input" :class="{ disabled: disabled }">
+ {{ displayText }}
+ <uni-icons type="arrowright" size="16" color="#999"></uni-icons>
+ </view>
+ </picker>
+ </view>
+</template>
+
+<script>
+import { listAvailableVehicles, getUserBoundVehicle } from "@/api/vehicle"
+
+export default {
+ name: 'VehicleSelector',
+ props: {
+ // 鏍囩鏂囨湰
+ label: {
+ type: String,
+ default: '浠诲姟杞﹁締'
+ },
+ // 褰撳墠閫変腑鐨勮溅杈咺D
+ value: {
+ type: [Number, String],
+ default: null
+ },
+ // 杞﹁締绫诲瀷杩囨护锛圙ENERAL/EMERGENCY/WELFARE锛�
+ vehicleType: {
+ type: String,
+ default: 'GENERAL'
+ },
+ // 閮ㄩ棬ID
+ deptId: {
+ type: [Number, String],
+ default: null
+ },
+ // 鍗犱綅绗�
+ placeholder: {
+ type: String,
+ default: '璇烽�夋嫨浠诲姟杞﹁締'
+ },
+ // 鏄惁绂佺敤
+ disabled: {
+ type: Boolean,
+ default: false
+ },
+ // 鏄惁鑷姩閫夋嫨缁戝畾杞﹁締
+ autoSelectBound: {
+ type: Boolean,
+ default: true
+ }
+ },
+ data() {
+ return {
+ vehicles: [],
+ vehicleOptions: [],
+ selectedIndex: -1
+ }
+ },
+ computed: {
+ displayText() {
+ if (this.selectedIndex >= 0 && this.selectedIndex < this.vehicles.length) {
+ return this.vehicles[this.selectedIndex]
+ }
+ return this.placeholder
+ }
+ },
+ watch: {
+ value: {
+ immediate: true,
+ handler(newVal) {
+ if (newVal && this.vehicleOptions.length > 0) {
+ const index = this.vehicleOptions.findIndex(v => v.id === newVal)
+ this.selectedIndex = index
+ }
+ }
+ },
+ deptId: {
+ immediate: true,
+ handler(newVal) {
+ if (newVal) {
+ this.loadVehicles()
+ }
+ }
+ }
+ },
+ mounted() {
+ if (this.deptId) {
+ this.loadVehicles()
+ }
+ },
+ methods: {
+ // 鍔犺浇杞﹁締鍒楄〃
+ loadVehicles() {
+ if (!this.deptId) {
+ console.warn('VehicleSelector: deptId is required')
+ return Promise.reject('deptId is required')
+ }
+
+ return listAvailableVehicles(this.deptId, this.vehicleType).then(response => {
+ const vehicleList = response.data || response.rows || []
+ this.vehicleOptions = vehicleList.map(vehicle => ({
+ id: vehicle.vehicleId,
+ name: vehicle.vehicleNo,
+ type: vehicle.vehicleType,
+ status: vehicle.status
+ }))
+ this.vehicles = this.vehicleOptions.map(v => v.name)
+
+ // 鑷姩閫夋嫨缁戝畾杞﹁締
+ if (this.autoSelectBound && !this.value) {
+ this.selectBoundVehicle()
+ } else if (this.value) {
+ // 濡傛灉鏈変紶鍏ョ殑value锛岃缃�変腑绱㈠紩
+ const index = this.vehicleOptions.findIndex(v => v.id === this.value)
+ this.selectedIndex = index
+ }
+
+ return vehicleList
+ }).catch(error => {
+ console.error('鍔犺浇杞﹁締鍒楄〃澶辫触:', error)
+ this.vehicles = []
+ this.vehicleOptions = []
+ return []
+ })
+ },
+
+ // 閫夋嫨缁戝畾鐨勮溅杈�
+ selectBoundVehicle() {
+ getUserBoundVehicle().then(response => {
+ const userInfo = response.data || response
+ if (userInfo.boundVehicle) {
+ const boundVehicleNo = userInfo.boundVehicle.vehicleNumber
+ const boundVehicleId = userInfo.boundVehicle.vehicleId
+
+ const vehicleIndex = this.vehicleOptions.findIndex(v =>
+ v.id === boundVehicleId || v.name === boundVehicleNo
+ )
+
+ if (vehicleIndex !== -1) {
+ this.selectedIndex = vehicleIndex
+ this.emitChange(this.vehicleOptions[vehicleIndex])
+ }
+ }
+ }).catch(error => {
+ console.error('鑾峰彇鐢ㄦ埛缁戝畾杞﹁締澶辫触:', error)
+ })
+ },
+
+ // 杞﹁締閫夋嫨鍙樺寲
+ onVehicleChange(e) {
+ const index = e.detail.value
+ this.selectedIndex = index
+ const selectedVehicle = this.vehicleOptions[index]
+ this.emitChange(selectedVehicle)
+ },
+
+ // 瑙﹀彂浜嬩欢
+ emitChange(vehicle) {
+ if (vehicle) {
+ this.$emit('input', vehicle.id)
+ this.$emit('change', {
+ vehicleId: vehicle.id,
+ vehicleName: vehicle.name,
+ vehicleType: vehicle.type,
+ vehicleStatus: vehicle.status
+ })
+ }
+ },
+
+ // 閲嶆柊鍔犺浇杞﹁締鍒楄〃锛堜緵澶栭儴璋冪敤锛�
+ reload() {
+ return this.loadVehicles()
+ }
+ }
+}
+</script>
+
+<style lang="scss" scoped>
+.vehicle-selector {
+ .form-label {
+ font-size: 28rpx;
+ margin-bottom: 15rpx;
+ color: #333;
+ }
+
+ .form-input {
+ height: 70rpx;
+ padding: 0 20rpx;
+ border: 1rpx solid #eee;
+ border-radius: 10rpx;
+ font-size: 28rpx;
+
+ &.picker-input {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ }
+
+ &.disabled {
+ background-color: #f5f5f5;
+ color: #999;
+ }
+ }
+}
+</style>
diff --git a/app/mixins/distanceCalculator.js b/app/mixins/distanceCalculator.js
new file mode 100644
index 0000000..71ef59a
--- /dev/null
+++ b/app/mixins/distanceCalculator.js
@@ -0,0 +1,141 @@
+/**
+ * 璺濈璁$畻 Mixin
+ * 鎻愪緵鍦板潃閫夋嫨鍜岃窛绂昏嚜鍔ㄨ绠楀姛鑳�
+ */
+import { calculateDistance } from "@/api/map"
+
+export default {
+ data() {
+ return {
+ // 鍦板潃鍧愭爣瀛樺偍
+ addressCoordinates: {
+ start: null,
+ end: null
+ },
+ // 褰撳墠姝e湪閫夋嫨鐨勫湴鍧�绫诲瀷
+ currentAddressType: '',
+ // 璁$畻鍑虹殑璺濈
+ calculatedDistance: null
+ }
+ },
+ methods: {
+ /**
+ * 璁剧疆璧风偣鍧愭爣
+ * @param {Object} location - 浣嶇疆瀵硅薄 { lat, lng }
+ */
+ setStartLocation(location) {
+ this.addressCoordinates.start = location
+ this.autoCalculateDistance()
+ },
+
+ /**
+ * 璁剧疆缁堢偣鍧愭爣
+ * @param {Object} location - 浣嶇疆瀵硅薄 { lat, lng }
+ */
+ setEndLocation(location) {
+ this.addressCoordinates.end = location
+ this.autoCalculateDistance()
+ },
+
+ /**
+ * 閫氳繃鍦板潃閫夋嫨缁撴灉璁剧疆鍧愭爣
+ * @param {String} type - 鍦板潃绫诲瀷 'start' 鎴� 'end'
+ * @param {Object} address - 鍦板潃瀵硅薄 { title, address, lat, lng }
+ */
+ setLocationByAddress(type, address) {
+ const location = {
+ lat: address.lat,
+ lng: address.lng
+ }
+
+ if (type === 'start') {
+ this.setStartLocation(location)
+ } else if (type === 'end') {
+ this.setEndLocation(location)
+ }
+
+ return location
+ },
+
+ /**
+ * 鑷姩璁$畻璺濈锛堝綋璧风偣鍜岀粓鐐归兘瀛樺湪鏃讹級
+ */
+ autoCalculateDistance() {
+ if (this.addressCoordinates.start && this.addressCoordinates.end) {
+ return this.getDistanceBetweenPoints(
+ this.addressCoordinates.start.lat,
+ this.addressCoordinates.start.lng,
+ this.addressCoordinates.end.lat,
+ this.addressCoordinates.end.lng
+ ).then(distance => {
+ this.calculatedDistance = distance
+ // 瑙﹀彂璺濈璁$畻瀹屾垚浜嬩欢
+ this.$emit && this.$emit('distance-calculated', distance)
+ return distance
+ }).catch(error => {
+ console.error('璺濈璁$畻澶辫触:', error)
+ return null
+ })
+ }
+ return Promise.resolve(null)
+ },
+
+ /**
+ * 璁$畻涓ょ偣涔嬮棿鐨勮窛绂伙紙鍏噷锛�
+ * @param {Number} lat1 - 璧风偣绾害
+ * @param {Number} lng1 - 璧风偣缁忓害
+ * @param {Number} lat2 - 缁堢偣绾害
+ * @param {Number} lng2 - 缁堢偣缁忓害
+ * @returns {Promise<Number>} 璺濈锛堝叕閲岋級
+ */
+ getDistanceBetweenPoints(lat1, lng1, lat2, lng2) {
+ return new Promise((resolve, reject) => {
+ calculateDistance(lat1, lng1, lat2, lng2).then(response => {
+ if (response.code === 200) {
+ const responseData = typeof response.data === 'string'
+ ? JSON.parse(response.data)
+ : response.data
+
+ if (responseData &&
+ responseData.status === 0 &&
+ responseData.result &&
+ responseData.result.elements &&
+ responseData.result.elements.length > 0) {
+ const distanceInKm = responseData.result.elements[0].distance / 1000
+ resolve(distanceInKm)
+ } else {
+ reject(new Error('璺濈璁$畻鎺ュ彛杩斿洖鏁版嵁鏍煎紡涓嶆纭�'))
+ }
+ } else {
+ reject(new Error('璺濈璁$畻鎺ュ彛璋冪敤澶辫触'))
+ }
+ }).catch(error => {
+ reject(error)
+ })
+ })
+ },
+
+ /**
+ * 娓呯┖鍦板潃鍧愭爣
+ */
+ clearAddressCoordinates() {
+ this.addressCoordinates = {
+ start: null,
+ end: null
+ }
+ this.calculatedDistance = null
+ },
+
+ /**
+ * 鏍煎紡鍖栬窛绂绘樉绀猴紙淇濈暀2浣嶅皬鏁帮級
+ * @param {Number} distance - 璺濈鍊�
+ * @returns {String} 鏍煎紡鍖栧悗鐨勮窛绂�
+ */
+ formatDistance(distance) {
+ if (distance === null || distance === undefined) {
+ return ''
+ }
+ return parseFloat(distance).toFixed(2)
+ }
+ }
+}
diff --git a/app/pages.json b/app/pages.json
index 6aa3977..8685365 100644
--- a/app/pages.json
+++ b/app/pages.json
@@ -121,6 +121,21 @@
"navigationBarTitleText": "浠诲姟璇︽儏"
}
}, {
+ "path": "pages/task/edit",
+ "style": {
+ "navigationBarTitleText": "缂栬緫浠诲姟"
+ }
+ }, {
+ "path": "pages/task/edit-emergency",
+ "style": {
+ "navigationBarTitleText": "缂栬緫杞繍浠诲姟"
+ }
+ }, {
+ "path": "pages/task/edit-welfare",
+ "style": {
+ "navigationBarTitleText": "缂栬緫绂忕杞︿换鍔�"
+ }
+ }, {
"path": "pages/task/settlement",
"style": {
"navigationBarTitleText": "浠诲姟缁撶畻"
diff --git a/app/pages/task/create-emergency.vue b/app/pages/task/create-emergency.vue
index 6cd7631..ef16aec 100644
--- a/app/pages/task/create-emergency.vue
+++ b/app/pages/task/create-emergency.vue
@@ -22,13 +22,12 @@
</picker>
</view>
<view class="form-item">
- <view class="form-label required">褰掑睘鏈烘瀯</view>
- <picker mode="selector" :range="organizations" @change="onOrganizationChange">
- <view class="form-input picker-input">
- {{ selectedOrganization || '璇烽�夋嫨褰掑睘鏈烘瀯' }}
- <uni-icons type="arrowright" size="16" color="#999"></uni-icons>
- </view>
- </picker>
+ <OrganizationSelector
+ v-model="selectedOrganizationId"
+ :required="true"
+ :auto-select-user-dept="true"
+ @change="onOrganizationChange"
+ />
</view>
<view class="form-item">
@@ -144,200 +143,38 @@
/>
</view>
- <view class="form-item">
- <view class="form-label">鐥呮儏</view>
- <view class="disease-container">
- <view class="disease-tags" v-if="selectedDiseases.length > 0">
- <view
- class="disease-tag"
- v-for="(disease, index) in selectedDiseases"
- :key="index"
- >
- <text class="disease-name">{{ disease.icdName }}</text>
- <uni-icons
- type="closeempty"
- size="16"
- color="#fff"
- @click="removeDisease(index)"
- ></uni-icons>
- </view>
- </view>
- <view class="add-disease-btn" @click="showDiseaseSelector">
- <uni-icons type="plusempty" size="20" color="#007AFF"></uni-icons>
- <text>娣诲姞鐥呮儏</text>
- </view>
- <textarea
- class="form-textarea"
- placeholder="鍏朵粬鐥呮儏鎻忚堪锛堥�夊~锛�"
- v-model="taskForm.patient.condition"
- style="margin-top: 20rpx;"
- />
- </view>
- </view>
+ <DiseaseSelector
+ v-model="selectedDiseases"
+ :other-description.sync="taskForm.patient.condition"
+ />
<view class="form-section-title">杞嚭鍖婚櫌淇℃伅</view>
- <view class="form-item">
- <view class="form-label required">鍖婚櫌鍚嶇О</view>
- <view class="hospital-search-container">
- <input
- class="form-input"
- placeholder="璇疯緭鍏ュ尰闄㈠悕绉版垨鍦板潃鎼滅储"
- v-model="hospitalOutSearchKeyword"
- @input="onHospitalOutSearch"
- @focus="onHospitalOutFocus"
- />
- <view class="search-results" v-if="showHospitalOutResults && hospitalOutResults.length > 0">
- <view
- class="search-result-item"
- v-for="hospital in hospitalOutResults"
- :key="hospital.hospId"
- @click="selectHospitalOut(hospital)"
- >
- <view class="hospital-name">
- {{ hospital.hospName }}
- <text class="hospital-short" v-if="hospital.hospShort">{{ hospital.hospShort }}</text>
- </view>
- <view class="hospital-address">{{ buildFullAddress(hospital) }}</view>
- </view>
- </view>
- </view>
- </view>
-
- <view class="form-item">
- <view class="form-label required">绉戝</view>
- <picker
- v-if="taskForm.hospitalOut.name !== '瀹朵腑'"
- mode="selector"
- :range="departmentOptions"
- range-key="text"
- @change="onHospitalOutDepartmentChange"
- >
- <view class="form-input picker-input">
- {{ taskForm.hospitalOut.department || '璇烽�夋嫨绉戝' }}
- <uni-icons type="arrowright" size="16" color="#999"></uni-icons>
- </view>
- </picker>
- <view v-else class="form-input picker-input disabled">
- 鍏跺畠
- </view>
- </view>
-
- <view class="form-item">
- <view class="form-label">搴婂彿</view>
- <input
- class="form-input"
- placeholder="璇疯緭鍏ュ簥鍙�"
- v-model="taskForm.hospitalOut.bedNumber"
- />
- </view>
-
- <view class="form-item">
- <view class="form-label">杞嚭鍦板潃</view>
- <view class="address-input-container" v-if="taskForm.hospitalOut.name === '瀹朵腑'">
- <input
- class="form-input"
- placeholder="璇疯緭鍏ヨ缁嗗湴鍧�"
- v-model="taskForm.hospitalOut.address"
- @input="onAddressOutInput"
- @focus="onAddressOutFocus"
- />
- <view class="address-suggestions" v-if="showAddressOutSuggestions && addressOutSuggestions.length > 0">
- <view
- class="address-suggestion-item"
- v-for="(item, index) in addressOutSuggestions"
- :key="index"
- @click="selectAddressOut(item)">
- <view class="suggestion-name">{{ item.name }}</view>
- <view class="suggestion-address">{{ item.district }}{{ item.address }}</view>
- </view>
- </view>
- </view>
- <view v-else class="form-input picker-input disabled">
- {{ taskForm.hospitalOut.address || '閫夋嫨鍖婚櫌鍚庤嚜鍔ㄥ~鍏�' }}
- </view>
- </view>
+ <HospitalSelector
+ label="鍖婚櫌鍚嶇О"
+ address-label="杞嚭鍦板潃"
+ :required="true"
+ :department-required="true"
+ v-model="taskForm.hospitalOut"
+ :dept-id="selectedOrganizationId"
+ :region="selectedRegion"
+ :department-options="departmentOptions"
+ @change="onHospitalOutChange"
+ @address-selected="onHospitalOutAddressSelected"
+ />
<view class="form-section-title">杞叆鍖婚櫌淇℃伅</view>
- <view class="form-item">
- <view class="form-label required">鍖婚櫌鍚嶇О</view>
- <view class="hospital-search-container">
- <input
- class="form-input"
- placeholder="璇疯緭鍏ュ尰闄㈠悕绉版垨鍦板潃鎼滅储"
- v-model="hospitalInSearchKeyword"
- @input="onHospitalInSearch"
- @focus="onHospitalInFocus"
- />
- <view class="search-results" v-if="showHospitalInResults && hospitalInResults.length > 0">
- <view
- class="search-result-item"
- v-for="hospital in hospitalInResults"
- :key="hospital.hospId"
- @click="selectHospitalIn(hospital)"
- >
- <view class="hospital-name">
- {{ hospital.hospName }}
- <text class="hospital-short" v-if="hospital.hospShort">{{ hospital.hospShort }}</text>
- </view>
- <view class="hospital-address">{{ buildFullAddress(hospital) }}</view>
- </view>
- </view>
- </view>
- </view>
-
- <view class="form-item">
- <view class="form-label required">绉戝</view>
- <picker
- v-if="taskForm.hospitalIn.name !== '瀹朵腑'"
- mode="selector"
- :range="departmentOptions"
- range-key="text"
- @change="onHospitalInDepartmentChange"
- >
- <view class="form-input picker-input">
- {{ taskForm.hospitalIn.department || '璇烽�夋嫨绉戝' }}
- <uni-icons type="arrowright" size="16" color="#999"></uni-icons>
- </view>
- </picker>
- <view v-else class="form-input picker-input disabled">
- 鍏跺畠
- </view>
- </view>
-
- <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>
- <view class="address-input-container" v-if="taskForm.hospitalIn.name === '瀹朵腑'">
- <input
- class="form-input"
- placeholder="璇疯緭鍏ヨ缁嗗湴鍧�"
- v-model="taskForm.hospitalIn.address"
- @input="onAddressInInput"
- @focus="onAddressInFocus"
- />
- <view class="address-suggestions" v-if="showAddressInSuggestions && addressInSuggestions.length > 0">
- <view
- class="address-suggestion-item"
- v-for="(item, index) in addressInSuggestions"
- :key="index"
- @click="selectAddressIn(item)">
- <view class="suggestion-name">{{ item.name }}</view>
- <view class="suggestion-address">{{ item.district }}{{ item.address }}</view>
- </view>
- </view>
- </view>
- <view v-else class="form-input picker-input disabled">
- {{ taskForm.hospitalIn.address || '閫夋嫨鍖婚櫌鍚庤嚜鍔ㄥ~鍏�' }}
- </view>
- </view>
+ <HospitalSelector
+ label="鍖婚櫌鍚嶇О"
+ address-label="杞叆鍦板潃"
+ :required="true"
+ :department-required="true"
+ v-model="taskForm.hospitalIn"
+ :dept-id="selectedOrganizationId"
+ :region="selectedRegion"
+ :department-options="departmentOptions"
+ @change="onHospitalInChange"
+ @address-selected="onHospitalInAddressSelected"
+ />
<view class="form-item">
<view class="form-label required">杞繍鍏噷鏁�</view>
@@ -475,64 +312,6 @@
</view>
</view>
</uni-popup>
-
- <!-- 鐥呮儏閫夋嫨寮圭獥 -->
- <uni-popup ref="diseasePopup" type="bottom" :safe-area="true">
- <view class="disease-selector-popup">
- <view class="popup-header">
- <view class="popup-title">閫夋嫨鐥呮儏锛圛CD-10锛�</view>
- <view class="popup-close" @click="closeDiseaseSelector">
- <uni-icons type="closeempty" size="24" color="#333"></uni-icons>
- </view>
- </view>
-
- <view class="search-box">
- <uni-icons type="search" size="18" color="#999"></uni-icons>
- <input
- class="search-input"
- placeholder="鎼滅储鐤剧梾鍚嶇О銆佺紪鐮佹垨鍔╄鐮�"
- v-model="diseaseSearchKeyword"
- @input="onDiseaseSearch"
- />
- </view>
-
- <scroll-view class="disease-list-popup" scroll-y="true">
- <view
- class="disease-item-popup"
- v-for="disease in diseaseSearchResults"
- :key="disease.id"
- @click="toggleDiseaseSelection(disease)"
- >
- <view class="disease-info">
- <view class="disease-name-row">
- <text class="disease-name">{{ disease.icdName }}</text>
- <text class="disease-code">[{{ disease.icdCode }}]</text>
- </view>
- <view class="disease-detail-row" v-if="disease.sm">
- <text class="disease-desc">{{ disease.sm }}</text>
- </view>
- </view>
- <uni-icons
- v-if="isDiseaseSelected(disease.id)"
- type="checkmarkempty"
- size="24"
- color="#007AFF"
- ></uni-icons>
- <view v-else class="checkbox-empty"></view>
- </view>
-
- <view class="no-data" v-if="diseaseSearchResults.length === 0">
- <uni-icons type="info" size="40" color="#ccc"></uni-icons>
- <text>{{ diseaseSearchKeyword ? '鏈壘鍒扮浉鍏崇柧鐥�' : '鏆傛棤鐥呮儏鏁版嵁' }}</text>
- </view>
- </scroll-view>
-
- <view class="popup-footer">
- <button class="cancel-btn" @click="closeDiseaseSelector">鍙栨秷</button>
- <button class="confirm-btn" @click="confirmDiseaseSelection">纭畾(宸查�墈{ tempSelectedDiseases.length }})</button>
- </view>
- </view>
- </uni-popup>
</scroll-view>
</template>
@@ -553,18 +332,23 @@
import { getServiceOrdAreaTypes, getServiceOrderTypes, getHospitalDepartments } 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'
export default {
components: {
uniDatetimePicker,
uniPopup,
- MapSelector
+ MapSelector,
+ OrganizationSelector,
+ HospitalSelector,
+ DiseaseSelector
},
data() {
return {
selectedVehicle: '',
selectedVehicleId: null,
- selectedOrganization: '',
selectedOrganizationId: null, // 褰掑睘鏈烘瀯ID锛堥儴闂↖D锛�
selectedOrganizationServiceOrderClass: '', // 褰掑睘鏈烘瀯鐨勬湇鍔″崟缂栫爜
selectedRegion: '', // 浠庡綊灞炴満鏋勪腑鎻愬彇鐨勫湴鍩熶俊鎭紙濡傦細骞垮窞銆佹繁鍦崇瓑锛�
@@ -573,21 +357,6 @@
selectedDocumentType: '', // 閫変腑鐨勫崟鎹被鍨嬫枃鏈�
selectedDocumentTypeId: null, // 閫変腑鐨勫崟鎹被鍨婭D
mapSelectorType: '',
- // 鍖婚櫌鎼滅储鐩稿叧
- hospitalOutSearchKeyword: '',
- hospitalOutResults: [],
- showHospitalOutResults: false,
- hospitalInSearchKeyword: '',
- hospitalInResults: [],
- showHospitalInResults: false,
- searchTimer: null,
- defaultHospitals: [], // 榛樿鐨�100鏉″尰闄㈡暟鎹�
- // 鍦板潃鎼滅储鎻愮ず鐩稿叧
- addressOutSuggestions: [], // 杞嚭鍦板潃鎻愮ず鍒楄〃
- showAddressOutSuggestions: false,
- addressInSuggestions: [], // 杞叆鍦板潃鎻愮ず鍒楄〃
- showAddressInSuggestions: false,
- addressSearchTimer: null, // 鍦板潃鎼滅储闃叉姈瀹氭椂鍣�
// 浜哄憳閫夋嫨鐩稿叧
selectedStaff: [], // 宸查�夋嫨鐨勪汉鍛樺垪琛�
allStaffList: [], // 鎵�鏈変汉鍛樺垪琛�
@@ -596,10 +365,6 @@
staffFilterType: 'driver', // 浜哄憳绛涢�夌被鍨嬶細driver/doctor/nurse锛岄粯璁ら�変腑鍙告満
// 鐥呮儏閫夋嫨鐩稿叧
selectedDiseases: [], // 宸查�夋嫨鐨勭梾鎯呭垪琛�
- tempSelectedDiseases: [], // 涓存椂閫夋嫨鐨勭梾鎯呭垪琛紙鐢ㄤ簬寮圭獥锛�
- diseaseSearchKeyword: '', // 鐥呮儏鎼滅储鍏抽敭璇�
- diseaseSearchResults: [], // 鐥呮儏鎼滅储缁撴灉
- diseaseSearchTimer: null, // 鐥呮儏鎼滅储闃叉姈瀹氭椂鍣�
taskForm: {
transferTime: '',
patient: {
@@ -631,8 +396,7 @@
},
vehicles: [],
vehicleOptions: [],
- organizations: [], // 褰掑睘鏈烘瀯鍒楄〃锛堜粠鍚庡彴鍔犺浇鍒嗗叕鍙告暟鎹級
- organizationOptions: [], // 褰掑睘鏈烘瀯閫夐」锛堢敤浜巔icker鏄剧ず锛�
+
emergencyTaskTypes: [], // 浠诲姟绫诲瀷鍒楄〃锛堜粠 SQL Server 鍔ㄦ�佸姞杞斤級
emergencyTaskTypeOptions: [], // 浠诲姟绫诲瀷閫夐」锛堢敤浜巔icker鏄剧ず锛�
documentTypes: [], // 鍗曟嵁绫诲瀷鍒楄〃
@@ -680,8 +444,6 @@
})
this.initSelectedStaff()
this.loadDeptStaff()
- // 鍔犺浇鍒嗗叕鍙告暟鎹紙浼氳嚜鍔ㄨ缃粯璁ゅ垎鍏徃骞跺姞杞藉尰闄㈠垪琛級
- this.loadBranchCompanies()
// 鍔犺浇绉戝瀛楀吀鏁版嵁
this.loadDepartments()
// 鍔犺浇浠诲姟绫诲瀷鏁版嵁
@@ -754,53 +516,17 @@
this.selectedVehicleId = this.vehicleOptions[index]?.id
},
- onOrganizationChange(e) {
- const index = e.detail.value
- const selected = this.organizationOptions[index]
- this.selectedOrganization = selected.deptName
- this.selectedOrganizationId = selected.deptId // 淇濆瓨閮ㄩ棬ID
- this.selectedOrganizationServiceOrderClass = selected.serviceOrderClass || '' // 淇濆瓨鏈嶅姟鍗曠紪鐮�
- // 浠庡綊灞炴満鏋勪腑鎻愬彇鍦板煙鍏抽敭璇嶏紙鍘婚櫎鈥滃垎鍏徃鈥濆悗缂�锛�
- // 渚嬪锛氣�滃箍宸炲垎鍏徃鈥� -> 鈥滃箍宸炩��
- //濡傛灉鍑虹幇骞垮窞鎬诲叕鍙革紝涔熻鍘婚櫎鈥滄�诲叕鍙糕�濆悗缂�
- this.selectedRegion = this.replaceRegion(selected.deptName);
- // 閲嶆柊鍔犺浇鍖婚櫌鍒楄〃锛堝甫鍦板煙杩囨护锛�
- this.loadDefaultHospitals()
+ onOrganizationChange(orgData) {
+ // orgData 鍖呭惈锛歞eptId, deptName, serviceOrderClass, region
+ this.selectedOrganizationId = orgData.deptId
+ this.selectedOrganizationServiceOrderClass = orgData.serviceOrderClass
+ this.selectedRegion = orgData.region
+
+ console.log('閫変腑褰掑睘鏈烘瀯:', orgData.deptName, '閮ㄩ棬ID:', orgData.deptId, '鏈嶅姟鍗曠紪鐮�:', orgData.serviceOrderClass, '鍦板煙:', orgData.region)
},
replaceRegion(region){
return region.replace(/(鍒嗗叕鍙竱鎬诲叕鍙竱鎬婚儴)$/g, '').trim();
},
- // 鍔犺浇鍒嗗叕鍙告暟鎹紙parent_id=100鐨勯儴闂級
- loadBranchCompanies() {
- listBranchCompany().then(response => {
- const list = response.data || []
- // 杩囨护鍑� parent_id = 100 鐨勯儴闂紙鍒嗗叕鍙革級
- this.organizationOptions = list.filter(dept => dept.parentId === 100)
- // 鐢熸垚picker鐨勬暟鎹簮锛堝彧鏄剧ず鍚嶇О锛�
- this.organizations = this.organizationOptions.map(dept => dept.deptName)
-
- // 榛樿璁剧疆涓哄綋鍓嶇敤鎴风殑鍒嗗叕鍙�
- if (this.currentUser.branchCompanyName) {
- const index = this.organizationOptions.findIndex(
- dept => dept.deptName === this.currentUser.branchCompanyName
- )
- if (index !== -1) {
- this.selectedOrganization = this.currentUser.branchCompanyName
- this.selectedOrganizationId = this.organizationOptions[index].deptId // 淇濆瓨閮ㄩ棬ID
- this.selectedOrganizationServiceOrderClass = this.organizationOptions[index].serviceOrderClass || '' // 淇濆瓨鏈嶅姟鍗曠紪鐮�
- // 鎻愬彇鍦板煙鍏抽敭璇�
- this.selectedRegion =this.replaceRegion(this.selectedOrganization);
- console.log('榛樿閫変腑褰掑睘鏈烘瀯:', this.selectedOrganization, '閮ㄩ棬ID:', this.selectedOrganizationId, '鏈嶅姟鍗曠紪鐮�:', this.selectedOrganizationServiceOrderClass, '鍦板煙:', this.selectedRegion)
- // 鍔犺浇鍖婚櫌鍒楄〃锛堝甫鍦板煙杩囨护锛�
- this.loadDefaultHospitals()
- }
- }
- }).catch(error => {
- console.error('鍔犺浇鍒嗗叕鍙告暟鎹け璐�:', error)
- this.organizationOptions = []
- this.organizations = []
- })
- },
// 鍔犺浇绉戝鏁版嵁锛堜粠 SQL Server 鍔ㄦ�佸姞杞斤級
loadDepartments() {
@@ -892,243 +618,15 @@
this.selectedDocumentTypeId = selected.id
},
- // 杞嚭鍖婚櫌绉戝閫夋嫨
- onHospitalOutDepartmentChange(e) {
- const index = e.detail.value
- const selected = this.departmentOptions[index]
- this.taskForm.hospitalOut.department = selected.text // 淇濆瓨绉戝鍚嶇О
- this.taskForm.hospitalOut.departmentId = selected.id // 淇濆瓨绉戝ID
- },
-
- // 杞叆鍖婚櫌绉戝閫夋嫨
- onHospitalInDepartmentChange(e) {
- const index = e.detail.value
- const selected = this.departmentOptions[index]
- this.taskForm.hospitalIn.department = selected.text // 淇濆瓨绉戝鍚嶇О
- this.taskForm.hospitalIn.departmentId = selected.id // 淇濆瓨绉戝ID
- },
-
- // 鍔犺浇榛樿鍖婚櫌鍒楄〃锛堝父鐢ㄥ尰闄級
- loadDefaultHospitals() {
- // 妫�鏌ユ槸鍚︽湁褰掑睘鏈烘瀯ID
- if (!this.selectedOrganizationId) {
- console.warn('鏈�夋嫨褰掑睘鏈烘瀯锛屾棤娉曞姞杞藉尰闄㈠垪琛�')
- return
- }
-
- // 杞嚭鍖婚櫌锛氭牴鎹綊灞炴満鏋勭殑鍖哄煙閰嶇疆鍔犺浇
- this.loadHospitalsByDeptRegion('out')
-
- // 杞叆鍖婚櫌锛氭牴鎹綊灞炴満鏋勭殑鍖哄煙閰嶇疆鍔犺浇
- this.loadHospitalsByDeptRegion('in')
- },
-
- // 闄嶇骇鍔犺浇鍖婚櫌锛堟寜鍦板煙杩囨护锛�
- loadDefaultHospitalsByRegion() {
- // 杞嚭鍖婚櫌锛氬彧鍔犺浇褰撳墠鍖哄煙鐨勫尰闄紙甯﹀湴鍩熻繃婊わ級
- searchHospitals('', this.selectedRegion).then(response => {
- this.hospitalOutResults = response.data || []
- console.log('鍔犺浇杞嚭鍖婚櫌锛堝綋鍓嶅尯鍩燂級:', this.selectedRegion, '鏁伴噺:', this.hospitalOutResults.length)
- }).catch(error => {
- console.error('鍔犺浇杞嚭鍖婚櫌鍒楄〃澶辫触:', error)
- this.hospitalOutResults = []
- })
-
- // 杞叆鍖婚櫌锛氬姞杞芥墍鏈夊尰闄紙涓嶅甫鍦板煙杩囨护锛屽悗缁細鎸夊湴鍩熸帓搴忥級
- searchHospitals('', '').then(response => {
- const allHospitals = response.data || []
- // 灏嗗尰闄㈡寜鍦板煙鎺掑簭锛氭湰鍦板尯鍩熶紭鍏�
- this.hospitalInResults = this.sortHospitalsByRegion(allHospitals)
- console.log('鍔犺浇杞叆鍖婚櫌锛堝叏閮ㄥ尯鍩燂級:', '鏁伴噺:', this.hospitalInResults.length)
- }).catch(error => {
- console.error('鍔犺浇杞叆鍖婚櫌鍒楄〃澶辫触:', error)
- this.hospitalInResults = []
- })
- },
-
- // 鏍规嵁閮ㄩ棬鍖哄煙閰嶇疆鍔犺浇鍖婚櫌
- loadHospitalsByDeptRegion(type) {
- const deptId = this.selectedOrganizationId
- if (!deptId) {
- console.warn('閮ㄩ棬ID涓嶅瓨鍦�')
- return
- }
-
- // 璋冪敤鍚庣鎺ュ彛锛屾牴鎹儴闂ㄧ殑鍖哄煙閰嶇疆鏌ヨ鍖婚櫌
- searchHospitalsByDeptRegion('', deptId).then(response => {
- const hospitals = response.data || []
-
- if (type === 'out') {
- this.hospitalOutResults = hospitals
- console.log('鍔犺浇杞嚭鍖婚櫌锛堝尯鍩熼厤缃級锛氶儴闂�', deptId, '鏁伴噺:', this.hospitalOutResults.length)
- } else if (type === 'in') {
- // 杞叆鍖婚櫌鎸夊湴鍩熸帓搴�
- this.hospitalInResults = this.sortHospitalsByRegion(hospitals)
- console.log('鍔犺浇杞叆鍖婚櫌锛堝尯鍩熼厤缃級锛氶儴闂�', deptId, '鏁伴噺:', this.hospitalInResults.length)
- }
- }).catch(error => {
- console.error('鍔犺浇鍖婚櫌澶辫触锛堝尯鍩熼厤缃級:', error)
- // 澶辫触鍚庨檷绾т负鏅�氭悳绱�
- this.loadDefaultHospitalsByRegion()
- })
- },
-
- // 鎸夊湴鍩熸帓搴忓尰闄細鏈湴鍖哄煙浼樺厛锛�"瀹朵腑"濮嬬粓鍦ㄦ渶鍓嶉潰
- sortHospitalsByRegion(hospitals) {
- if (!hospitals || hospitals.length === 0) {
- return hospitals
- }
-
- const region = this.selectedRegion
- const homeHospital = [] // "瀹朵腑"
- const localHospitals = [] // 鏈湴鍖婚櫌
- const otherHospitals = [] // 鍏朵粬鍖婚櫌
-
- hospitals.forEach(hospital => {
- // "瀹朵腑"浼樺厛澶勭悊锛屾斁鍦ㄦ渶鍓嶉潰
- if (hospital.hospName === '瀹朵腑') {
- homeHospital.push(hospital)
- return
- }
-
- // 鍒ゆ柇鍖婚櫌鏄惁鍦ㄦ湰鍦板尯鍩燂紙鐪併�佸競銆佸尯浠讳竴鍖呭惈鍦板煙鍏抽敭璇嶏級
- const isLocal = region && (
- (hospital.hopsProvince && hospital.hopsProvince.includes(region)) ||
- (hospital.hopsCity && hospital.hopsCity.includes(region)) ||
- (hospital.hopsArea && hospital.hopsArea.includes(region))
- )
-
- if (isLocal) {
- localHospitals.push(hospital)
- } else {
- otherHospitals.push(hospital)
- }
- })
-
- // "瀹朵腑"鍦ㄦ渶鍓嶏紝鏈湴鍖婚櫌鍏舵锛屽叾浠栧尰闄㈠湪鍚�
- return [...homeHospital, ...localHospitals, ...otherHospitals]
- },
-
- // 杞嚭鍖婚櫌杈撳叆妗嗚幏寰楃劍鐐�
- onHospitalOutFocus() {
- // 濡傛灉娌℃湁鎼滅储鍏抽敭璇嶏紝鏄剧ず甯哥敤杞嚭鍖婚櫌
- if (!this.hospitalOutSearchKeyword || this.hospitalOutSearchKeyword.trim() === '') {
- // 濡傛灉宸茬粡鍔犺浇杩囧父鐢ㄥ尰闄紝鐩存帴鏄剧ず
- if (this.hospitalOutResults.length > 0) {
- this.showHospitalOutResults = true
- return
- }
-
- // 鍚﹀垯閲嶆柊鍔犺浇甯哥敤鍖婚櫌
- if (this.selectedOrganizationServiceOrderClass) {
- getFrequentOutHospitals(this.selectedOrganizationServiceOrderClass, this.selectedRegion).then(response => {
- const hospitals = response.data || []
- // 纭繚"瀹朵腑"鍦ㄦ渶鍓嶉潰
- this.hospitalOutResults = this.sortHospitalsByRegion(hospitals)
- // 濡傛灉娌℃湁甯哥敤鍖婚櫌锛岄檷绾т负鏅�氭悳绱�
- if (this.hospitalOutResults.length === 0) {
- searchHospitals('', this.selectedOrganizationId).then(res => {
- const hospitals = res.data || []
- this.hospitalOutResults = this.sortHospitalsByRegion(hospitals)
- })
- }
- }).catch(error => {
- console.error('鍔犺浇甯哥敤杞嚭鍖婚櫌澶辫触:', error)
- searchHospitals('', this.selectedOrganizationId).then(res => {
- const hospitals = res.data || []
- this.hospitalOutResults = this.sortHospitalsByRegion(hospitals)
- })
- })
- } else {
- // 娌℃湁鏈嶅姟鍗曠紪鐮侊紝浣跨敤鏅�氭悳绱�
- searchHospitals('', this.selectedOrganizationId).then(response => {
- const hospitals = response.data || []
- this.hospitalOutResults = this.sortHospitalsByRegion(hospitals)
- }).catch(error => {
- console.error('鍔犺浇杞嚭鍖婚櫌澶辫触:', error)
- this.hospitalOutResults = []
- })
- }
- }
- this.showHospitalOutResults = true
- },
-
- // 杞嚭鍖婚櫌鎼滅储
- onHospitalOutSearch(e) {
- const keyword = e.detail.value
- this.hospitalOutSearchKeyword = keyword
-
- // 闃叉姈澶勭悊
- if (this.searchTimer) {
- clearTimeout(this.searchTimer)
- }
-
- // 濡傛灉鍏抽敭璇嶄负绌猴紝鏄剧ず褰撳墠鍖哄煙鐨勫尰闄�
- if (!keyword || keyword.trim() === '') {
- searchHospitals('', this.selectedOrganizationId).then(response => {
- const hospitals = response.data || []
- // 纭繚"瀹朵腑"鍦ㄦ渶鍓嶉潰
- this.hospitalOutResults = this.sortHospitalsByRegion(hospitals)
- }).catch(error => {
- console.error('鍔犺浇杞嚭鍖婚櫌澶辫触:', error)
- this.hospitalOutResults = []
- })
- this.showHospitalOutResults = true
- return
- }
-
- // 鏈夊叧閿瘝鏃讹紝鍘绘湇鍔$鎼滅储锛堜粎闄愬綋鍓嶅尯鍩燂級
- this.searchTimer = setTimeout(() => {
- this.searchHospitalOut(keyword)
- }, 300)
- },
-
- // 鎼滅储杞嚭鍖婚櫌锛堜粎闄愬綋鍓嶅尯鍩燂級
- searchHospitalOut(keyword) {
- // 浼犲叆鍏抽敭璇嶅拰閮ㄩ棬ID锛屽彧鎼滅储褰撳墠鍖哄煙鐨勫尰闄�
- searchHospitals(keyword, this.selectedOrganizationId).then(response => {
- const hospitals = response.data || []
- // 纭繚"瀹朵腑"鍦ㄦ渶鍓嶉潰
- this.hospitalOutResults = this.sortHospitalsByRegion(hospitals)
- this.showHospitalOutResults = true
- console.log('鎼滅储杞嚭鍖婚櫌:', keyword, '閮ㄩ棬ID:', this.selectedOrganizationId, '缁撴灉鏁�:', this.hospitalOutResults.length)
- }).catch(error => {
- console.error('鎼滅储杞嚭鍖婚櫌澶辫触:', error)
- this.hospitalOutResults = []
- })
- },
-
- // 閫夋嫨杞嚭鍖婚櫌
- selectHospitalOut(hospital) {
- this.taskForm.hospitalOut.id = hospital.hospId // 淇濆瓨鍖婚櫌ID
- this.taskForm.hospitalOut.name = hospital.hospName
- // 濡傛灉閫夋嫨鐨勬槸"瀹朵腑"锛屾竻绌哄湴鍧�璁╃敤鎴锋墜鍔ㄨ緭鍏ワ紱鍚﹀垯鑷姩濉厖鍦板潃
- if (hospital.hospName === '瀹朵腑') {
- this.taskForm.hospitalOut.address = ''
- // 绉戝鑷姩璁剧疆涓�"鍏跺畠"
- this.taskForm.hospitalOut.department = '鍏跺畠'
- this.taskForm.hospitalOut.departmentId = null
- } else {
- // 鍚堝苟鐪佸競鍖� + 璇︾粏鍦板潃
- const fullAddress = this.buildFullAddress(hospital)
- this.taskForm.hospitalOut.address = fullAddress
- // 娓呯┖绉戝锛岃鐢ㄦ埛閲嶆柊閫夋嫨
- if (this.taskForm.hospitalOut.department === '鍏跺畠') {
- this.taskForm.hospitalOut.department = ''
- this.taskForm.hospitalOut.departmentId = null
- }
- }
- this.hospitalOutSearchKeyword = hospital.hospName
- this.showHospitalOutResults = false
- this.hospitalOutResults = []
-
- // 淇濆瓨杞嚭鍖婚櫌鐨勫煄甯備俊鎭�
- this.taskForm.hospitalOut.city = hospital.hopsCity || ''
+ // 杞嚭鍖婚櫌鍙樺寲
+ onHospitalOutChange(hospitalData) {
+ console.log('杞嚭鍖婚櫌鍙樺寲:', hospitalData)
+ // 缁勪欢宸茬粡閫氳繃 v-model 鏇存柊浜� taskForm.hospitalOut
// 濡傛灉杞叆鍦板潃宸插~鍐�,鑷姩璁$畻璺濈
if (this.taskForm.hospitalIn.address) {
// 濡傛灉涓や釜閮戒笉鏄�"瀹朵腑",浣跨敤鍖婚櫌璺濈璁$畻
- if (hospital.hospName !== '瀹朵腑' && this.taskForm.hospitalIn.name !== '瀹朵腑') {
+ if (hospitalData.name !== '瀹朵腑' && this.taskForm.hospitalIn.name !== '瀹朵腑') {
this.calculateHospitalDistance()
} else {
// 鏈変竴涓槸"瀹朵腑",浣跨敤鍦板潃璁$畻
@@ -1137,130 +635,44 @@
}
},
- // 杞叆鍖婚櫌杈撳叆妗嗚幏寰楃劍鐐�
- onHospitalInFocus() {
- // 濡傛灉娌℃湁鎼滅储鍏抽敭璇嶏紝鏄剧ず甯哥敤杞叆鍖婚櫌
- if (!this.hospitalInSearchKeyword || this.hospitalInSearchKeyword.trim() === '') {
- // 濡傛灉宸茬粡鍔犺浇杩囧父鐢ㄥ尰闄紝鐩存帴鏄剧ず
- if (this.hospitalInResults.length > 0) {
- this.showHospitalInResults = true
- return
- }
+ // 杞嚭鍖婚櫌鍦板潃閫夋嫨锛堝綋閫夋嫨"瀹朵腑"鏃朵娇鐢ㄧ櫨搴﹀湴鍥惧湴鍧�寤鸿锛�
+ onHospitalOutAddressSelected(data) {
+ // data 鍖呭惈锛歛ddress, location
+ if (data.location) {
+ this.addressCoordinates.hospitalOutAddress = data.location
- // 鍚﹀垯閲嶆柊鍔犺浇甯哥敤鍖婚櫌
- if (this.selectedOrganizationServiceOrderClass) {
- getFrequentInHospitals(this.selectedOrganizationServiceOrderClass, '').then(response => {
- const allHospitals = response.data || []
- // 鎸夊湴鍩熸帓搴忥細鏈湴鍖哄煙浼樺厛
- this.hospitalInResults = this.sortHospitalsByRegion(allHospitals)
- // 濡傛灉娌℃湁甯哥敤鍖婚櫌锛岄檷绾т负鏅�氭悳绱�
- if (this.hospitalInResults.length === 0) {
- searchHospitals('', null).then(res => {
- const allHospitals = res.data || []
- this.hospitalInResults = this.sortHospitalsByRegion(allHospitals)
- })
- }
- }).catch(error => {
- console.error('鍔犺浇甯哥敤杞叆鍖婚櫌澶辫触:', error)
- searchHospitals('', null).then(res => {
- const allHospitals = res.data || []
- this.hospitalInResults = this.sortHospitalsByRegion(allHospitals)
- })
- })
- } else {
- // 娌℃湁鏈嶅姟鍗曠紪鐮侊紝浣跨敤鏅�氭悳绱�
- searchHospitals('', null).then(response => {
- const allHospitals = response.data || []
- // 鎸夊湴鍩熸帓搴忥細鏈湴鍖哄煙浼樺厛
- this.hospitalInResults = this.sortHospitalsByRegion(allHospitals)
- }).catch(error => {
- console.error('鍔犺浇杞叆鍖婚櫌澶辫触:', error)
- this.hospitalInResults = []
- })
+ // 濡傛灉杞叆鍦板潃涔熷凡濉啓,鑷姩璁$畻璺濈
+ if (this.taskForm.hospitalIn.address) {
+ this.calculateDistanceByManualAddress()
}
}
- this.showHospitalInResults = true
},
- // 杞叆鍖婚櫌鎼滅储
- onHospitalInSearch(e) {
- const keyword = e.detail.value
- this.hospitalInSearchKeyword = keyword
-
- // 闃叉姈澶勭悊
- if (this.searchTimer) {
- clearTimeout(this.searchTimer)
- }
-
- // 濡傛灉鍏抽敭璇嶄负绌猴紝鏄剧ず鎵�鏈夊尰闄紙鏈湴鍖哄煙浼樺厛锛�
- if (!keyword || keyword.trim() === '') {
- searchHospitals('', null).then(response => {
- const allHospitals = response.data || []
- // 鎸夊湴鍩熸帓搴忥細"瀹朵腑"鏈�鍓嶏紝鏈湴鍖哄煙浼樺厛
- this.hospitalInResults = this.sortHospitalsByRegion(allHospitals)
- }).catch(error => {
- console.error('鍔犺浇杞叆鍖婚櫌澶辫触:', error)
- this.hospitalInResults = []
- })
- this.showHospitalInResults = true
- return
- }
-
- // 鏈夊叧閿瘝鏃讹紝鍘绘湇鍔$鎼滅储锛堜笉闄愬尯鍩燂紝浣嗙粨鏋滄寜鍦板煙鎺掑簭锛�
- this.searchTimer = setTimeout(() => {
- this.searchHospitalIn(keyword)
- }, 300)
- },
-
- // 鎼滅储杞叆鍖婚櫌锛堜笉闄愬尯鍩燂紝浣嗘湰鍦板尯鍩熶紭鍏堬級
- searchHospitalIn(keyword) {
- // 浼犲叆鍏抽敭璇嶏紝涓嶄紶閮ㄩ棬ID锛堟悳绱㈡墍鏈夊尯鍩燂級
- searchHospitals(keyword, null).then(response => {
- const allHospitals = response.data || []
- // 鎸夊湴鍩熸帓搴忥細"瀹朵腑"鏈�鍓嶏紝鏈湴鍖哄煙浼樺厛
- this.hospitalInResults = this.sortHospitalsByRegion(allHospitals)
- this.showHospitalInResults = true
- console.log('鎼滅储杞叆鍖婚櫌:', keyword, '缁撴灉鏁�:', this.hospitalInResults.length)
- }).catch(error => {
- console.error('鎼滅储杞叆鍖婚櫌澶辫触:', error)
- this.hospitalInResults = []
- })
- },
-
- // 閫夋嫨杞叆鍖婚櫌
- selectHospitalIn(hospital) {
- this.taskForm.hospitalIn.id = hospital.hospId // 淇濆瓨鍖婚櫌ID
- this.taskForm.hospitalIn.name = hospital.hospName
- // 濡傛灉閫夋嫨鐨勬槸"瀹朵腑"锛屾竻绌哄湴鍧�璁╃敤鎴锋墜鍔ㄨ緭鍏ワ紱鍚﹀垯鑷姩濉厖鍦板潃
- if (hospital.hospName === '瀹朵腑') {
- this.taskForm.hospitalIn.address = ''
- // 绉戝鑷姩璁剧疆涓�"鍏跺畠"
- this.taskForm.hospitalIn.department = '鍏跺畠'
- this.taskForm.hospitalIn.departmentId = null
- } else {
- // 鍚堝苟鐪佸競鍖� + 璇︾粏鍦板潃
- const fullAddress = this.buildFullAddress(hospital)
- this.taskForm.hospitalIn.address = fullAddress
- // 娓呯┖绉戝锛岃鐢ㄦ埛閲嶆柊閫夋嫨
- if (this.taskForm.hospitalIn.department === '鍏跺畠') {
- this.taskForm.hospitalIn.department = ''
- this.taskForm.hospitalIn.departmentId = null
- }
- }
- this.hospitalInSearchKeyword = hospital.hospName
- this.showHospitalInResults = false
- this.hospitalInResults = []
-
- // 淇濆瓨杞叆鍖婚櫌鐨勫煄甯備俊鎭�
- this.taskForm.hospitalIn.city = hospital.hopsCity || ''
+ // 杞叆鍖婚櫌鍙樺寲
+ onHospitalInChange(hospitalData) {
+ console.log('杞叆鍖婚櫌鍙樺寲:', hospitalData)
+ // 缁勪欢宸茬粡閫氳繃 v-model 鏇存柊浜� taskForm.hospitalIn
// 濡傛灉杞嚭鍦板潃宸插~鍐�,鑷姩璁$畻璺濈
if (this.taskForm.hospitalOut.address) {
// 濡傛灉涓や釜閮戒笉鏄�"瀹朵腑",浣跨敤鍖婚櫌璺濈璁$畻
- if (hospital.hospName !== '瀹朵腑' && this.taskForm.hospitalOut.name !== '瀹朵腑') {
+ if (hospitalData.name !== '瀹朵腑' && this.taskForm.hospitalOut.name !== '瀹朵腑') {
this.calculateHospitalDistance()
} else {
// 鏈変竴涓槸"瀹朵腑",浣跨敤鍦板潃璁$畻
+ this.calculateDistanceByManualAddress()
+ }
+ }
+ },
+
+ // 杞叆鍖婚櫌鍦板潃閫夋嫨锛堝綋閫夋嫨"瀹朵腑"鏃朵娇鐢ㄧ櫨搴﹀湴鍥惧湴鍧�寤鸿锛�
+ onHospitalInAddressSelected(data) {
+ // data 鍖呭惈锛歛ddress, location
+ if (data.location) {
+ this.addressCoordinates.hospitalInAddress = data.location
+
+ // 濡傛灉杞嚭鍦板潃涔熷凡濉啓,鑷姩璁$畻璺濈
+ if (this.taskForm.hospitalOut.address) {
this.calculateDistanceByManualAddress()
}
}
@@ -1396,7 +808,7 @@
console.log('鎸夊叧閿瘝杩囨护鍚庯紝鏁伴噺:', list.length)
this.filteredStaffList = list
- console.log('鏈�缁堣繃婊ょ粨鏋�:', this.filteredStaffList)
+ // console.log('鏈�缁堣繃婊ょ粨鏋�:', this.filteredStaffList)
},
// 鍒囨崲浜哄憳閫変腑鐘舵��
@@ -1443,168 +855,6 @@
addStaff() {
this.showStaffSelector()
},
-
- // ==================== 鍦板潃杈撳叆鑱旀兂鐩稿叧鏂规硶 ====================
-
- // 杞嚭鍦板潃杈撳叆鐩戝惉
- onAddressOutInput(e) {
- const query = e.detail.value
- this.taskForm.hospitalOut.address = query
-
- // 闃叉姈澶勭悊
- if (this.addressSearchTimer) {
- clearTimeout(this.addressSearchTimer)
- }
-
- // 濡傛灉杈撳叆涓虹┖锛岄殣钘忔彁绀哄垪琛�
- if (!query || query.trim() === '') {
- this.showAddressOutSuggestions = false
- this.addressOutSuggestions = []
- return
- }
-
- // 杈撳叆闀垮害澶т簬2鎵嶅紑濮嬫悳绱�
- if (query.trim().length < 2) {
- this.showAddressOutSuggestions = false
- return
- }
-
- // 寤惰繜300ms鎼滅储
- this.addressSearchTimer = setTimeout(() => {
- this.searchAddressOut(query)
- }, 300)
- },
-
- // 杞嚭鍦板潃杈撳叆妗嗚幏寰楃劍鐐�
- onAddressOutFocus() {
- // 濡傛灉鏈夊湴鍧�涓旀湁鎼滅储缁撴灉锛屾樉绀烘彁绀哄垪琛�
- if (this.taskForm.hospitalOut.address && this.addressOutSuggestions.length > 0) {
- this.showAddressOutSuggestions = true
- }
- },
-
- // 鎼滅储杞嚭鍦板潃
- searchAddressOut(query) {
- // 鑾峰彇褰撳墠鍖哄煙锛堜紭鍏堜娇鐢ㄥ綊灞炴満鏋勭殑鍖哄煙锛�
- const region = this.selectedRegion || '骞垮窞'
-
- baiduPlaceSuggestion(query, region).then(response => {
- if (response.code === 200 && response.data) {
- this.addressOutSuggestions = response.data
- this.showAddressOutSuggestions = true
- } else {
- this.addressOutSuggestions = []
- this.showAddressOutSuggestions = false
- }
- }).catch(error => {
- console.error('鎼滅储杞嚭鍦板潃澶辫触:', error)
- this.addressOutSuggestions = []
- this.showAddressOutSuggestions = false
- })
- },
-
- // 閫夋嫨杞嚭鍦板潃
- selectAddressOut(item) {
- // 濉厖瀹屾暣鍦板潃
- const fullAddress = item.district + item.address
- this.taskForm.hospitalOut.address = fullAddress
-
- // 淇濆瓨缁忕含搴︼紙濡傛灉鏈夛級
- if (item.location) {
- this.taskForm.hospitalOut.latitude = item.location.lat
- this.taskForm.hospitalOut.longitude = item.location.lng
- }
-
- // 闅愯棌鎻愮ず鍒楄〃
- this.showAddressOutSuggestions = false
- this.addressOutSuggestions = []
-
- // 濡傛灉杞叆鍦板潃涔熷凡濉啓,鑷姩璁$畻璺濈
- if (this.taskForm.hospitalIn.address) {
- this.calculateDistanceByManualAddress()
- }
- },
-
- // 杞叆鍦板潃杈撳叆鐩戝惉
- onAddressInInput(e) {
- const query = e.detail.value
- this.taskForm.hospitalIn.address = query
-
- // 闃叉姈澶勭悊
- if (this.addressSearchTimer) {
- clearTimeout(this.addressSearchTimer)
- }
-
- // 濡傛灉杈撳叆涓虹┖锛岄殣钘忔彁绀哄垪琛�
- if (!query || query.trim() === '') {
- this.showAddressInSuggestions = false
- this.addressInSuggestions = []
- return
- }
-
- // 杈撳叆闀垮害澶т簬2鎵嶅紑濮嬫悳绱�
- if (query.trim().length < 2) {
- this.showAddressInSuggestions = false
- return
- }
-
- // 寤惰繜300ms鎼滅储
- this.addressSearchTimer = setTimeout(() => {
- this.searchAddressIn(query)
- }, 300)
- },
-
- // 杞叆鍦板潃杈撳叆妗嗚幏寰楃劍鐐�
- onAddressInFocus() {
- // 濡傛灉鏈夊湴鍧�涓旀湁鎼滅储缁撴灉锛屾樉绀烘彁绀哄垪琛�
- if (this.taskForm.hospitalIn.address && this.addressInSuggestions.length > 0) {
- this.showAddressInSuggestions = true
- }
- },
-
- // 鎼滅储杞叆鍦板潃
- searchAddressIn(query) {
- // 鑾峰彇褰撳墠鍖哄煙锛堜紭鍏堜娇鐢ㄥ綊灞炴満鏋勭殑鍖哄煙锛�
- const region = this.selectedRegion || '骞垮窞'
-
- baiduPlaceSuggestion(query, region).then(response => {
- if (response.code === 200 && response.data) {
- this.addressInSuggestions = response.data
- this.showAddressInSuggestions = true
- } else {
- this.addressInSuggestions = []
- this.showAddressInSuggestions = false
- }
- }).catch(error => {
- console.error('鎼滅储杞叆鍦板潃澶辫触:', error)
- this.addressInSuggestions = []
- this.showAddressInSuggestions = false
- })
- },
-
- // 閫夋嫨杞叆鍦板潃
- selectAddressIn(item) {
- // 濉厖瀹屾暣鍦板潃
- const fullAddress = item.district + item.address
- this.taskForm.hospitalIn.address = fullAddress
-
- // 淇濆瓨缁忕含搴︼紙濡傛灉鏈夛級
- if (item.location) {
- this.taskForm.hospitalIn.latitude = item.location.lat
- this.taskForm.hospitalIn.longitude = item.location.lng
- }
-
- // 闅愯棌鎻愮ず鍒楄〃
- this.showAddressInSuggestions = false
- this.addressInSuggestions = []
-
- // 濡傛灉杞嚭鍦板潃涔熷凡濉啓,鑷姩璁$畻璺濈
- if (this.taskForm.hospitalOut.address) {
- this.calculateDistanceByManualAddress()
- }
- },
-
- // 鎵嬪姩杈撳叆鍦板潃鏃惰绠楄窛绂�
calculateDistanceByManualAddress() {
const fromAddress = this.taskForm.hospitalOut.address
const toAddress = this.taskForm.hospitalIn.address
@@ -1694,107 +944,7 @@
// 璁$畻澶辫触鏃朵笉鎻愮ず鐢ㄦ埛锛屽厑璁哥敤鎴锋墜鍔ㄨ緭鍏�
})
},
-
- // ==================== 鐥呮儏閫夋嫨鐩稿叧鏂规硶 ====================
-
- // 鏄剧ず鐥呮儏閫夋嫨寮圭獥
- showDiseaseSelector() {
- // 鍒濆鍖栦复鏃堕�夋嫨鍒楄〃锛堝鍒跺綋鍓嶅凡閫夋嫨鐨勭梾鎯咃級
- this.tempSelectedDiseases = [...this.selectedDiseases]
- this.diseaseSearchKeyword = ''
- // 榛樿鍔犺浇鎵�鏈夌梾鎯�
- this.loadAllDiseases()
- this.$refs.diseasePopup.open()
- },
-
- // 鍏抽棴鐥呮儏閫夋嫨寮圭獥
- closeDiseaseSelector() {
- this.$refs.diseasePopup.close()
- this.diseaseSearchKeyword = ''
- this.diseaseSearchResults = []
- this.tempSelectedDiseases = []
- },
-
- // 鐥呮儏鎼滅储
- onDiseaseSearch(e) {
- const keyword = e.detail.value
- this.diseaseSearchKeyword = keyword
-
- // 闃叉姈澶勭悊
- if (this.diseaseSearchTimer) {
- clearTimeout(this.diseaseSearchTimer)
- }
-
- // 濡傛灉鍏抽敭璇嶄负绌猴紝鍔犺浇鎵�鏈夌梾鎯�
- if (!keyword || keyword.trim() === '') {
- this.loadAllDiseases()
- return
- }
-
- // 鏈夊叧閿瘝鏃惰繘琛屾悳绱�
- this.diseaseSearchTimer = setTimeout(() => {
- this.searchDiseaseByKeyword(keyword)
- }, 300)
- },
-
- // 鍔犺浇鎵�鏈夌梾鎯咃紙榛樿鏄剧ず锛�
- loadAllDiseases() {
- // 浣跨敤绌哄瓧绗︿覆鎴栫壒娈婃爣璇嗙鏉ヨ幏鍙栨墍鏈夌梾鎯�
- // 濡傛灉鍚庣涓嶆敮鎸佺┖鏌ヨ锛屽彲浠ヤ紶鍏ヤ竴涓�氶厤绗﹀'%'鎴栬�呬慨鏀瑰悗绔帴鍙�
- searchIcd10('').then(response => {
- this.diseaseSearchResults = response.data || []
- }).catch(error => {
- console.error('鍔犺浇鐥呮儏鍒楄〃澶辫触:', error)
- this.diseaseSearchResults = []
- })
- },
-
- // 鏍规嵁鍏抽敭璇嶆悳绱㈢梾鎯�
- searchDiseaseByKeyword(keyword) {
- searchIcd10(keyword).then(response => {
- this.diseaseSearchResults = response.data || []
- }).catch(error => {
- console.error('鎼滅储鐥呮儏澶辫触:', error)
- this.diseaseSearchResults = []
- })
- },
-
- // 鍒囨崲鐥呮儏閫変腑鐘舵��
- toggleDiseaseSelection(disease) {
- const index = this.tempSelectedDiseases.findIndex(d => d.id === disease.id)
-
- if (index > -1) {
- // 宸查�変腑锛岀Щ闄�
- this.tempSelectedDiseases.splice(index, 1)
- } else {
- // 鏈�変腑锛屾坊鍔�
- this.tempSelectedDiseases.push({
- id: disease.id,
- icdCode: disease.icdCode,
- icdName: disease.icdName,
- sm: disease.sm
- })
- }
- },
-
- // 鍒ゆ柇鐥呮儏鏄惁宸查�変腑
- isDiseaseSelected(diseaseId) {
- return this.tempSelectedDiseases.some(d => d.id === diseaseId)
- },
-
- // 纭鐥呮儏閫夋嫨
- confirmDiseaseSelection() {
- // 灏嗕复鏃堕�夋嫨鐨勭梾鎯呭鍒跺埌姝e紡鍒楄〃
- this.selectedDiseases = [...this.tempSelectedDiseases]
- this.closeDiseaseSelector()
- },
-
- // 绉婚櫎鐥呮儏
- removeDisease(index) {
- this.selectedDiseases.splice(index, 1)
- },
-
- // 璁剧疆榛樿杞繍鏃堕棿涓哄綋鍓嶆椂闂�
+ // 鎵嬪姩杈撳叆鍦板潃鏃惰绠楄窛绂�
setDefaultTransferTime() {
const now = new Date()
const year = now.getFullYear()
@@ -1886,8 +1036,14 @@
// 鍚堝苟鐥呮儏淇℃伅锛氶�変腑鐨処CD-10鐤剧梾 + 鍏朵粬鎻忚堪
let conditionText = ''
if (this.selectedDiseases.length > 0) {
- const diseaseNames = this.selectedDiseases.map(d => `${d.icdName}(${d.icdCode})`).join('銆�')
- conditionText = diseaseNames
+ // 杩囨护鎺夌梾鎯呭悕绉颁负绌虹殑椤癸紝骞舵瀯寤虹梾鎯呭瓧绗︿覆
+ const diseaseNames = this.selectedDiseases
+ .filter(d => d.icdName && d.icdName.trim())
+ .map(d => `${d.icdName}(${d.icdCode})`)
+ .join('銆�')
+ if (diseaseNames) {
+ conditionText = diseaseNames
+ }
}
if (this.taskForm.patient.condition && this.taskForm.patient.condition.trim()) {
if (conditionText) {
@@ -1914,18 +1070,20 @@
documentTypeId: this.selectedDocumentTypeId, // 鍗曟嵁绫诲瀷ID
taskTypeId: this.selectedEmergencyTaskTypeId, // 浠诲姟绫诲瀷ID
// 鐥呮儏ID鍒楄〃锛堢敤浜庡悓姝ヨ皟搴﹀崟鐨凮rdICD_ID鍙傛暟锛�
- diseaseIds: this.selectedDiseases.map(d => d.id),
+ diseaseIds: this.selectedDiseases.filter(d => d.id !== null).map(d => d.id),
// 灏嗚浆鍑哄尰闄㈠湴鍧�浣滀负鍑哄彂鍦帮紝杞叆鍖婚櫌鍦板潃浣滀负鐩殑鍦�
departureAddress: this.taskForm.hospitalOut.address || '',
destinationAddress: this.taskForm.hospitalIn.address || '',
patient: {
...this.taskForm.patient,
condition: conditionText, // 浣跨敤鍚堝苟鍚庣殑鐥呮儏淇℃伅
- diseases: this.selectedDiseases.map(d => ({
- icdId: d.id,
- icdCode: d.icdCode,
- icdName: d.icdName
- }))
+ diseases: this.selectedDiseases
+ .filter(d => d.icdName && d.icdName.trim())
+ .map(d => ({
+ icdId: d.id,
+ icdCode: d.icdCode,
+ icdName: d.icdName
+ }))
},
// 鍖婚櫌淇℃伅锛堝寘鍚尰闄D銆佺瀹ゅ悕绉般�佺瀹D绛夊畬鏁翠俊鎭級
hospitalOut: this.taskForm.hospitalOut, // 鍖呭惈: id, name, department, departmentId, bedNumber, address
@@ -2989,145 +2147,6 @@
background-color: #ccc;
color: #999;
}
- }
- }
-}
-
-// 鐥呮儏閫夋嫨寮圭獥鏍峰紡
-.disease-selector-popup {
- background-color: white;
- border-radius: 20rpx 20rpx 0 0;
- max-height: 80vh;
- display: flex;
- flex-direction: column;
-
- .popup-header {
- display: flex;
- justify-content: space-between;
- align-items: center;
- padding: 30rpx;
- border-bottom: 1rpx solid #f0f0f0;
- flex-shrink: 0;
-
- .popup-title {
- font-size: 32rpx;
- font-weight: bold;
- color: #333;
- }
-
- .popup-close {
- padding: 10rpx;
- }
- }
-
- .search-box {
- display: flex;
- align-items: center;
- margin: 20rpx 30rpx;
- padding: 15rpx 20rpx;
- background-color: #f5f5f5;
- border-radius: 10rpx;
- flex-shrink: 0;
-
- .search-input {
- flex: 1;
- margin-left: 10rpx;
- font-size: 28rpx;
- }
- }
-
- .disease-list-popup {
- flex: 1;
- overflow-y: auto;
- padding: 0 30rpx;
-
- .disease-item-popup {
- display: flex;
- justify-content: space-between;
- align-items: center;
- padding: 25rpx 20rpx;
- border-bottom: 1rpx solid #f0f0f0;
-
- &:active {
- background-color: #f5f5f5;
- }
-
- .disease-info {
- flex: 1;
-
- .disease-name-row {
- display: flex;
- align-items: center;
- margin-bottom: 8rpx;
-
- .disease-name {
- font-size: 30rpx;
- font-weight: bold;
- color: #333;
- margin-right: 15rpx;
- }
-
- .disease-code {
- font-size: 24rpx;
- color: #007AFF;
- background-color: #e6f2ff;
- padding: 4rpx 12rpx;
- border-radius: 6rpx;
- }
- }
-
- .disease-detail-row {
- .disease-desc {
- font-size: 24rpx;
- color: #999;
- line-height: 1.5;
- }
- }
- }
-
- .checkbox-empty {
- width: 40rpx;
- height: 40rpx;
- border: 2rpx solid #ddd;
- border-radius: 50%;
- }
- }
-
- .no-data {
- text-align: center;
- padding: 100rpx 0;
- color: #999;
-
- text {
- display: block;
- margin-top: 20rpx;
- font-size: 28rpx;
- }
- }
- }
-
- .popup-footer {
- display: flex;
- padding: 20rpx 30rpx;
- border-top: 1rpx solid #f0f0f0;
- gap: 20rpx;
- flex-shrink: 0;
-
- button {
- flex: 1;
- height: 80rpx;
- border-radius: 10rpx;
- font-size: 30rpx;
- }
-
- .cancel-btn {
- background-color: #f5f5f5;
- color: #666;
- }
-
- .confirm-btn {
- background-color: #007AFF;
- color: white;
}
}
}
diff --git a/app/pages/task/create-normal.vue b/app/pages/task/create-normal.vue
index f8a8a3d..a2a7bdf 100644
--- a/app/pages/task/create-normal.vue
+++ b/app/pages/task/create-normal.vue
@@ -39,17 +39,49 @@
<view class="form-item">
<view class="form-label">浠诲姟鍑哄彂鍦�</view>
- <view class="form-input picker-input" @click="selectStartLocation">
- {{ taskForm.startLocation || '璇烽�夋嫨浠诲姟鍑哄彂鍦�' }}
- <uni-icons type="arrowright" size="16" color="#999"></uni-icons>
+ <view class="address-input-container">
+ <input
+ class="form-input"
+ placeholder="璇疯緭鍏ヤ换鍔″嚭鍙戝湴"
+ v-model="taskForm.startLocation"
+ @input="onStartLocationInput"
+ @focus="onStartLocationFocus"
+ />
+ <view class="address-suggestions" v-if="showStartSuggestions && startSuggestions.length > 0">
+ <view
+ class="address-suggestion-item"
+ v-for="(item, index) in startSuggestions"
+ :key="index"
+ @click="selectStartSuggestion(item)"
+ >
+ <view class="suggestion-name">{{ item.name }}</view>
+ <view class="suggestion-address">{{ item.address }}</view>
+ </view>
+ </view>
</view>
</view>
<view class="form-item">
<view class="form-label">浠诲姟鐩殑鍦�</view>
- <view class="form-input picker-input" @click="selectEndLocation">
- {{ taskForm.endLocation || '璇烽�夋嫨浠诲姟鐩殑鍦�' }}
- <uni-icons type="arrowright" size="16" color="#999"></uni-icons>
+ <view class="address-input-container">
+ <input
+ class="form-input"
+ placeholder="璇疯緭鍏ヤ换鍔$洰鐨勫湴"
+ v-model="taskForm.endLocation"
+ @input="onEndLocationInput"
+ @focus="onEndLocationFocus"
+ />
+ <view class="address-suggestions" v-if="showEndSuggestions && endSuggestions.length > 0">
+ <view
+ class="address-suggestion-item"
+ v-for="(item, index) in endSuggestions"
+ :key="index"
+ @click="selectEndSuggestion(item)"
+ >
+ <view class="suggestion-name">{{ item.name }}</view>
+ <view class="suggestion-address">{{ item.address }}</view>
+ </view>
+ </view>
</view>
</view>
@@ -109,40 +141,22 @@
</view>
</view>
- <!-- 鍦板浘閫夋嫨鍣ㄥ脊绐� -->
- <uni-popup ref="mapPopup" type="bottom" :mask-click="false">
- <view class="map-popup-container">
- <view class="popup-header">
- <view class="popup-title">閫夋嫨鍦板潃</view>
- <view class="close-btn" @click="closeMapSelector">
- <uni-icons type="closeempty" size="20" color="#999"></uni-icons>
- </view>
- </view>
- <map-selector
- :initial-address="getInitialAddress()"
- @addressSelected="onAddressSelected"
- ></map-selector>
- </view>
- </uni-popup>
+
</scroll-view>
</template>
<script>
import { mapState } from 'vuex'
import uniDatetimePicker from '@/uni_modules/uni-datetime-picker/components/uni-datetime-picker/uni-datetime-picker.vue'
-import uniPopup from '@/uni_modules/uni-popup/components/uni-popup/uni-popup.vue'
import { getUserProfile } from "@/api/system/user"
import { addTask } from "@/api/task"
import { listAvailableVehicles } from "@/api/vehicle"
-import { calculateDistance } from "@/api/map"
+import { baiduPlaceSuggestion, baiduGeocoding, baiduDistanceByAddress } from "@/api/map"
import { getDicts } from "@/api/dict"
-import MapSelector from '@/components/map-selector.vue'
export default {
components: {
- uniDatetimePicker,
- uniPopup,
- MapSelector
+ uniDatetimePicker
},
data() {
return {
@@ -157,7 +171,13 @@
boundVehicleId: null,
taskTypeOptions: [],
taskTypeLabels: [],
- mapSelectorType: '',
+ // 鍦板潃鎼滅储鐩稿叧
+ startSuggestions: [],
+ endSuggestions: [],
+ showStartSuggestions: false,
+ showEndSuggestions: false,
+ startSearchTimer: null,
+ endSearchTimer: null,
taskForm: {
taskDescription: '',
taskType: '',
@@ -173,14 +193,17 @@
vehicleOptions: [],
loading: false,
addressCoordinates: {
- startLocation: null,
- endLocation: null
- }
+ startLocation: { lon: null, lat: null },
+ endLocation: { lon: null, lat: null }
+ },
+ // 鎼滅储鍖哄煙锛堝彲鏍规嵁鐢ㄦ埛鎵�鍦ㄥ煄甯傝皟鏁达級
+ searchRegion: '骞垮窞甯�'
}
},
computed: {
...mapState({
currentUser: state => ({
+ id: state.user.userId,
name: state.user.nickName || '寮犱笁',
position: '鍙告満',
deptId: state.user.deptId || 100
@@ -300,77 +323,202 @@
this.taskForm.vehicleId = this.selectedVehicleId
},
- selectStartLocation() {
- this.mapSelectorType = 'startLocation'
- this.$refs.mapPopup.open()
- },
-
- selectEndLocation() {
- this.mapSelectorType = 'endLocation'
- this.$refs.mapPopup.open()
- },
-
- getInitialAddress() {
- return this.mapSelectorType === 'startLocation' ? this.taskForm.startLocation : this.taskForm.endLocation
- },
-
- onAddressSelected(address) {
- if (this.mapSelectorType === 'startLocation') {
- this.taskForm.startLocation = address.title + ' - ' + address.address
- this.addressCoordinates.startLocation = {
- lat: address.lat,
- lng: address.lng
- }
- } else if (this.mapSelectorType === 'endLocation') {
- this.taskForm.endLocation = address.title + ' - ' + address.address
- this.addressCoordinates.endLocation = {
- lat: address.lat,
- lng: address.lng
- }
+ // 鍑哄彂鍦拌緭鍏ョ洃鍚�
+ onStartLocationInput(e) {
+ const keyword = e.detail.value
+ this.taskForm.startLocation = keyword
+
+ if (this.startSearchTimer) {
+ clearTimeout(this.startSearchTimer)
}
- this.calculateDistance()
- this.closeMapSelector()
- },
-
- calculateDistance() {
- if (this.addressCoordinates.startLocation && this.addressCoordinates.endLocation) {
- this.getDistanceBetweenPoints(
- this.addressCoordinates.startLocation.lat,
- this.addressCoordinates.startLocation.lng,
- this.addressCoordinates.endLocation.lat,
- this.addressCoordinates.endLocation.lng
- ).then(distance => {
- this.taskForm.distance = distance.toFixed(2)
- }).catch(error => {
- console.error('璺濈璁$畻澶辫触:', error)
- })
+ if (!keyword || keyword.trim() === '') {
+ this.startSuggestions = []
+ this.showStartSuggestions = false
+ return
}
+
+ // 闃叉姈澶勭悊
+ this.startSearchTimer = setTimeout(() => {
+ this.searchStartAddress(keyword)
+ }, 300)
},
- getDistanceBetweenPoints(lat1, lng1, lat2, lng2) {
- return new Promise((resolve, reject) => {
- calculateDistance(lat1, lng1, lat2, lng2).then(response => {
- if (response.code === 200) {
- const responseData = typeof response.data === 'string' ? JSON.parse(response.data) : response.data
- if (responseData && responseData.status === 0 && responseData.result && responseData.result.elements && responseData.result.elements.length > 0) {
- const distanceInKm = responseData.result.elements[0].distance / 1000
- resolve(distanceInKm)
- } else {
- reject(new Error('璺濈璁$畻鎺ュ彛杩斿洖鏁版嵁鏍煎紡涓嶆纭�'))
- }
- } else {
- reject(new Error('璺濈璁$畻鎺ュ彛璋冪敤澶辫触'))
- }
- }).catch(error => {
- reject(error)
- })
+ // 鎼滅储鍑哄彂鍦板湴鍧�
+ searchStartAddress(keyword) {
+ baiduPlaceSuggestion(keyword, this.searchRegion).then(response => {
+ if (response.code === 200 && response.data) {
+ this.startSuggestions = response.data
+ this.showStartSuggestions = true
+ } else {
+ this.startSuggestions = []
+ this.showStartSuggestions = false
+ }
+ }).catch(error => {
+ console.error('鎼滅储鍑哄彂鍦板湴鍧�澶辫触:', error)
+ this.startSuggestions = []
+ this.showStartSuggestions = false
})
},
- closeMapSelector() {
- this.$refs.mapPopup.close()
- this.mapSelectorType = ''
+ // 鍑哄彂鍦拌緭鍏ユ鑾峰緱鐒︾偣
+ onStartLocationFocus() {
+ if (this.taskForm.startLocation && this.startSuggestions.length > 0) {
+ this.showStartSuggestions = true
+ }
+ },
+
+ // 閫夋嫨鍑哄彂鍦板湴鍧�寤鸿
+ selectStartSuggestion(item) {
+ this.taskForm.startLocation = item.name
+ this.showStartSuggestions = false
+ this.startSuggestions = []
+
+ // 鑾峰彇鍦板潃鍧愭爣
+ if (item.location && item.location.lng && item.location.lat) {
+ this.addressCoordinates.startLocation = {
+ lon: item.location.lng,
+ lat: item.location.lat
+ }
+ } else {
+ // 濡傛灉娌℃湁鍧愭爣锛岄渶瑕侀�氳繃鍦板潃鑾峰彇鍧愭爣
+ this.getCoordinatesByAddress(item.name, 'start')
+ }
+
+ // 濡傛灉涓や釜鍦板潃閮藉凡閫夋嫨锛岃嚜鍔ㄨ绠楄窛绂�
+ if (this.taskForm.endLocation && this.addressCoordinates.endLocation.lon) {
+ this.calculateDistance()
+ }
+ },
+
+ // 鐩殑鍦拌緭鍏ョ洃鍚�
+ onEndLocationInput(e) {
+ const keyword = e.detail.value
+ this.taskForm.endLocation = keyword
+
+ if (this.endSearchTimer) {
+ clearTimeout(this.endSearchTimer)
+ }
+
+ if (!keyword || keyword.trim() === '') {
+ this.endSuggestions = []
+ this.showEndSuggestions = false
+ return
+ }
+
+ // 闃叉姈澶勭悊
+ this.endSearchTimer = setTimeout(() => {
+ this.searchEndAddress(keyword)
+ }, 300)
+ },
+
+ // 鎼滅储鐩殑鍦板湴鍧�
+ searchEndAddress(keyword) {
+ baiduPlaceSuggestion(keyword, this.searchRegion).then(response => {
+ if (response.code === 200 && response.data) {
+ this.endSuggestions = response.data
+ this.showEndSuggestions = true
+ } else {
+ this.endSuggestions = []
+ this.showEndSuggestions = false
+ }
+ }).catch(error => {
+ console.error('鎼滅储鐩殑鍦板湴鍧�澶辫触:', error)
+ this.endSuggestions = []
+ this.showEndSuggestions = false
+ })
+ },
+
+ // 鐩殑鍦拌緭鍏ユ鑾峰緱鐒︾偣
+ onEndLocationFocus() {
+ if (this.taskForm.endLocation && this.endSuggestions.length > 0) {
+ this.showEndSuggestions = true
+ }
+ },
+
+ // 閫夋嫨鐩殑鍦板湴鍧�寤鸿
+ selectEndSuggestion(item) {
+ this.taskForm.endLocation = item.name
+ this.showEndSuggestions = false
+ this.endSuggestions = []
+
+ // 鑾峰彇鍦板潃鍧愭爣
+ if (item.location && item.location.lng && item.location.lat) {
+ this.addressCoordinates.endLocation = {
+ lon: item.location.lng,
+ lat: item.location.lat
+ }
+ } else {
+ // 濡傛灉娌℃湁鍧愭爣锛岄渶瑕侀�氳繃鍦板潃鑾峰彇鍧愭爣
+ this.getCoordinatesByAddress(item.name, 'end')
+ }
+
+ // 濡傛灉涓や釜鍦板潃閮藉凡閫夋嫨锛岃嚜鍔ㄨ绠楄窛绂�
+ if (this.taskForm.startLocation && this.addressCoordinates.startLocation.lon) {
+ this.calculateDistance()
+ }
+ },
+
+ // 閫氳繃鍦板潃鑾峰彇鍧愭爣
+ getCoordinatesByAddress(address, type) {
+ baiduGeocoding(address, this.searchRegion).then(response => {
+ if (response.code === 200 && response.data && response.data.location) {
+ if (type === 'start') {
+ this.addressCoordinates.startLocation = {
+ lon: response.data.location.lng,
+ lat: response.data.location.lat
+ }
+ } else if (type === 'end') {
+ this.addressCoordinates.endLocation = {
+ lon: response.data.location.lng,
+ lat: response.data.location.lat
+ }
+ }
+
+ // 濡傛灉涓や釜鍦板潃閮藉凡鏈夊潗鏍囷紝鑷姩璁$畻璺濈
+ if (this.addressCoordinates.startLocation.lon && this.addressCoordinates.endLocation.lon) {
+ this.calculateDistance()
+ }
+ }
+ }).catch(error => {
+ console.error('鑾峰彇鍦板潃鍧愭爣澶辫触:', error)
+ })
+ },
+
+ // 璁$畻涓ゅ湴涔嬮棿鐨勮窛绂�
+ calculateDistance() {
+ if (!this.taskForm.startLocation || !this.taskForm.endLocation) {
+ return
+ }
+
+ // 浣跨敤鐧惧害鍦板浘璁$畻璺濈(缁勫悎鎺ュ彛)
+ baiduDistanceByAddress(this.taskForm.startLocation, this.searchRegion, this.taskForm.endLocation, this.searchRegion).then(response => {
+ if (response.code === 200 && response.data) {
+ // 鐧惧害鍦板浘杩斿洖鐨勮窛绂诲崟浣嶆槸绫�,闇�瑕佽浆鎹负鍏噷
+ const distanceInMeters = response.data.distance
+ const distanceInKm = distanceInMeters / 1000
+ this.taskForm.distance = distanceInKm.toFixed(2)
+
+ console.log('璺濈璁$畻鎴愬姛:', distanceInMeters, '绫� =', distanceInKm, '鍏噷')
+
+ // 鍚屾椂鏇存柊鍧愭爣淇℃伅
+ if (response.data.fromLocation) {
+ this.addressCoordinates.startLocation = {
+ lon: response.data.fromLocation.lng,
+ lat: response.data.fromLocation.lat
+ }
+ }
+ if (response.data.toLocation) {
+ this.addressCoordinates.endLocation = {
+ lon: response.data.toLocation.lng,
+ lat: response.data.toLocation.lat
+ }
+ }
+ }
+ }).catch(error => {
+ console.error('璁$畻璺濈澶辫触:', error)
+ this.$modal.showToast('璁$畻璺濈澶辫触,璇锋墜鍔ㄨ緭鍏�')
+ })
},
validateForm() {
@@ -413,10 +561,17 @@
},
buildSubmitData() {
+ // 璋冭瘯锛氭墦鍗板綋鍓嶇敤鎴蜂俊鎭�
+ console.log('褰撳墠鐢ㄦ埛淇℃伅:', this.currentUser)
+ console.log('鐢ㄦ埛ID:', this.currentUser.id)
+ console.log('Vuex State:', this.$store.state.user)
+
const submitData = {
taskDescription: this.taskForm.taskDescription,
taskType: this.taskForm.taskType,
vehicleIds: this.taskForm.vehicleId ? [this.taskForm.vehicleId] : [],
+ assigneeId: this.currentUser.id || this.$store.state.user.userId, // 涓昏鎵ц浜�
+ assigneeIds: (this.currentUser.id || this.$store.state.user.userId) ? [this.currentUser.id || this.$store.state.user.userId] : [], // 鎵ц浜哄憳ID鍒楄〃
plannedStartTime: this.taskForm.plannedStartTime,
plannedEndTime: this.taskForm.plannedEndTime,
departureAddress: this.taskForm.startLocation,
@@ -425,13 +580,16 @@
remark: this.taskForm.remark
}
- if (this.addressCoordinates.startLocation) {
- submitData.departureLongitude = this.addressCoordinates.startLocation.lng
+ // 璋冭瘯锛氭墦鍗版彁浜ゆ暟鎹�
+ console.log('鎻愪氦鏁版嵁:', submitData)
+
+ if (this.addressCoordinates.startLocation && this.addressCoordinates.startLocation.lon) {
+ submitData.departureLongitude = this.addressCoordinates.startLocation.lon
submitData.departureLatitude = this.addressCoordinates.startLocation.lat
}
- if (this.addressCoordinates.endLocation) {
- submitData.destinationLongitude = this.addressCoordinates.endLocation.lng
+ if (this.addressCoordinates.endLocation && this.addressCoordinates.endLocation.lon) {
+ submitData.destinationLongitude = this.addressCoordinates.endLocation.lon
submitData.destinationLatitude = this.addressCoordinates.endLocation.lat
}
@@ -450,9 +608,18 @@
addTask(submitData).then(response => {
this.loading = false
this.$modal.showToast('浠诲姟鍒涘缓鎴愬姛')
+
+ // 寤惰繜璺宠浆锛岃鐢ㄦ埛鐪嬪埌鎴愬姛鎻愮ず
setTimeout(() => {
- this.$tab.navigateTo('/pages/task/index')
- }, 1500)
+ // 璺宠浆鍒颁换鍔″垪琛ㄥ苟瑙﹀彂鍒锋柊
+ uni.switchTab({
+ url: '/pages/task/index',
+ success: () => {
+ // 浣跨敤浜嬩欢鎬荤嚎閫氱煡浠诲姟鍒楄〃椤甸潰鍒锋柊
+ uni.$emit('refreshTaskList')
+ }
+ })
+ }, 1000)
}).catch(error => {
this.loading = false
console.error('浠诲姟鍒涘缓澶辫触:', error)
@@ -540,6 +707,60 @@
border-radius: 10rpx;
font-size: 28rpx;
}
+
+ // 鍦板潃杈撳叆瀹瑰櫒
+ .address-input-container {
+ position: relative;
+
+ .form-input {
+ width: 100%;
+ height: 70rpx;
+ padding: 0 20rpx;
+ border: 1rpx solid #eee;
+ border-radius: 10rpx;
+ font-size: 28rpx;
+ box-sizing: border-box;
+ }
+
+ .address-suggestions {
+ position: absolute;
+ top: 75rpx;
+ left: 0;
+ right: 0;
+ max-height: 400rpx;
+ overflow-y: auto;
+ background-color: white;
+ border: 1rpx solid #eee;
+ border-radius: 10rpx;
+ box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.1);
+ z-index: 100;
+
+ .address-suggestion-item {
+ padding: 20rpx;
+ border-bottom: 1rpx solid #f0f0f0;
+
+ &:last-child {
+ border-bottom: none;
+ }
+
+ &:active {
+ background-color: #f5f5f5;
+ }
+
+ .suggestion-name {
+ font-size: 28rpx;
+ color: #333;
+ margin-bottom: 8rpx;
+ font-weight: 500;
+ }
+
+ .suggestion-address {
+ font-size: 24rpx;
+ color: #999;
+ }
+ }
+ }
+ }
}
.form-actions {
@@ -562,34 +783,6 @@
}
}
- .map-popup-container {
- height: 80vh;
- background-color: white;
- border-top-left-radius: 20rpx;
- border-top-right-radius: 20rpx;
- overflow: hidden;
-
- .popup-header {
- display: flex;
- justify-content: space-between;
- align-items: center;
- padding: 20rpx 30rpx;
- border-bottom: 1rpx solid #f0f0f0;
-
- .popup-title {
- font-size: 32rpx;
- font-weight: bold;
- color: #333;
- }
-
- .close-btn {
- width: 50rpx;
- height: 50rpx;
- display: flex;
- align-items: center;
- justify-content: center;
- }
- }
- }
+
}
</style>
diff --git a/app/pages/task/detail.vue b/app/pages/task/detail.vue
index e28d9e9..ffd445d 100644
--- a/app/pages/task/detail.vue
+++ b/app/pages/task/detail.vue
@@ -135,7 +135,7 @@
</view>
<view class="info-item" v-if="taskDetail.emergencyInfo.patientCondition">
<view class="label">鐥呮儏鎻忚堪</view>
- <view class="value">{{ taskDetail.emergencyInfo.patientCondition }}</view>
+ <view class="value" style="white-space: pre-line;">{{ taskDetail.emergencyInfo.patientCondition }}</view>
</view>
</view>
@@ -269,8 +269,14 @@
<!-- 鎿嶄綔鎸夐挳鍖哄煙 -->
<view class="action-buttons" v-if="taskDetail">
- <!-- 寰呭鐞嗙姸鎬�: 鏄剧ず鍑哄彂銆佸彇娑� -->
+ <!-- 寰呭鐞嗙姸鎬�: 鏄剧ず缂栬緫銆佸嚭鍙戙�佸彇娑� -->
<template v-if="taskDetail.taskStatus === 'PENDING'">
+ <button
+ class="action-btn edit"
+ @click="handleEdit"
+ >
+ 淇敼
+ </button>
<button
class="action-btn primary"
@click="handleTaskAction('depart')"
@@ -285,8 +291,14 @@
</button>
</template>
- <!-- 鍑哄彂涓姸鎬�: 鏄剧ず宸插埌杈俱�佸己鍒剁粨鏉� -->
+ <!-- 鍑哄彂涓姸鎬�: 鏄剧ず缂栬緫銆佸凡鍒拌揪銆佸己鍒剁粨鏉� -->
<template v-else-if="taskDetail.taskStatus === 'DEPARTING'">
+ <button
+ class="action-btn edit"
+ @click="handleEdit"
+ >
+ 淇敼
+ </button>
<button
class="action-btn primary"
@click="handleTaskAction('arrive')"
@@ -301,8 +313,14 @@
</button>
</template>
- <!-- 宸插埌杈剧姸鎬�: 鏄剧ず宸茶繑绋� -->
+ <!-- 宸插埌杈剧姸鎬�: 鏄剧ず缂栬緫銆佸凡杩旂▼ -->
<template v-else-if="taskDetail.taskStatus === 'ARRIVED'">
+ <button
+ class="action-btn edit"
+ @click="handleEdit"
+ >
+ 淇敼
+ </button>
<button
class="action-btn primary"
@click="handleTaskAction('return')"
@@ -311,8 +329,14 @@
</button>
</template>
- <!-- 杩旂▼涓姸鎬�: 鏄剧ず宸插畬鎴� -->
+ <!-- 杩旂▼涓姸鎬�: 鏄剧ず缂栬緫銆佸凡瀹屾垚 -->
<template v-else-if="taskDetail.taskStatus === 'RETURNING'">
+ <button
+ class="action-btn edit"
+ @click="handleEdit"
+ >
+ 淇敼
+ </button>
<button
class="action-btn primary"
@click="handleTaskAction('complete')"
@@ -409,6 +433,12 @@
this.taskId = options.id
this.loadTaskDetail()
},
+ onShow() {
+ // 姣忔椤甸潰鏄剧ず鏃堕噸鏂板姞杞芥暟鎹紝纭繚浠庣紪杈戦〉闈㈣繑鍥炲悗鑳界湅鍒版渶鏂版暟鎹�
+ if (this.taskId) {
+ this.loadTaskDetail()
+ }
+ },
methods: {
// 鍔犺浇浠诲姟璇︽儏
loadTaskDetail() {
@@ -420,11 +450,12 @@
getTask(this.taskId).then(response => {
this.taskDetail = response.data || response
// 璋冭瘯锛氭墦鍗拌繑鍥炵殑鏁版嵁
- // console.log('浠诲姟璇︽儏瀹屾暣鏁版嵁:', JSON.stringify(this.taskDetail, null, 2))
- // console.log('浠诲姟绫诲瀷瀛楁鍊�:', this.taskDetail.taskType)
- // console.log('浠诲姟鐘舵�佸瓧娈靛��:', this.taskDetail.taskStatus)
- // console.log('鍑哄彂鍦板潃:', this.taskDetail.departureAddress)
- // console.log('鐩殑鍦板潃:', this.taskDetail.destinationAddress)
+ console.log('浠诲姟璇︽儏瀹屾暣鏁版嵁:', JSON.stringify(this.taskDetail, null, 2))
+ console.log('浠诲姟绫诲瀷瀛楁鍊�:', this.taskDetail.taskType)
+ console.log('浠诲姟鐘舵�佸瓧娈靛��:', this.taskDetail.taskStatus)
+ console.log('鍑哄彂鍦板潃:', this.taskDetail.departureAddress)
+ console.log('鐩殑鍦板潃:', this.taskDetail.destinationAddress)
+ console.log('杞繍浠诲姟淇℃伅 (emergencyInfo):', this.taskDetail.emergencyInfo)
}).catch(error => {
console.error('鍔犺浇浠诲姟璇︽儏澶辫触:', error)
this.$modal.showToast('鍔犺浇浠诲姟璇︽儏澶辫触')
@@ -473,6 +504,41 @@
// 杩斿洖涓婁竴椤�
goBack() {
uni.navigateBack()
+ },
+
+ // 澶勭悊缂栬緫鎸夐挳
+ handleEdit() {
+ if (!this.taskDetail) {
+ this.$modal.showToast('浠诲姟淇℃伅涓嶅瓨鍦�')
+ return
+ }
+
+ // 妫�鏌ヤ换鍔$姸鎬侊紝宸插畬鎴愭垨宸插彇娑堢殑浠诲姟涓嶈兘缂栬緫
+ if (this.isTaskFinished) {
+ this.$modal.showToast('宸插畬鎴愭垨宸插彇娑堢殑浠诲姟涓嶈兘缂栬緫')
+ return
+ }
+
+ const taskType = this.taskDetail.taskType
+ const taskId = this.taskDetail.taskId
+
+ // 鏍规嵁浠诲姟绫诲瀷璺宠浆鍒颁笉鍚岀殑缂栬緫椤甸潰
+ if (taskType === 'EMERGENCY_TRANSFER') {
+ // 杞繍浠诲姟锛氳烦杞埌杞繍浠诲姟缂栬緫椤甸潰
+ uni.navigateTo({
+ url: `/pages/task/edit-emergency?id=${taskId}`
+ })
+ } else if (taskType === 'WELFARE') {
+ // 绂忕杞︿换鍔★細璺宠浆鍒扮绁楄溅缂栬緫椤甸潰
+ uni.navigateTo({
+ url: `/pages/task/edit-welfare?id=${taskId}`
+ })
+ } else {
+ // 鍏朵粬浠诲姟锛氳烦杞埌閫氱敤浠诲姟缂栬緫椤甸潰
+ uni.navigateTo({
+ url: `/pages/task/edit?id=${taskId}`
+ })
+ }
},
// 鑾峰彇鐘舵�佹枃鏈�
@@ -1095,6 +1161,11 @@
background-color: #f0f0f0;
color: #333;
+ &.edit {
+ background-color: #ff9500;
+ color: white;
+ }
+
&.primary {
background-color: #007AFF;
color: white;
diff --git a/app/pages/task/edit-emergency.vue b/app/pages/task/edit-emergency.vue
new file mode 100644
index 0000000..2dd9009
--- /dev/null
+++ b/app/pages/task/edit-emergency.vue
@@ -0,0 +1,1015 @@
+<template>
+ <scroll-view class="edit-emergency-task-container" scroll-y="true">
+ <view class="form-header">
+ <view class="back-btn" @click="goBack">
+ <uni-icons type="arrowleft" size="20"></uni-icons>
+ </view>
+ <view class="title">缂栬緫杞繍浠诲姟</view>
+ </view>
+
+ <view class="form-section" v-if="taskDetail">
+ <!-- 浣跨敤杞﹁締閫夋嫨鍣ㄧ粍浠� -->
+ <VehicleSelector
+ label="浠诲姟杞﹁締"
+ v-model="selectedVehicleId"
+ :dept-id="currentUser.deptId"
+ vehicle-type="EMERGENCY"
+ :auto-select-bound="false"
+ @change="onVehicleChange"
+ />
+
+ <view class="form-item">
+ <OrganizationSelector
+ v-model="selectedOrganizationId"
+ :required="true"
+ :auto-select-user-dept="false"
+ @change="onOrganizationChange"
+ />
+ </view>
+
+ <view class="form-item">
+ <view class="form-label required">杞繍鏃堕棿</view>
+ <uni-datetime-picker
+ v-model="taskForm.transferTime"
+ type="datetime"
+ :placeholder="'璇烽�夋嫨杞繍鏃堕棿'"
+ class="form-input"
+ />
+ </view>
+
+ <view class="form-section-title">鎮h�呬俊鎭�</view>
+ <view class="form-item">
+ <view class="form-label required">鑱旂郴浜�</view>
+ <input
+ class="form-input"
+ placeholder="璇疯緭鍏ヨ仈绯讳汉"
+ v-model="taskForm.patient.contact"
+ />
+ </view>
+
+ <view class="form-item">
+ <view class="form-label required">鑱旂郴鐢佃瘽</view>
+ <input
+ class="form-input"
+ type="number"
+ placeholder="璇疯緭鍏ヨ仈绯荤數璇�"
+ v-model="taskForm.patient.phone"
+ />
+ </view>
+
+ <view class="form-item">
+ <view class="form-label required">鎮h�呭鍚�</view>
+ <input
+ class="form-input"
+ placeholder="璇疯緭鍏ユ偅鑰呭鍚�"
+ v-model="taskForm.patient.name"
+ />
+ </view>
+
+ <view class="form-item">
+ <view class="form-label">鎬у埆</view>
+ <view class="radio-group">
+ <label class="radio-item">
+ <radio value="male" :checked="taskForm.patient.gender === 'male'" @click="taskForm.patient.gender = 'male'" />
+ <text>鐢�</text>
+ </label>
+ <label class="radio-item">
+ <radio value="female" :checked="taskForm.patient.gender === 'female'" @click="taskForm.patient.gender = 'female'" />
+ <text>濂�</text>
+ </label>
+ </view>
+ </view>
+
+ <view class="form-item">
+ <view class="form-label">鎮h�呰韩浠借瘉</view>
+ <input
+ class="form-input"
+ type="idcard"
+ placeholder="璇疯緭鍏ユ偅鑰呰韩浠借瘉鍙�"
+ v-model="taskForm.patient.idCard"
+ />
+ </view>
+
+ <DiseaseSelector
+ v-model="selectedDiseases"
+ :other-description.sync="taskForm.patient.otherCondition"
+ @change="onDiseaseChange"
+ />
+
+ <view class="form-section-title">杞嚭鍖婚櫌淇℃伅</view>
+ <HospitalSelector
+ label="鍖洪櫌鍚嶇О"
+ address-label="杞嚭鍦板潃"
+ :required="true"
+ v-model="taskForm.hospitalOut"
+ :dept-id="selectedOrganizationId"
+ @change="onHospitalOutChange"
+ @address-selected="onHospitalOutAddressSelected"
+ />
+
+ <view class="form-section-title">杞叆鍖婚櫌淇℃伅</view>
+ <HospitalSelector
+ label="鍖婚櫌鍚嶇О"
+ address-label="杞叆鍦板潃"
+ :required="true"
+ v-model="taskForm.hospitalIn"
+ :dept-id="selectedOrganizationId"
+ @change="onHospitalInChange"
+ @address-selected="onHospitalInAddressSelected"
+ />
+
+ <view class="form-item">
+ <view class="form-label">杞繍璺濈</view>
+ <input
+ class="form-input"
+ type="digit"
+ placeholder="鑷姩璁$畻"
+ v-model="taskForm.transferDistance"
+ disabled
+ />
+ </view>
+
+ <view class="form-item">
+ <view class="form-label">鎴愪氦浠�</view>
+ <input
+ class="form-input"
+ type="digit"
+ placeholder="璇疯緭鍏ユ垚浜や环"
+ v-model="taskForm.price"
+ />
+ </view>
+
+ <view class="form-actions">
+ <button class="submit-btn" @click="submitTask" :disabled="loading">
+ {{ loading ? '淇濆瓨涓�...' : '淇濆瓨' }}
+ </button>
+ </view>
+ </view>
+
+ <view class="loading" v-else>
+ <uni-icons type="spinner-cycle" size="40" color="#007AFF"></uni-icons>
+ <text>鍔犺浇涓�...</text>
+ </view>
+
+ <!-- 鍦板浘閫夋嫨鍣ㄥ脊绐� -->
+ <uni-popup ref="mapPopup" type="bottom" :mask-click="false">
+ <view class="map-popup-container">
+ <view class="popup-header">
+ <view class="popup-title">閫夋嫨鍦板潃</view>
+ <view class="close-btn" @click="closeMapSelector">
+ <uni-icons type="closeempty" size="20" color="#999"></uni-icons>
+ </view>
+ </view>
+ <map-selector
+ :initial-address="getInitialAddress()"
+ @addressSelected="onAddressSelected"
+ ></map-selector>
+ </view>
+ </uni-popup>
+ </scroll-view>
+</template>
+
+<script>
+import { mapState } from 'vuex'
+import uniDatetimePicker from '@/uni_modules/uni-datetime-picker/components/uni-datetime-picker/uni-datetime-picker.vue'
+import uniPopup from '@/uni_modules/uni-popup/components/uni-popup/uni-popup.vue'
+import { getTask, updateTask } from "@/api/task"
+import { baiduDistanceByAddress } from "@/api/map"
+import { calculateTransferPrice } from "@/api/price"
+import MapSelector from '@/components/map-selector.vue'
+import VehicleSelector from '@/components/VehicleSelector.vue'
+import OrganizationSelector from '@/components/OrganizationSelector.vue'
+import HospitalSelector from '@/components/HospitalSelector.vue'
+import DiseaseSelector from '@/components/DiseaseSelector.vue'
+import distanceCalculator from '@/mixins/distanceCalculator.js'
+
+export default {
+ components: {
+ uniDatetimePicker,
+ uniPopup,
+ MapSelector,
+ VehicleSelector,
+ OrganizationSelector,
+ HospitalSelector,
+ DiseaseSelector
+ },
+ mixins: [distanceCalculator],
+ data() {
+ return {
+ taskId: null,
+ taskDetail: null,
+ selectedVehicleId: null,
+ selectedOrganizationId: null,
+ selectedRegion: '',
+ mapSelectorType: '',
+ // 鍦板潃鍧愭爣锛堢敤浜庢墜鍔ㄨ緭鍏ュ湴鍧�鏃惰绠楄窛绂伙級
+ addressCoordinates: {
+ hospitalOutAddress: null,
+ hospitalInAddress: null
+ },
+ selectedDiseases: [], // 宸查�夋嫨鐨勭梾鎯呭垪琛�
+ taskForm: {
+ transferTime: '',
+ patient: {
+ contact: '',
+ phone: '',
+ name: '',
+ gender: 'male',
+ idCard: '',
+ condition: '',
+ otherCondition: '' // 鍏朵粬鐥呮儏鎻忚堪
+ },
+ hospitalOut: {
+ id: null,
+ name: '',
+ department: '',
+ departmentId: null,
+ bedNumber: '',
+ address: ''
+ },
+ hospitalIn: {
+ id: null,
+ name: '',
+ department: '',
+ departmentId: null,
+ bedNumber: '',
+ address: ''
+ },
+ transferDistance: '',
+ price: ''
+ },
+ loading: false
+ }
+ },
+ computed: {
+ ...mapState({
+ currentUser: state => ({
+ name: state.user.nickName || '寮犱笁',
+ position: '鍙告満',
+ deptId: state.user.deptId || 100,
+ branchCompanyName: state.user.branchCompanyName
+ })
+ })
+ },
+ onLoad(options) {
+ if (options.id) {
+ this.taskId = options.id
+ this.loadTaskDetail()
+ } else {
+ this.$modal.showToast('浠诲姟ID涓嶈兘涓虹┖')
+ setTimeout(() => {
+ uni.navigateBack()
+ }, 1500)
+ }
+ },
+ methods: {
+ // 鍔犺浇浠诲姟璇︽儏
+ loadTaskDetail() {
+ if (!this.taskId) {
+ this.$modal.showToast('浠诲姟ID涓嶈兘涓虹┖')
+ return
+ }
+
+ console.log('寮�濮嬪姞杞戒换鍔¤鎯咃紝taskId:', this.taskId)
+
+ getTask(this.taskId).then(response => {
+ console.log('浠诲姟璇︽儏API鍝嶅簲:', response)
+
+ this.taskDetail = response.data || response
+
+ if (!this.taskDetail) {
+ console.error('浠诲姟璇︽儏涓虹┖')
+ this.$modal.showToast('浠诲姟鏁版嵁鍔犺浇澶辫触')
+ return
+ }
+
+ console.log('浠诲姟璇︽儏鏁版嵁:', this.taskDetail)
+
+ // 濉厖琛ㄥ崟鏁版嵁 - 杞繍浠诲姟鐗规湁瀛楁
+ if (this.taskDetail.emergencyInfo) {
+ const info = this.taskDetail.emergencyInfo
+ console.log('杞繍浠诲姟淇℃伅:', info)
+
+ // 杞繍鏃堕棿
+ this.taskForm.transferTime = this.taskDetail.plannedStartTime || ''
+
+ // 鎮h�呬俊鎭�
+ this.taskForm.patient.contact = info.patientContact || ''
+ this.taskForm.patient.phone = info.patientPhone || ''
+ this.taskForm.patient.name = info.patientName || ''
+ this.taskForm.patient.gender = info.patientGender || 'male'
+ this.taskForm.patient.idCard = info.patientIdCard || ''
+ this.taskForm.patient.condition = info.patientCondition || ''
+
+ // 瑙f瀽鐥呮儏淇℃伅
+ this.parseDiseaseInfo(info.patientCondition, info.diseaseIds)
+
+ // 杞嚭鍖婚櫌淇℃伅
+ this.taskForm.hospitalOut.id = info.hospitalOutId || null
+ this.taskForm.hospitalOut.name = info.hospitalOutName || ''
+ this.taskForm.hospitalOut.department = info.hospitalOutDepartment || ''
+ this.taskForm.hospitalOut.bedNumber = info.hospitalOutBedNumber || ''
+ this.taskForm.hospitalOut.address = info.hospitalOutAddress || ''
+
+ // 杞叆鍖婚櫌淇℃伅
+ this.taskForm.hospitalIn.id = info.hospitalInId || null
+ this.taskForm.hospitalIn.name = info.hospitalInName || ''
+ this.taskForm.hospitalIn.department = info.hospitalInDepartment || ''
+ this.taskForm.hospitalIn.bedNumber = info.hospitalInBedNumber || ''
+ this.taskForm.hospitalIn.address = info.hospitalInAddress || ''
+
+ // 杞繍璺濈鍜屼环鏍�
+ this.taskForm.transferDistance = info.transferDistance ? String(info.transferDistance) : ''
+ this.taskForm.price = info.transferPrice ? String(info.transferPrice) : ''
+ } else {
+ console.warn('浠诲姟璇︽儏涓病鏈塭mergencyInfo瀛楁锛屽皾璇曚粠涓诲璞¤幏鍙栨暟鎹�')
+ // 鍏煎澶勭悊锛氬鏋渆mergencyInfo涓嶅瓨鍦紝灏濊瘯浠庝富瀵硅薄鑾峰彇
+ this.taskForm.transferTime = this.taskDetail.plannedStartTime || ''
+ this.taskForm.transferDistance = this.taskDetail.estimatedDistance ? String(this.taskDetail.estimatedDistance) : ''
+ }
+
+
+ // 璁剧疆杞﹁締淇℃伅
+ if (this.taskDetail.assignedVehicles && this.taskDetail.assignedVehicles.length > 0) {
+ const firstVehicle = this.taskDetail.assignedVehicles[0]
+ this.selectedVehicleId = firstVehicle.vehicleId
+ console.log('璁剧疆杞﹁締ID:', this.selectedVehicleId)
+ } else {
+ console.warn('浠诲姟娌℃湁鍒嗛厤杞﹁締')
+ }
+
+ // 璁剧疆褰掑睘鏈烘瀯
+ if (this.taskDetail.deptId) {
+ this.selectedOrganizationId = this.taskDetail.deptId
+ console.log('璁剧疆褰掑睘鏈烘瀯ID:', this.selectedOrganizationId)
+ } else {
+ console.warn('鏈壘鍒板綊灞炴満鏋勪俊鎭�')
+ }
+
+ // 璁剧疆鍦板潃鍧愭爣锛堜娇鐢╩ixin涓殑鏂规硶锛�
+ if (this.taskDetail.departureLongitude && this.taskDetail.departureLatitude) {
+ this.setStartLocation({
+ lng: this.taskDetail.departureLongitude,
+ lat: this.taskDetail.departureLatitude
+ })
+ console.log('璁剧疆鍑哄彂鍦板潗鏍�')
+ }
+ if (this.taskDetail.destinationLongitude && this.taskDetail.destinationLatitude) {
+ this.setEndLocation({
+ lng: this.taskDetail.destinationLongitude,
+ lat: this.taskDetail.destinationLatitude
+ })
+ console.log('璁剧疆鐩殑鍦板潗鏍�')
+ }
+
+ console.log('琛ㄥ崟鏁版嵁濉厖瀹屾垚:', this.taskForm)
+ }).catch(error => {
+ console.error('鍔犺浇浠诲姟璇︽儏澶辫触:', error)
+ console.error('閿欒璇︽儏:', error.response || error.message || error)
+ this.$modal.showToast('鍔犺浇浠诲姟璇︽儏澶辫触: ' + (error.message || '缃戠粶閿欒'))
+ setTimeout(() => {
+ uni.navigateBack()
+ }, 1500)
+ })
+ },
+
+ // 杞﹁締閫夋嫨鍙樺寲
+ onVehicleChange(vehicle) {
+ console.log('閫変腑杞﹁締:', vehicle)
+ },
+
+ // 褰掑睘鏈烘瀯閫夋嫨鍙樺寲
+ onOrganizationChange(orgData) {
+ // orgData 鍖呭惈锛歞eptId, deptName, serviceOrderClass, region
+ this.selectedOrganizationId = orgData.deptId
+ console.log('閫変腑褰掑睘鏈烘瀯:', orgData.deptName, '閮ㄩ棬ID:', orgData.deptId)
+ },
+
+ // 杞嚭鍖婚櫌鍙樺寲
+ onHospitalOutChange(hospitalData) {
+ console.log('杞嚭鍖婚櫌鍙樺寲:', hospitalData)
+ // 缁勪欢宸茬粡閫氳繃 v-model 鏇存柊浜� taskForm.hospitalOut
+
+ // 濡傛灉杞叆鍦板潃宸插~鍐�,鑷姩璁$畻璺濈
+ if (this.taskForm.hospitalIn.address) {
+ // 濡傛灉涓や釜閮戒笉鏄�"瀹朵腑",浣跨敤鍖婚櫌璺濈璁$畻
+ if (hospitalData.name !== '瀹朵腑' && this.taskForm.hospitalIn.name !== '瀹朵腑') {
+ this.calculateHospitalDistance()
+ } else {
+ // 鏈変竴涓槸"瀹朵腑",浣跨敤鍦板潃璁$畻
+ this.calculateDistanceByManualAddress()
+ }
+ }
+ },
+
+ // 杞嚭鍖婚櫌鍦板潃閫夋嫨锛堝綋閫夋嫨"瀹朵腑"鏃朵娇鐢ㄧ櫨搴﹀湴鍥惧湴鍧�寤鸿锛�
+ onHospitalOutAddressSelected(data) {
+ // data 鍖呭惈锛歛ddress, location
+ if (data.location) {
+ this.addressCoordinates.hospitalOutAddress = data.location
+
+ // 濡傛灉杞叆鍦板潃涔熷凡濉啓,鑷姩璁$畻璺濈
+ if (this.taskForm.hospitalIn.address) {
+ this.calculateDistanceByManualAddress()
+ }
+ }
+ },
+
+ // 杞叆鍖婚櫌鍙樺寲
+ onHospitalInChange(hospitalData) {
+ console.log('杞叆鍖婚櫌鍙樺寲:', hospitalData)
+ // 缁勪欢宸茬粡閫氳繃 v-model 鏇存柊浜� taskForm.hospitalIn
+
+ // 濡傛灉杞嚭鍦板潃宸插~鍐�,鑷姩璁$畻璺濈
+ if (this.taskForm.hospitalOut.address) {
+ // 濡傛灉涓や釜閮戒笉鏄�"瀹朵腑",浣跨敤鍖婚櫌璺濈璁$畻
+ if (hospitalData.name !== '瀹朵腑' && this.taskForm.hospitalOut.name !== '瀹朵腑') {
+ this.calculateHospitalDistance()
+ } else {
+ // 鏈変竴涓槸"瀹朵腑",浣跨敤鍦板潃璁$畻
+ this.calculateDistanceByManualAddress()
+ }
+ }
+ },
+
+ // 杞叆鍖婚櫌鍦板潃閫夋嫨锛堝綋閫夋嫨"瀹朵腑"鏃朵娇鐢ㄧ櫨搴﹀湴鍥惧湴鍧�寤鸿锛�
+ onHospitalInAddressSelected(data) {
+ // data 鍖呭惈锛歛ddress, location
+ if (data.location) {
+ this.addressCoordinates.hospitalInAddress = data.location
+
+ // 濡傛灉杞嚭鍦板潃涔熷凡濉啓,鑷姩璁$畻璺濈
+ if (this.taskForm.hospitalOut.address) {
+ this.calculateDistanceByManualAddress()
+ }
+ }
+ },
+
+ // 鐥呮儏鍙樺寲
+ onDiseaseChange(diseases) {
+ console.log('鐥呮儏鍙樺寲:', diseases)
+ // 缁勪欢宸茬粡閫氳繃 v-model 鏇存柊浜� selectedDiseases
+ },
+
+ // 瑙f瀽鐥呮儏淇℃伅锛堜粠瀛楃涓茶В鏋愬嚭ICD-10鐤剧梾鍒楄〃锛�
+ parseDiseaseInfo(conditionText, diseaseIds) {
+ if (!conditionText) {
+ this.selectedDiseases = []
+ this.taskForm.patient.otherCondition = ''
+ return
+ }
+
+ // 瑙f瀽diseaseIds锛堥�楀彿鍒嗛殧鐨勫瓧绗︿覆杞负鏁扮粍锛�
+ const diseaseIdArray = diseaseIds ? diseaseIds.split(',').map(id => parseInt(id.trim())).filter(id => !isNaN(id)) : []
+
+ // 濡傛灉鍖呭惈"鍏朵粬锛�"鍒嗛殧绗︼紝鎷嗗垎鐥呮儏鍜屽叾浠栨弿杩�
+ if (conditionText.includes('\n鍏朵粬锛�')) {
+ const parts = conditionText.split('\n鍏朵粬锛�')
+ const diseasePart = parts[0]
+ this.taskForm.patient.otherCondition = parts[1] || ''
+
+ // 瑙f瀽鐥呮儏閮ㄥ垎
+ this.parseDiseaseList(diseasePart, diseaseIdArray)
+ } else {
+ // 娌℃湁"鍏朵粬"閮ㄥ垎锛屽叏閮ㄤ綔涓哄叾浠栨弿杩�
+ this.taskForm.patient.otherCondition = conditionText
+ this.selectedDiseases = []
+ }
+ },
+
+ // 瑙f瀽鐥呮儏鍒楄〃锛堟牸寮忥細鐤剧梾鍚�(缂栫爜)銆佺柧鐥呭悕(缂栫爜)锛�
+ parseDiseaseList(diseasePart, diseaseIdArray) {
+ if (!diseasePart) {
+ this.selectedDiseases = []
+ return
+ }
+
+ // 鍖归厤鏍煎紡锛氱柧鐥呭悕(缂栫爜)
+ const regex = /([^(]+)\(([^)]+)\)/g
+ const diseases = []
+ let match
+ let index = 0
+
+ while ((match = regex.exec(diseasePart)) !== null) {
+ const icdName = match[1].replace(/[銆�,\s]+$/, '').replace(/^[銆�,\s]+/, '').trim()
+ const icdCode = match[2].trim()
+
+ // 鍙坊鍔犵梾鎯呭悕绉颁笉涓虹┖鐨勯」
+ if (icdName) {
+ diseases.push({
+ icdName: icdName,
+ icdCode: icdCode,
+ id: diseaseIdArray && index < diseaseIdArray.length ? diseaseIdArray[index] : null
+ })
+ index++
+ }
+ }
+
+ this.selectedDiseases = diseases
+ },
+
+ // 閫夋嫨杞嚭鍖婚櫌鍦板潃
+ selectHospitalOutAddress() {
+ this.mapSelectorType = 'hospitalOut'
+ this.$refs.mapPopup.open()
+ },
+
+ // 閫夋嫨杞叆鍖婚櫌鍦板潃
+ selectHospitalInAddress() {
+ this.mapSelectorType = 'hospitalIn'
+ this.$refs.mapPopup.open()
+ },
+
+ getInitialAddress() {
+ if (this.mapSelectorType === 'hospitalOut') {
+ return this.taskForm.hospitalOut.address
+ } else if (this.mapSelectorType === 'hospitalIn') {
+ return this.taskForm.hospitalIn.address
+ }
+ return ''
+ },
+
+ onAddressSelected(address) {
+ const formattedAddress = address.title + ' - ' + address.address
+
+ if (this.mapSelectorType === 'hospitalOut') {
+ this.taskForm.hospitalOut.address = formattedAddress
+ this.setLocationByAddress('start', address)
+ } else if (this.mapSelectorType === 'hospitalIn') {
+ this.taskForm.hospitalIn.address = formattedAddress
+ this.setLocationByAddress('end', address)
+ }
+
+ // 鐩戝惉mixin涓殑璺濈璁$畻瀹屾垚浜嬩欢
+ this.$once('distance-calculated', (distance) => {
+ this.taskForm.transferDistance = this.formatDistance(distance)
+ })
+
+ this.closeMapSelector()
+ },
+
+ closeMapSelector() {
+ this.$refs.mapPopup.close()
+ this.mapSelectorType = ''
+ },
+
+ validateForm() {
+ if (!this.selectedVehicleId) {
+ this.$modal.showToast('璇烽�夋嫨浠诲姟杞﹁締')
+ return false
+ }
+
+ if (!this.selectedOrganizationId) {
+ this.$modal.showToast('璇烽�夋嫨褰掑睘鏈烘瀯')
+ return false
+ }
+
+ if (!this.taskForm.transferTime) {
+ this.$modal.showToast('璇烽�夋嫨杞繍鏃堕棿')
+ return false
+ }
+
+ if (!this.taskForm.patient.contact) {
+ this.$modal.showToast('璇疯緭鍏ヨ仈绯讳汉')
+ return false
+ }
+
+ if (!this.taskForm.patient.phone) {
+ this.$modal.showToast('璇疯緭鍏ヨ仈绯荤數璇�')
+ return false
+ }
+
+ if (!this.taskForm.patient.name) {
+ this.$modal.showToast('璇疯緭鍏ユ偅鑰呭鍚�')
+ return false
+ }
+
+ if (!this.taskForm.hospitalOut.name) {
+ this.$modal.showToast('璇疯緭鍏ヨ浆鍑哄尰闄㈠悕绉�')
+ return false
+ }
+
+ if (!this.taskForm.hospitalOut.address) {
+ this.$modal.showToast('璇烽�夋嫨杞嚭鍖婚櫌鍦板潃')
+ return false
+ }
+
+ if (!this.taskForm.hospitalIn.name) {
+ this.$modal.showToast('璇疯緭鍏ヨ浆鍏ュ尰闄㈠悕绉�')
+ return false
+ }
+
+ if (!this.taskForm.hospitalIn.address) {
+ this.$modal.showToast('璇烽�夋嫨杞叆鍖婚櫌鍦板潃')
+ return false
+ }
+
+ return true
+ },
+
+ buildSubmitData() {
+ // 鍚堝苟鐥呮儏淇℃伅锛氶�変腑鐨処CD-10鐤剧梾 + 鍏朵粬鎻忚堪
+ let conditionText = ''
+ if (this.selectedDiseases.length > 0) {
+ // 杩囨护鎺夌梾鎯呭悕绉颁负绌虹殑椤癸紝骞舵瀯寤虹梾鎯呭瓧绗︿覆
+ const diseaseNames = this.selectedDiseases
+ .filter(d => d.icdName && d.icdName.trim())
+ .map(d => `${d.icdName}(${d.icdCode})`)
+ .join('銆�')
+ if (diseaseNames) {
+ conditionText = diseaseNames
+ }
+ }
+ if (this.taskForm.patient.otherCondition && this.taskForm.patient.otherCondition.trim()) {
+ if (conditionText) {
+ conditionText += '\n鍏朵粬锛�' + this.taskForm.patient.otherCondition
+ } else {
+ conditionText = this.taskForm.patient.otherCondition
+ }
+ }
+
+ const submitData = {
+ taskId: this.taskId,
+ taskType: 'EMERGENCY_TRANSFER',
+ deptId: this.selectedOrganizationId,
+ vehicleIds: this.selectedVehicleId ? [this.selectedVehicleId] : [],
+ plannedStartTime: this.taskForm.transferTime,
+ departureAddress: this.taskForm.hospitalOut.address,
+ destinationAddress: this.taskForm.hospitalIn.address,
+ // 鐥呮儏ID鍒楄〃锛堢敤浜庡悓姝ヨ皟搴﹀崟鐨凮rdICD_ID鍙傛暟锛�
+ diseaseIds: this.selectedDiseases.map(d => d.id).filter(id => id !== null),
+ emergencyInfo: {
+ patientContact: this.taskForm.patient.contact,
+ patientPhone: this.taskForm.patient.phone,
+ patientName: this.taskForm.patient.name,
+ patientGender: this.taskForm.patient.gender,
+ patientIdCard: this.taskForm.patient.idCard,
+ patientCondition: conditionText, // 浣跨敤鍚堝苟鍚庣殑鐥呮儏淇℃伅
+ hospitalOutName: this.taskForm.hospitalOut.name,
+ hospitalOutDepartment: this.taskForm.hospitalOut.department,
+ hospitalOutBedNumber: this.taskForm.hospitalOut.bedNumber,
+ hospitalOutAddress: this.taskForm.hospitalOut.address,
+ hospitalInName: this.taskForm.hospitalIn.name,
+ hospitalInDepartment: this.taskForm.hospitalIn.department,
+ hospitalInBedNumber: this.taskForm.hospitalIn.bedNumber,
+ hospitalInAddress: this.taskForm.hospitalIn.address,
+ transferDistance: this.taskForm.transferDistance ? parseFloat(this.taskForm.transferDistance) : null,
+ transferPrice: this.taskForm.price ? parseFloat(this.taskForm.price) : null,
+ // 鐥呮儏璇︾粏淇℃伅锛堣繃婊ゆ帀绌虹殑鐥呮儏鍚嶇О锛�
+ diseases: this.selectedDiseases
+ .filter(d => d.icdName && d.icdName.trim())
+ .map(d => ({
+ icdId: d.id,
+ icdCode: d.icdCode,
+ icdName: d.icdName
+ }))
+ }
+ }
+
+ // 娣诲姞GPS鍧愭爣
+ if (this.addressCoordinates.start) {
+ submitData.departureLongitude = this.addressCoordinates.start.lng
+ submitData.departureLatitude = this.addressCoordinates.start.lat
+ }
+
+ if (this.addressCoordinates.end) {
+ submitData.destinationLongitude = this.addressCoordinates.end.lng
+ submitData.destinationLatitude = this.addressCoordinates.end.lat
+ }
+
+ return submitData
+ },
+
+ submitTask() {
+ if (!this.validateForm()) {
+ return
+ }
+
+ this.$modal.confirm('纭畾瑕佷繚瀛樹慨鏀瑰悧锛�').then(() => {
+ this.loading = true
+ const submitData = this.buildSubmitData()
+
+ console.log('鎻愪氦鏁版嵁:', JSON.stringify(submitData, null, 2))
+
+ updateTask(submitData).then(response => {
+ this.loading = false
+ console.log('浠诲姟鏇存柊鍝嶅簲:', response)
+ this.$modal.showToast('浠诲姟鏇存柊鎴愬姛')
+ setTimeout(() => {
+ uni.navigateBack()
+ }, 1500)
+ }).catch(error => {
+ this.loading = false
+ console.error('浠诲姟鏇存柊澶辫触:', error)
+ console.error('閿欒璇︽儏:', error.response || error.message || error)
+ const errorMsg = error.response?.data?.msg || error.message || '璇烽噸璇�'
+ this.$modal.showToast('浠诲姟鏇存柊澶辫触: ' + errorMsg)
+ })
+ }).catch(() => {})
+ },
+
+ goBack() {
+ uni.navigateBack()
+ },
+
+ // 鑷姩璁$畻涓や釜鍖婚櫌涔嬮棿鐨勮窛绂�
+ calculateHospitalDistance() {
+ const fromAddress = this.taskForm.hospitalOut.address
+ const toAddress = this.taskForm.hospitalIn.address
+
+ if (!fromAddress || !toAddress) {
+ console.log('鍦板潃淇℃伅涓嶅畬鏁达紝鏃犳硶璁$畻璺濈')
+ return
+ }
+
+ console.log('寮�濮嬭绠楄窛绂�:', fromAddress, '->', toAddress)
+
+ // 鏄剧ず鍔犺浇鎻愮ず
+ uni.showLoading({
+ title: '璁$畻璺濈涓�...'
+ })
+
+ // 璋冪敤鐧惧害鍦板浘API璁$畻璺濈
+ const region = this.selectedRegion || '骞垮窞'
+ baiduDistanceByAddress(fromAddress, region, toAddress, region)
+ .then(response => {
+ uni.hideLoading()
+
+ if (response.code === 200 && response.data) {
+ const distanceInMeters = response.data.distance
+ // 杞崲涓哄叕閲岋紝淇濈暀1浣嶅皬鏁�
+ const distanceInKm = (distanceInMeters / 1000).toFixed(1)
+ this.taskForm.transferDistance = distanceInKm
+
+ console.log('璺濈璁$畻鎴愬姛:', distanceInKm, 'km')
+ this.$modal.showToast(`璺濈: ${distanceInKm}鍏噷`)
+
+ // 璺濈璁$畻鎴愬姛鍚庯紝鑷姩璁$畻鎴愪氦浠�
+ this.calculatePrice()
+ } else {
+ console.error('璺濈璁$畻澶辫触:', response.msg)
+ this.$modal.showToast('璺濈璁$畻澶辫触锛岃鎵嬪姩杈撳叆')
+ }
+ })
+ .catch(error => {
+ uni.hideLoading()
+ console.error('璺濈璁$畻澶辫触:', error)
+ this.$modal.showToast('璺濈璁$畻澶辫触锛岃鎵嬪姩杈撳叆')
+ })
+ },
+
+ // 鎵嬪姩杈撳叆鍦板潃鏃惰绠楄窛绂�
+ calculateDistanceByManualAddress() {
+ const fromAddress = this.taskForm.hospitalOut.address
+ const toAddress = this.taskForm.hospitalIn.address
+
+ if (!fromAddress || !toAddress) {
+ return
+ }
+
+ console.log('璁$畻鎵嬪姩杈撳叆鍦板潃璺濈:', fromAddress, '->', toAddress)
+
+ // 鏄剧ず鍔犺浇鎻愮ず
+ uni.showLoading({
+ title: '璁$畻璺濈涓�...'
+ })
+
+ // 璋冪敤鐧惧害鍦板浘API璁$畻璺濈
+ const region = this.selectedRegion || '骞垮窞'
+ baiduDistanceByAddress(fromAddress, region, toAddress, region)
+ .then(response => {
+ uni.hideLoading()
+
+ if (response.code === 200 && response.data) {
+ const distanceInMeters = response.data.distance
+ // 杞崲涓哄叕閲岋紝淇濈暀1浣嶅皬鏁�
+ const distanceInKm = (distanceInMeters / 1000).toFixed(1)
+ this.taskForm.transferDistance = distanceInKm
+
+ console.log('璺濈璁$畻鎴愬姛:', distanceInKm, 'km')
+ this.$modal.showToast(`璺濈: ${distanceInKm}鍏噷`)
+
+ // 璺濈璁$畻鎴愬姛鍚庯紝鑷姩璁$畻鎴愪氦浠�
+ this.calculatePrice()
+ } else {
+ console.error('璺濈璁$畻澶辫触:', response.msg)
+ this.$modal.showToast('璺濈璁$畻澶辫触,璇锋墜鍔ㄨ緭鍏�')
+ }
+ })
+ .catch(error => {
+ uni.hideLoading()
+ console.error('璺濈璁$畻澶辫触:', error)
+ this.$modal.showToast('璺濈璁$畻澶辫触,璇锋墜鍔ㄨ緭鍏�')
+ })
+ },
+
+ // 璁$畻鎴愪氦浠�
+ calculatePrice() {
+ const fromAddress = this.taskForm.hospitalOut.address
+ const toAddress = this.taskForm.hospitalIn.address
+ const distance = this.taskForm.transferDistance
+
+ // 濡傛灉鍦板潃鎴栬窛绂讳笉瀹屾暣锛屼笉杩涜璁$畻
+ if (!fromAddress || !toAddress || !distance || parseFloat(distance) <= 0) {
+ console.log('鍦板潃鎴栬窛绂讳俊鎭笉瀹屾暣锛岃烦杩囨垚浜や环璁$畻')
+ return
+ }
+
+ console.log('寮�濮嬭绠楁垚浜や环:', fromAddress, '->', toAddress, '璺濈:', distance)
+
+ // 璋冪敤鎴愪氦浠疯绠楁帴鍙�
+ calculateTransferPrice({
+ fromAddress: fromAddress,
+ toAddress: toAddress,
+ distance: parseFloat(distance),
+ region: this.selectedRegion || ''
+ }).then(response => {
+ if (response.code === 200 && response.data) {
+ const price = response.data.price
+
+ // 鍙湁褰撹繑鍥炵殑浠锋牸澶т簬0鏃讹紝鎵嶈嚜鍔ㄥ~鍏呮垚浜や环
+ if (price && price > 0) {
+ this.taskForm.price = price.toFixed(2)
+ console.log('鎴愪氦浠疯绠楁垚鍔�:', price)
+ this.$modal.showToast(`鎴愪氦浠�: 楼${price.toFixed(2)}`)
+ } else {
+ console.log('鎴愪氦浠蜂负0锛屼笉鑷姩濉厖')
+ }
+ } else {
+ console.log('鎴愪氦浠疯绠楀け璐ワ紝淇濇寔鎵嬪姩杈撳叆')
+ }
+ }).catch(error => {
+ console.error('鎴愪氦浠疯绠楀け璐�:', error)
+ // 璁$畻澶辫触鏃朵笉鎻愮ず鐢ㄦ埛锛屽厑璁哥敤鎴锋墜鍔ㄨ緭鍏�
+ })
+ }
+ }
+}
+</script>
+
+<style lang="scss" scoped>
+.edit-emergency-task-container {
+ padding: 20rpx;
+ background-color: #f5f5f5;
+ min-height: 100vh;
+
+ .form-header {
+ display: flex;
+ align-items: center;
+ padding: 20rpx 0;
+ margin-bottom: 30rpx;
+
+ .back-btn {
+ width: 60rpx;
+ height: 60rpx;
+ border-radius: 50%;
+ background-color: #f0f0f0;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ margin-right: 20rpx;
+ }
+
+ .title {
+ font-size: 36rpx;
+ font-weight: bold;
+ color: #333;
+ }
+ }
+
+ .form-section {
+ background-color: white;
+ border-radius: 15rpx;
+ padding: 30rpx;
+ box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05);
+
+ .form-section-title {
+ font-size: 32rpx;
+ font-weight: bold;
+ margin: 40rpx 0 20rpx 0;
+ padding-bottom: 10rpx;
+ border-bottom: 1rpx solid #f0f0f0;
+ }
+
+ .form-item {
+ margin-bottom: 40rpx;
+
+ .form-label {
+ font-size: 28rpx;
+ margin-bottom: 15rpx;
+ color: #333;
+
+ &.required::before {
+ content: '*';
+ color: #ff3b30;
+ margin-right: 4rpx;
+ }
+ }
+
+ .form-input {
+ height: 70rpx;
+ padding: 0 20rpx;
+ border: 1rpx solid #eee;
+ border-radius: 10rpx;
+ font-size: 28rpx;
+
+ &.picker-input {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ }
+
+ &[disabled] {
+ background-color: #f5f5f5;
+ color: #999;
+ }
+ }
+
+ .form-textarea {
+ width: 100%;
+ min-height: 150rpx;
+ padding: 20rpx;
+ border: 1rpx solid #eee;
+ border-radius: 10rpx;
+ font-size: 28rpx;
+ }
+
+ .radio-group {
+ display: flex;
+ gap: 40rpx;
+
+ .radio-item {
+ display: flex;
+ align-items: center;
+ gap: 10rpx;
+ font-size: 28rpx;
+ color: #333;
+ }
+ }
+ }
+
+ .form-actions {
+ margin-top: 50rpx;
+ text-align: center;
+
+ .submit-btn {
+ width: 80%;
+ height: 80rpx;
+ background-color: #007AFF;
+ color: white;
+ border-radius: 10rpx;
+ font-size: 32rpx;
+
+ &[disabled] {
+ background-color: #ccc;
+ color: #999;
+ }
+ }
+ }
+ }
+
+ .loading {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ height: 400rpx;
+ color: #999;
+
+ text {
+ margin-top: 20rpx;
+ font-size: 28rpx;
+ }
+ }
+
+ .map-popup-container {
+ height: 80vh;
+ background-color: white;
+ border-top-left-radius: 20rpx;
+ border-top-right-radius: 20rpx;
+ overflow: hidden;
+
+ .popup-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 20rpx 30rpx;
+ border-bottom: 1rpx solid #f0f0f0;
+
+ .popup-title {
+ font-size: 32rpx;
+ font-weight: bold;
+ color: #333;
+ }
+
+ .close-btn {
+ width: 50rpx;
+ height: 50rpx;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ }
+ }
+ }
+}
+</style>
diff --git a/app/pages/task/edit-welfare.vue b/app/pages/task/edit-welfare.vue
new file mode 100644
index 0000000..68c0684
--- /dev/null
+++ b/app/pages/task/edit-welfare.vue
@@ -0,0 +1,569 @@
+<template>
+ <scroll-view class="edit-welfare-task-container" scroll-y="true">
+ <view class="form-header">
+ <view class="back-btn" @click="goBack">
+ <uni-icons type="arrowleft" size="20"></uni-icons>
+ </view>
+ <view class="title">缂栬緫绂忕杞︿换鍔�</view>
+ </view>
+
+ <view class="form-section" v-if="taskDetail">
+ <!-- 浣跨敤杞﹁締閫夋嫨鍣ㄧ粍浠� -->
+ <VehicleSelector
+ label="浠诲姟杞﹁締"
+ v-model="selectedVehicleId"
+ :dept-id="currentUser.deptId"
+ vehicle-type="WELFARE"
+ :auto-select-bound="false"
+ @change="onVehicleChange"
+ />
+
+ <view class="form-item">
+ <view class="form-label">鎵ц浠诲姟浜哄憳</view>
+ <view class="staff-list">
+ <view class="staff-item">
+ <text>{{ currentUser.name }} ({{ currentUser.position }})</text>
+ <uni-icons type="checkmarkempty" size="20" color="#007AFF"></uni-icons>
+ </view>
+ <view
+ class="staff-item"
+ v-for="(staff, index) in additionalStaff"
+ :key="index"
+ @click="removeStaff(index)"
+ >
+ <text>{{ staff.name }} ({{ staff.position }})</text>
+ <uni-icons type="closeempty" size="20" color="#ff4d4f"></uni-icons>
+ </view>
+ <view class="add-staff" @click="addStaff">
+ <uni-icons type="plusempty" size="20" color="#007AFF"></uni-icons>
+ <text>娣诲姞浜哄憳</text>
+ </view>
+ </view>
+ </view>
+
+ <view class="form-item">
+ <view class="form-label">褰掑睘鏈烘瀯</view>
+ <picker mode="selector" :range="organizations" @change="onOrganizationChange">
+ <view class="form-input picker-input">
+ {{ selectedOrganization || '璇烽�夋嫨褰掑睘鏈烘瀯' }}
+ <uni-icons type="arrowright" size="16" color="#999"></uni-icons>
+ </view>
+ </picker>
+ </view>
+
+ <view class="form-item">
+ <view class="form-label">鏈嶅姟鏃堕棿</view>
+ <uni-datetime-picker
+ v-model="taskForm.serviceTime"
+ type="datetime"
+ :placeholder="'璇烽�夋嫨鏈嶅姟鏃堕棿'"
+ class="form-input"
+ />
+ </view>
+
+ <view class="form-section-title">涔樺淇℃伅</view>
+ <view class="form-item">
+ <view class="form-label">鑱旂郴浜�</view>
+ <input
+ class="form-input"
+ placeholder="璇疯緭鍏ヨ仈绯讳汉"
+ v-model="taskForm.passenger.contact"
+ />
+ </view>
+
+ <view class="form-item">
+ <view class="form-label">鑱旂郴鐢佃瘽</view>
+ <input
+ class="form-input"
+ type="number"
+ placeholder="璇疯緭鍏ヨ仈绯荤數璇�"
+ v-model="taskForm.passenger.phone"
+ />
+ </view>
+
+ <view class="form-item">
+ <view class="form-label">鍑哄彂鍦板潃</view>
+ <view class="form-input picker-input" @click="selectStartAddress">
+ {{ taskForm.startAddress || '璇烽�夋嫨鍑哄彂鍦板潃' }}
+ <uni-icons type="arrowright" size="16" color="#999"></uni-icons>
+ </view>
+ </view>
+
+ <view class="form-item">
+ <view class="form-label">鐩殑鍦板潃</view>
+ <view class="form-input picker-input" @click="selectEndAddress">
+ {{ taskForm.endAddress || '璇烽�夋嫨鐩殑鍦板潃' }}
+ <uni-icons type="arrowright" size="16" color="#999"></uni-icons>
+ </view>
+ </view>
+
+ <view class="form-item">
+ <view class="form-label">鍏噷鏁�</view>
+ <input
+ class="form-input"
+ type="digit"
+ placeholder="璇疯緭鍏ュ叕閲屾暟"
+ v-model="taskForm.distance"
+ />
+ </view>
+
+ <view class="form-item">
+ <view class="form-label">鎴愪氦浠�</view>
+ <input
+ class="form-input"
+ type="digit"
+ placeholder="璇疯緭鍏ユ垚浜や环"
+ v-model="taskForm.price"
+ />
+ </view>
+
+ <view class="form-actions">
+ <button class="submit-btn" @click="submitTask" :disabled="loading">
+ {{ loading ? '淇濆瓨涓�...' : '淇濆瓨' }}
+ </button>
+ </view>
+ </view>
+
+ <view class="loading" v-else>
+ <uni-icons type="spinner-cycle" size="40" color="#007AFF"></uni-icons>
+ <text>鍔犺浇涓�...</text>
+ </view>
+
+ <!-- 鍦板浘閫夋嫨鍣ㄥ脊绐� -->
+ <uni-popup ref="mapPopup" type="bottom" :mask-click="false">
+ <view class="map-popup-container">
+ <view class="popup-header">
+ <view class="popup-title">閫夋嫨鍦板潃</view>
+ <view class="close-btn" @click="closeMapSelector">
+ <uni-icons type="closeempty" size="20" color="#999"></uni-icons>
+ </view>
+ </view>
+ <map-selector
+ :initial-address="getInitialAddress()"
+ @addressSelected="onAddressSelected"
+ ></map-selector>
+ </view>
+ </uni-popup>
+ </scroll-view>
+</template>
+
+<script>
+import { mapState } from 'vuex'
+import uniDatetimePicker from '@/uni_modules/uni-datetime-picker/components/uni-datetime-picker/uni-datetime-picker.vue'
+import uniPopup from '@/uni_modules/uni-popup/components/uni-popup/uni-popup.vue'
+import { getTask, updateTask } from "@/api/task"
+import MapSelector from '@/components/map-selector.vue'
+import VehicleSelector from '@/components/VehicleSelector.vue'
+import distanceCalculator from '@/mixins/distanceCalculator.js'
+
+export default {
+ components: {
+ uniDatetimePicker,
+ uniPopup,
+ MapSelector,
+ VehicleSelector
+ },
+ mixins: [distanceCalculator],
+ data() {
+ return {
+ taskId: null,
+ taskDetail: null,
+ selectedVehicleId: null,
+ selectedOrganization: '',
+ mapSelectorType: '',
+ taskForm: {
+ serviceTime: '',
+ passenger: {
+ contact: '',
+ phone: ''
+ },
+ startAddress: '',
+ endAddress: '',
+ distance: '',
+ price: ''
+ },
+ organizations: ['骞垮窞鍒嗗叕鍙�', '娣卞湷鍒嗗叕鍙�', '鐝犳捣鍒嗗叕鍙�', '浣涘北鍒嗗叕鍙�'],
+ additionalStaff: [],
+ loading: false
+ }
+ },
+ computed: {
+ ...mapState({
+ currentUser: state => ({
+ name: state.user.nickName || '寮犱笁',
+ position: '鍙告満',
+ deptId: state.user.deptId || 100
+ })
+ })
+ },
+ onLoad(options) {
+ if (options.id) {
+ this.taskId = options.id
+ this.loadTaskDetail()
+ } else {
+ this.$modal.showToast('浠诲姟ID涓嶈兘涓虹┖')
+ setTimeout(() => {
+ uni.navigateBack()
+ }, 1500)
+ }
+ },
+ methods: {
+ // 鍔犺浇浠诲姟璇︽儏
+ loadTaskDetail() {
+ if (!this.taskId) {
+ this.$modal.showToast('浠诲姟ID涓嶈兘涓虹┖')
+ return
+ }
+
+ getTask(this.taskId).then(response => {
+ this.taskDetail = response.data || response
+
+ // 濉厖琛ㄥ崟鏁版嵁 - 绂忕杞︿换鍔$壒鏈夊瓧娈�
+ if (this.taskDetail.welfareInfo) {
+ this.taskForm.serviceTime = this.taskDetail.plannedStartTime || ''
+ this.taskForm.passenger.contact = this.taskDetail.welfareInfo.passengerContact || ''
+ this.taskForm.passenger.phone = this.taskDetail.welfareInfo.passengerPhone || ''
+ this.taskForm.startAddress = this.taskDetail.welfareInfo.pickupAddress || ''
+ this.taskForm.endAddress = this.taskDetail.welfareInfo.destinationAddress || ''
+ this.taskForm.distance = this.taskDetail.welfareInfo.serviceDistance || ''
+ this.taskForm.price = this.taskDetail.welfareInfo.servicePrice || ''
+ }
+
+ // 璁剧疆杞﹁締淇℃伅
+ if (this.taskDetail.assignedVehicles && this.taskDetail.assignedVehicles.length > 0) {
+ const firstVehicle = this.taskDetail.assignedVehicles[0]
+ this.selectedVehicleId = firstVehicle.vehicleId
+ }
+
+ // 璁剧疆鍦板潃鍧愭爣锛堜娇鐢╩ixin涓殑鏂规硶锛�
+ if (this.taskDetail.departureLongitude && this.taskDetail.departureLatitude) {
+ this.setStartLocation({
+ lng: this.taskDetail.departureLongitude,
+ lat: this.taskDetail.departureLatitude
+ })
+ }
+ if (this.taskDetail.destinationLongitude && this.taskDetail.destinationLatitude) {
+ this.setEndLocation({
+ lng: this.taskDetail.destinationLongitude,
+ lat: this.taskDetail.destinationLatitude
+ })
+ }
+ }).catch(error => {
+ console.error('鍔犺浇浠诲姟璇︽儏澶辫触:', error)
+ this.$modal.showToast('鍔犺浇浠诲姟璇︽儏澶辫触')
+ setTimeout(() => {
+ uni.navigateBack()
+ }, 1500)
+ })
+ },
+
+ // 杞﹁締閫夋嫨鍙樺寲
+ onVehicleChange(vehicle) {
+ // 缁勪欢宸茬粡澶勭悊浜唖electedVehicleId鐨勬洿鏂�
+ console.log('閫変腑杞﹁締:', vehicle)
+ },
+
+ onOrganizationChange(e) {
+ this.selectedOrganization = this.organizations[e.detail.value]
+ },
+
+ selectStartAddress() {
+ this.mapSelectorType = 'startAddress'
+ this.$refs.mapPopup.open()
+ },
+
+ selectEndAddress() {
+ this.mapSelectorType = 'endAddress'
+ this.$refs.mapPopup.open()
+ },
+
+ getInitialAddress() {
+ return this.mapSelectorType === 'startAddress'
+ ? this.taskForm.startAddress
+ : this.taskForm.endAddress
+ },
+
+ onAddressSelected(address) {
+ const formattedAddress = address.title + ' - ' + address.address
+
+ if (this.mapSelectorType === 'startAddress') {
+ this.taskForm.startAddress = formattedAddress
+ this.setLocationByAddress('start', address)
+ } else if (this.mapSelectorType === 'endAddress') {
+ this.taskForm.endAddress = formattedAddress
+ this.setLocationByAddress('end', address)
+ }
+
+ // 鐩戝惉mixin涓殑璺濈璁$畻瀹屾垚浜嬩欢
+ this.$once('distance-calculated', (distance) => {
+ this.taskForm.distance = this.formatDistance(distance)
+ })
+
+ this.closeMapSelector()
+ },
+
+ closeMapSelector() {
+ this.$refs.mapPopup.close()
+ this.mapSelectorType = ''
+ },
+
+ addStaff() {
+ this.$modal.showToast('娣诲姞浜哄憳鍔熻兘寮�鍙戜腑')
+ },
+
+ removeStaff(index) {
+ this.additionalStaff.splice(index, 1)
+ },
+
+ validateForm() {
+ if (!this.selectedVehicleId) {
+ this.$modal.showToast('璇烽�夋嫨浠诲姟杞﹁締')
+ return false
+ }
+
+ if (!this.taskForm.passenger.contact) {
+ this.$modal.showToast('璇疯緭鍏ヨ仈绯讳汉')
+ return false
+ }
+
+ if (!this.taskForm.passenger.phone) {
+ this.$modal.showToast('璇疯緭鍏ヨ仈绯荤數璇�')
+ return false
+ }
+
+ if (!this.taskForm.startAddress) {
+ this.$modal.showToast('璇烽�夋嫨鍑哄彂鍦板潃')
+ return false
+ }
+
+ if (!this.taskForm.endAddress) {
+ this.$modal.showToast('璇烽�夋嫨鐩殑鍦板潃')
+ return false
+ }
+
+ return true
+ },
+
+ buildSubmitData() {
+ const submitData = {
+ taskId: this.taskId,
+ taskType: 'WELFARE',
+ vehicleIds: this.selectedVehicleId ? [this.selectedVehicleId] : [],
+ plannedStartTime: this.taskForm.serviceTime,
+ welfareInfo: {
+ passengerContact: this.taskForm.passenger.contact,
+ passengerPhone: this.taskForm.passenger.phone,
+ pickupAddress: this.taskForm.startAddress,
+ destinationAddress: this.taskForm.endAddress,
+ serviceDistance: this.taskForm.distance ? parseFloat(this.taskForm.distance) : null,
+ servicePrice: this.taskForm.price ? parseFloat(this.taskForm.price) : null
+ }
+ }
+
+ if (this.addressCoordinates.startAddress) {
+ submitData.departureLongitude = this.addressCoordinates.startAddress.lng
+ submitData.departureLatitude = this.addressCoordinates.startAddress.lat
+ }
+
+ if (this.addressCoordinates.endAddress) {
+ submitData.destinationLongitude = this.addressCoordinates.endAddress.lng
+ submitData.destinationLatitude = this.addressCoordinates.endAddress.lat
+ }
+
+ return submitData
+ },
+
+ submitTask() {
+ if (!this.validateForm()) {
+ return
+ }
+
+ this.$modal.confirm('纭畾瑕佷繚瀛樹慨鏀瑰悧锛�').then(() => {
+ this.loading = true
+ const submitData = this.buildSubmitData()
+
+ updateTask(submitData).then(response => {
+ this.loading = false
+ this.$modal.showToast('浠诲姟鏇存柊鎴愬姛')
+ setTimeout(() => {
+ uni.navigateBack()
+ }, 1500)
+ }).catch(error => {
+ this.loading = false
+ console.error('浠诲姟鏇存柊澶辫触:', error)
+ this.$modal.showToast('浠诲姟鏇存柊澶辫触锛岃閲嶈瘯')
+ })
+ }).catch(() => {})
+ },
+
+ goBack() {
+ uni.navigateBack()
+ }
+ }
+}
+</script>
+
+<style lang="scss" scoped>
+.edit-welfare-task-container {
+ padding: 20rpx;
+ background-color: #f5f5f5;
+ min-height: 100vh;
+
+ .form-header {
+ display: flex;
+ align-items: center;
+ padding: 20rpx 0;
+ margin-bottom: 30rpx;
+
+ .back-btn {
+ width: 60rpx;
+ height: 60rpx;
+ border-radius: 50%;
+ background-color: #f0f0f0;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ margin-right: 20rpx;
+ }
+
+ .title {
+ font-size: 36rpx;
+ font-weight: bold;
+ color: #333;
+ }
+ }
+
+ .form-section {
+ background-color: white;
+ border-radius: 15rpx;
+ padding: 30rpx;
+ box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05);
+
+ .form-section-title {
+ font-size: 32rpx;
+ font-weight: bold;
+ margin: 40rpx 0 20rpx 0;
+ padding-bottom: 10rpx;
+ border-bottom: 1rpx solid #f0f0f0;
+ }
+
+ .form-item {
+ margin-bottom: 40rpx;
+
+ .form-label {
+ font-size: 28rpx;
+ margin-bottom: 15rpx;
+ color: #333;
+ }
+
+ .form-input {
+ height: 70rpx;
+ padding: 0 20rpx;
+ border: 1rpx solid #eee;
+ border-radius: 10rpx;
+ font-size: 28rpx;
+
+ &.picker-input {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ }
+ }
+
+ .form-textarea {
+ width: 100%;
+ min-height: 150rpx;
+ padding: 20rpx;
+ border: 1rpx solid #eee;
+ border-radius: 10rpx;
+ font-size: 28rpx;
+ }
+
+ .staff-list {
+ .staff-item {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 20rpx;
+ background-color: #f9f9f9;
+ border-radius: 10rpx;
+ margin-bottom: 20rpx;
+ }
+
+ .add-staff {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ padding: 20rpx;
+ border: 1rpx dashed #007AFF;
+ border-radius: 10rpx;
+ color: #007AFF;
+ }
+ }
+ }
+
+ .form-actions {
+ margin-top: 50rpx;
+ text-align: center;
+
+ .submit-btn {
+ width: 80%;
+ height: 80rpx;
+ background-color: #007AFF;
+ color: white;
+ border-radius: 10rpx;
+ font-size: 32rpx;
+
+ &[disabled] {
+ background-color: #ccc;
+ color: #999;
+ }
+ }
+ }
+ }
+
+ .loading {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ height: 400rpx;
+ color: #999;
+
+ text {
+ margin-top: 20rpx;
+ font-size: 28rpx;
+ }
+ }
+
+ .map-popup-container {
+ height: 80vh;
+ background-color: white;
+ border-top-left-radius: 20rpx;
+ border-top-right-radius: 20rpx;
+ overflow: hidden;
+
+ .popup-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 20rpx 30rpx;
+ border-bottom: 1rpx solid #f0f0f0;
+
+ .popup-title {
+ font-size: 32rpx;
+ font-weight: bold;
+ color: #333;
+ }
+
+ .close-btn {
+ width: 50rpx;
+ height: 50rpx;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ }
+ }
+ }
+}
+</style>
diff --git a/app/pages/task/edit.vue b/app/pages/task/edit.vue
new file mode 100644
index 0000000..8d93d34
--- /dev/null
+++ b/app/pages/task/edit.vue
@@ -0,0 +1,520 @@
+<template>
+ <scroll-view class="edit-task-container" scroll-y="true">
+ <view class="form-header">
+ <view class="back-btn" @click="goBack">
+ <uni-icons type="arrowleft" size="20"></uni-icons>
+ </view>
+ <view class="title">缂栬緫浠诲姟</view>
+ </view>
+
+ <view class="form-section" v-if="taskDetail">
+ <!-- 浣跨敤杞﹁締閫夋嫨鍣ㄧ粍浠� -->
+ <VehicleSelector
+ v-model="taskForm.vehicleId"
+ :dept-id="currentUser.deptId"
+ :auto-select-bound="false"
+ @change="onVehicleChange"
+ />
+
+ <!-- 浣跨敤浠诲姟绫诲瀷閫夋嫨鍣ㄧ粍浠� -->
+ <TaskTypeSelector
+ v-model="taskForm.taskType"
+ @change="onTaskTypeChange"
+ />
+
+ <view class="form-item">
+ <view class="form-label">浠诲姟鎻忚堪</view>
+ <textarea
+ class="form-textarea"
+ placeholder="璇疯緭鍏ヤ换鍔℃弿杩�"
+ v-model="taskForm.taskDescription"
+ />
+ </view>
+
+ <view class="form-item">
+ <view class="form-label">浠诲姟鍑哄彂鍦�</view>
+ <view class="form-input picker-input" @click="selectStartLocation">
+ {{ taskForm.startLocation || '璇烽�夋嫨浠诲姟鍑哄彂鍦�' }}
+ <uni-icons type="arrowright" size="16" color="#999"></uni-icons>
+ </view>
+ </view>
+
+ <view class="form-item">
+ <view class="form-label">浠诲姟鐩殑鍦�</view>
+ <view class="form-input picker-input" @click="selectEndLocation">
+ {{ taskForm.endLocation || '璇烽�夋嫨浠诲姟鐩殑鍦�' }}
+ <uni-icons type="arrowright" size="16" color="#999"></uni-icons>
+ </view>
+ </view>
+
+ <view class="form-item">
+ <view class="form-label">琛岄┒鍏噷鏁�</view>
+ <input
+ class="form-input"
+ type="digit"
+ placeholder="璇疯緭鍏ヨ椹跺叕閲屾暟"
+ v-model="taskForm.distance"
+ />
+ </view>
+
+ <view class="form-item">
+ <view class="form-label">璁″垝寮�濮嬫椂闂�</view>
+ <uni-datetime-picker
+ v-model="taskForm.plannedStartTime"
+ type="datetime"
+ :placeholder="'璇烽�夋嫨璁″垝寮�濮嬫椂闂�'"
+ class="form-input"
+ />
+ </view>
+
+ <view class="form-item">
+ <view class="form-label">璁″垝缁撴潫鏃堕棿</view>
+ <uni-datetime-picker
+ v-model="taskForm.plannedEndTime"
+ type="datetime"
+ :placeholder="'璇烽�夋嫨璁″垝缁撴潫鏃堕棿'"
+ class="form-input"
+ />
+ </view>
+
+ <view class="form-item">
+ <view class="form-label">鎵ц浜�</view>
+ <input
+ class="form-input"
+ :value="currentUser.name"
+ disabled
+ />
+ </view>
+
+ <view class="form-item">
+ <view class="form-label">澶囨敞</view>
+ <textarea
+ class="form-textarea"
+ placeholder="璇疯緭鍏ュ娉ㄤ俊鎭紙鏈�澶�200瀛楋級"
+ v-model="taskForm.remark"
+ maxlength="200"
+ />
+ </view>
+
+ <view class="form-actions">
+ <button class="submit-btn" @click="submitTask" :disabled="loading">
+ {{ loading ? '淇濆瓨涓�...' : '淇濆瓨' }}
+ </button>
+ </view>
+ </view>
+
+ <view class="loading" v-else>
+ <uni-icons type="spinner-cycle" size="40" color="#007AFF"></uni-icons>
+ <text>鍔犺浇涓�...</text>
+ </view>
+
+ <!-- 鍦板浘閫夋嫨鍣ㄥ脊绐� -->
+ <uni-popup ref="mapPopup" type="bottom" :mask-click="false">
+ <view class="map-popup-container">
+ <view class="popup-header">
+ <view class="popup-title">閫夋嫨鍦板潃</view>
+ <view class="close-btn" @click="closeMapSelector">
+ <uni-icons type="closeempty" size="20" color="#999"></uni-icons>
+ </view>
+ </view>
+ <map-selector
+ :initial-address="getInitialAddress()"
+ @addressSelected="onAddressSelected"
+ ></map-selector>
+ </view>
+ </uni-popup>
+ </scroll-view>
+</template>
+
+<script>
+import { mapState } from 'vuex'
+import uniDatetimePicker from '@/uni_modules/uni-datetime-picker/components/uni-datetime-picker/uni-datetime-picker.vue'
+import uniPopup from '@/uni_modules/uni-popup/components/uni-popup/uni-popup.vue'
+import { getTask, updateTask } from "@/api/task"
+import MapSelector from '@/components/map-selector.vue'
+import VehicleSelector from '@/components/VehicleSelector.vue'
+import TaskTypeSelector from '@/components/TaskTypeSelector.vue'
+import distanceCalculator from '@/mixins/distanceCalculator.js'
+
+export default {
+ components: {
+ uniDatetimePicker,
+ uniPopup,
+ MapSelector,
+ VehicleSelector,
+ TaskTypeSelector
+ },
+ mixins: [distanceCalculator],
+ data() {
+ return {
+ taskId: null,
+ taskDetail: null,
+ mapSelectorType: '',
+ taskForm: {
+ taskDescription: '',
+ taskType: '',
+ vehicleId: null,
+ plannedStartTime: '',
+ plannedEndTime: '',
+ startLocation: '',
+ endLocation: '',
+ distance: '',
+ remark: ''
+ },
+ loading: false
+ }
+ },
+ computed: {
+ ...mapState({
+ currentUser: state => ({
+ name: state.user.nickName || '寮犱笁',
+ position: '鍙告満',
+ deptId: state.user.deptId || 100
+ })
+ })
+ },
+ onLoad(options) {
+ if (options.id) {
+ this.taskId = options.id
+ this.loadTaskDetail()
+ } else {
+ this.$modal.showToast('浠诲姟ID涓嶈兘涓虹┖')
+ setTimeout(() => {
+ uni.navigateBack()
+ }, 1500)
+ }
+ },
+ methods: {
+ // 鍔犺浇浠诲姟璇︽儏
+ loadTaskDetail() {
+ if (!this.taskId) {
+ this.$modal.showToast('浠诲姟ID涓嶈兘涓虹┖')
+ return
+ }
+
+ getTask(this.taskId).then(response => {
+ this.taskDetail = response.data || response
+
+ // 濉厖琛ㄥ崟鏁版嵁
+ this.taskForm.taskDescription = this.taskDetail.taskDescription || ''
+ this.taskForm.taskType = this.taskDetail.taskType || ''
+ this.taskForm.plannedStartTime = this.taskDetail.plannedStartTime || ''
+ this.taskForm.plannedEndTime = this.taskDetail.plannedEndTime || ''
+ this.taskForm.startLocation = this.taskDetail.departureAddress || ''
+ this.taskForm.endLocation = this.taskDetail.destinationAddress || ''
+ this.taskForm.distance = this.taskDetail.estimatedDistance || ''
+ this.taskForm.remark = this.taskDetail.remark || ''
+
+ // 璁剧疆杞﹁締淇℃伅
+ if (this.taskDetail.assignedVehicles && this.taskDetail.assignedVehicles.length > 0) {
+ const firstVehicle = this.taskDetail.assignedVehicles[0]
+ this.taskForm.vehicleId = firstVehicle.vehicleId
+ }
+
+ // 璁剧疆鍦板潃鍧愭爣锛堜娇鐢╩ixin涓殑鏂规硶锛�
+ if (this.taskDetail.departureLongitude && this.taskDetail.departureLatitude) {
+ this.setStartLocation({
+ lng: this.taskDetail.departureLongitude,
+ lat: this.taskDetail.departureLatitude
+ })
+ }
+ if (this.taskDetail.destinationLongitude && this.taskDetail.destinationLatitude) {
+ this.setEndLocation({
+ lng: this.taskDetail.destinationLongitude,
+ lat: this.taskDetail.destinationLatitude
+ })
+ }
+ }).catch(error => {
+ console.error('鍔犺浇浠诲姟璇︽儏澶辫触:', error)
+ this.$modal.showToast('鍔犺浇浠诲姟璇︽儏澶辫触')
+ setTimeout(() => {
+ uni.navigateBack()
+ }, 1500)
+ })
+ },
+
+ // 杞﹁締閫夋嫨鍙樺寲
+ onVehicleChange(vehicle) {
+ // 缁勪欢宸茬粡澶勭悊浜唙ehicleId鐨勬洿鏂�
+ console.log('閫変腑杞﹁締:', vehicle)
+ },
+
+ // 浠诲姟绫诲瀷閫夋嫨鍙樺寲
+ onTaskTypeChange(taskType) {
+ // 缁勪欢宸茬粡澶勭悊浜唗askType鐨勬洿鏂�
+ console.log('閫変腑浠诲姟绫诲瀷:', taskType)
+ },
+
+ selectStartLocation() {
+ this.mapSelectorType = 'startLocation'
+ this.$refs.mapPopup.open()
+ },
+
+ selectEndLocation() {
+ this.mapSelectorType = 'endLocation'
+ this.$refs.mapPopup.open()
+ },
+
+ getInitialAddress() {
+ return this.mapSelectorType === 'startLocation' ? this.taskForm.startLocation : this.taskForm.endLocation
+ },
+
+ onAddressSelected(address) {
+ const formattedAddress = address.title + ' - ' + address.address
+
+ if (this.mapSelectorType === 'startLocation') {
+ this.taskForm.startLocation = formattedAddress
+ this.setLocationByAddress('start', address)
+ } else if (this.mapSelectorType === 'endLocation') {
+ this.taskForm.endLocation = formattedAddress
+ this.setLocationByAddress('end', address)
+ }
+
+ // 鐩戝惉mixin涓殑璺濈璁$畻瀹屾垚浜嬩欢
+ this.$once('distance-calculated', (distance) => {
+ this.taskForm.distance = this.formatDistance(distance)
+ })
+
+ this.closeMapSelector()
+ },
+
+ closeMapSelector() {
+ this.$refs.mapPopup.close()
+ this.mapSelectorType = ''
+ },
+
+ validateForm() {
+ if (!this.taskForm.vehicleId) {
+ this.$modal.showToast('璇烽�夋嫨浠诲姟杞﹁締')
+ return false
+ }
+
+ if (!this.taskForm.taskType) {
+ this.$modal.showToast('璇烽�夋嫨浠诲姟绫诲瀷')
+ return false
+ }
+
+ if (!this.taskForm.taskDescription) {
+ this.$modal.showToast('璇疯緭鍏ヤ换鍔℃弿杩�')
+ return false
+ }
+
+ if (!this.taskForm.startLocation) {
+ this.$modal.showToast('璇烽�夋嫨浠诲姟鍑哄彂鍦�')
+ return false
+ }
+
+ if (!this.taskForm.endLocation) {
+ this.$modal.showToast('璇烽�夋嫨浠诲姟鐩殑鍦�')
+ return false
+ }
+
+ if (!this.taskForm.plannedStartTime) {
+ this.$modal.showToast('璇烽�夋嫨寮�濮嬫椂闂�')
+ return false
+ }
+
+ if (!this.taskForm.plannedEndTime) {
+ this.$modal.showToast('璇烽�夋嫨缁撴潫鏃堕棿')
+ return false
+ }
+
+ return true
+ },
+
+ buildSubmitData() {
+ const submitData = {
+ taskId: this.taskId,
+ taskDescription: this.taskForm.taskDescription,
+ taskType: this.taskForm.taskType,
+ vehicleIds: this.taskForm.vehicleId ? [this.taskForm.vehicleId] : [],
+ plannedStartTime: this.taskForm.plannedStartTime,
+ plannedEndTime: this.taskForm.plannedEndTime,
+ departureAddress: this.taskForm.startLocation,
+ destinationAddress: this.taskForm.endLocation,
+ estimatedDistance: this.taskForm.distance ? parseFloat(this.taskForm.distance) : null,
+ remark: this.taskForm.remark
+ }
+
+ if (this.addressCoordinates.startLocation) {
+ submitData.departureLongitude = this.addressCoordinates.startLocation.lng
+ submitData.departureLatitude = this.addressCoordinates.startLocation.lat
+ }
+
+ if (this.addressCoordinates.endLocation) {
+ submitData.destinationLongitude = this.addressCoordinates.endLocation.lng
+ submitData.destinationLatitude = this.addressCoordinates.endLocation.lat
+ }
+
+ return submitData
+ },
+
+ submitTask() {
+ if (!this.validateForm()) {
+ return
+ }
+
+ this.$modal.confirm('纭畾瑕佷繚瀛樹慨鏀瑰悧锛�').then(() => {
+ this.loading = true
+ const submitData = this.buildSubmitData()
+
+ updateTask(submitData).then(response => {
+ this.loading = false
+ this.$modal.showToast('浠诲姟鏇存柊鎴愬姛')
+ setTimeout(() => {
+ uni.navigateBack()
+ }, 1500)
+ }).catch(error => {
+ this.loading = false
+ console.error('浠诲姟鏇存柊澶辫触:', error)
+ this.$modal.showToast('浠诲姟鏇存柊澶辫触锛岃閲嶈瘯')
+ })
+ }).catch(() => {})
+ },
+
+ goBack() {
+ uni.navigateBack()
+ }
+ }
+}
+</script>
+
+<style lang="scss" scoped>
+.edit-task-container {
+ padding: 20rpx;
+ background-color: #f5f5f5;
+ min-height: 100vh;
+
+ .form-header {
+ display: flex;
+ align-items: center;
+ padding: 20rpx 0;
+ margin-bottom: 30rpx;
+
+ .back-btn {
+ width: 60rpx;
+ height: 60rpx;
+ border-radius: 50%;
+ background-color: #f0f0f0;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ margin-right: 20rpx;
+ }
+
+ .title {
+ font-size: 36rpx;
+ font-weight: bold;
+ color: #333;
+ }
+ }
+
+ .form-section {
+ background-color: white;
+ border-radius: 15rpx;
+ padding: 30rpx;
+ box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05);
+
+ .form-item {
+ margin-bottom: 40rpx;
+
+ .form-label {
+ font-size: 28rpx;
+ margin-bottom: 15rpx;
+ color: #333;
+ }
+
+ .form-input {
+ height: 70rpx;
+ padding: 0 20rpx;
+ border: 1rpx solid #eee;
+ border-radius: 10rpx;
+ font-size: 28rpx;
+
+ &.picker-input {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ }
+
+ &[disabled] {
+ background-color: #f5f5f5;
+ color: #999;
+ }
+ }
+
+ .form-textarea {
+ width: 100%;
+ min-height: 150rpx;
+ padding: 20rpx;
+ border: 1rpx solid #eee;
+ border-radius: 10rpx;
+ font-size: 28rpx;
+ }
+ }
+
+ .form-actions {
+ margin-top: 50rpx;
+ text-align: center;
+
+ .submit-btn {
+ width: 80%;
+ height: 80rpx;
+ background-color: #007AFF;
+ color: white;
+ border-radius: 10rpx;
+ font-size: 32rpx;
+
+ &[disabled] {
+ background-color: #ccc;
+ color: #999;
+ }
+ }
+ }
+ }
+
+ .loading {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ height: 400rpx;
+ color: #999;
+
+ text {
+ margin-top: 20rpx;
+ font-size: 28rpx;
+ }
+ }
+
+ .map-popup-container {
+ height: 80vh;
+ background-color: white;
+ border-top-left-radius: 20rpx;
+ border-top-right-radius: 20rpx;
+ overflow: hidden;
+
+ .popup-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 20rpx 30rpx;
+ border-bottom: 1rpx solid #f0f0f0;
+
+ .popup-title {
+ font-size: 32rpx;
+ font-weight: bold;
+ color: #333;
+ }
+
+ .close-btn {
+ width: 50rpx;
+ height: 50rpx;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ }
+ }
+ }
+}
+</style>
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/VehicleGpsController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/VehicleGpsController.java
index 48791f2..188657d 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/VehicleGpsController.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/VehicleGpsController.java
@@ -1055,9 +1055,9 @@
@GetMapping("/tianditu/place/suggestion")
public AjaxResult tiandituPlaceSuggestion(String keyWord, String region, String city, Integer count) {
try {
- // 妫�鏌ュ弬鏁�
+ // 妫�鏌ュ繀闇�鍙傛暟
if (keyWord == null || keyWord.trim().isEmpty()) {
- return AjaxResult.error("鍙傛暟涓嶅畬鏁达紝缂哄皯鎼滅储鍏抽敭璇�");
+ return AjaxResult.error("鍙傛暟涓嶅畬鏁达紝缂哄皯鎼滅储鍏抽敭璇�(keyWord)");
}
// 璁剧疆榛樿鍊�
@@ -1065,38 +1065,50 @@
count = 10;
}
- // 鏋勫缓澶╁湴鍥捐緭鍏ユ彁绀篈PI URL
- String url = "http://api.tianditu.gov.cn/search";
+ // 鏋勫缓澶╁湴鍥炬櫘閫氭悳绱PI URL
+ String url = "http://api.tianditu.gov.cn/v2/search";
StringBuilder paramsBuilder = new StringBuilder();
paramsBuilder.append("postStr={\"keyWord\":\"").append(keyWord).append("\"");
+ // 纭紪鐮佷腑鍥藉湴鍥捐寖鍥�
+ paramsBuilder.append(",\"mapBound\":\"").append("73.66,3.86,135.05,53.55").append("\"");
+ // 榛樿绾у埆涓�18
+ paramsBuilder.append(",\"level\":\"").append("18").append("\"");
+ // 榛樿鏌ヨ绫诲瀷涓烘櫘閫氭悳绱�
+ paramsBuilder.append(",\"queryType\":\"").append("1").append("\"");
+ // 榛樿璧峰浣嶇疆涓�0
+ paramsBuilder.append(",\"start\":\"").append("0").append("\"");
+ paramsBuilder.append(",\"count\":\"").append(count).append("\"");
+
+ // 娣诲姞鍙�夊弬鏁�
if (region != null && !region.trim().isEmpty()) {
- paramsBuilder.append(",\"region\":\"").append(region).append("\"");
+ paramsBuilder.append(",\"specify\":\"").append(region).append("\"");
}
if (city != null && !city.trim().isEmpty()) {
- paramsBuilder.append(",\"city\":\"").append(city).append("\"");
+ paramsBuilder.append(",\"dataTypes\":\"").append(city).append("\"");
}
- paramsBuilder.append(",\"count\":\"").append(count).append("\"");
- paramsBuilder.append("}" );
- paramsBuilder.append("&type=suggest");
+
+ paramsBuilder.append("}");
+ paramsBuilder.append("&type=query");
paramsBuilder.append("&tk=").append(tiandituMapConfig.getTk());
String params = paramsBuilder.toString();
- logger.info("澶╁湴鍥捐緭鍏ユ彁绀鸿姹�: keyWord={}, region={}", keyWord, region);
+ logger.info("澶╁湴鍥炬櫘閫氭悳绱㈣姹�: keyWord={}, count={}", keyWord, count);
+ logger.debug("鍦板浘璇锋眰鎺ュ彛鍙傛暟锛歿}", params);
// 鍙戦�丠TTP璇锋眰
String response = HttpUtils.sendGet(url, params);
- logger.debug("澶╁湴鍥捐緭鍏ユ彁绀哄搷搴�: {}", response);
+ logger.debug("澶╁湴鍥炬櫘閫氭悳绱㈠搷搴�: {}", response);
// 瑙f瀽鍝嶅簲
com.alibaba.fastjson2.JSONObject jsonResponse = com.alibaba.fastjson2.JSONObject.parseObject(response);
if (!"0".equals(jsonResponse.getString("status"))) {
- logger.error("杈撳叆鎻愮ず澶辫触: {}", response);
+ logger.error("鏅�氭悳绱㈠け璐�: {}", response);
return AjaxResult.error("鍦板潃鎼滅储澶辫触");
}
- // 鎻愬彇鎻愮ず鍒楄〃
- com.alibaba.fastjson2.JSONArray results = jsonResponse.getJSONArray("suggests");
+ // 鎻愬彇鎼滅储缁撴灉
+ com.alibaba.fastjson2.JSONArray results = jsonResponse.getJSONArray("pois");
if (results == null || results.isEmpty()) {
logger.info("鏈壘鍒板尮閰嶇殑鍦板潃");
return AjaxResult.success("鏌ヨ鎴愬姛", new ArrayList<>());
@@ -1109,13 +1121,16 @@
Map<String, Object> suggestion = new HashMap<>();
suggestion.put("name", item.getString("name")); // 鍚嶇О
- suggestion.put("address", item.getString("address")); // 鍦板潃
- suggestion.put("province", item.getString("province")); // 鐪�
+ suggestion.put("address", item.getString("addr")); // 鍦板潃
+ suggestion.put("province", item.getString("prov")); // 鐪�
suggestion.put("city", item.getString("city")); // 甯�
- suggestion.put("district", item.getString("district")); // 鍖�
+ suggestion.put("district", item.getString("county")); // 鍖哄幙
+ suggestion.put("tel", item.getString("tel")); // 鐢佃瘽
+ suggestion.put("postcode", item.getString("postcode")); // 閭紪
+ suggestion.put("type", item.getString("type")); // 绫诲瀷
// 缁忕含搴︿俊鎭�
- com.alibaba.fastjson2.JSONObject location = item.getJSONObject("location");
+ com.alibaba.fastjson2.JSONObject location = item.getJSONObject("lonlat");
if (location != null) {
Map<String, Object> locationMap = new HashMap<>();
locationMap.put("lon", location.getDouble("lon"));
@@ -1126,10 +1141,10 @@
suggestions.add(suggestion);
}
- logger.info("鍦板潃鎼滅储鎻愮ず鎴愬姛: 鎵惧埌{}鏉$粨鏋�", suggestions.size());
+ logger.info("鍦板潃鎼滅储鎴愬姛: 鎵惧埌{}鏉$粨鏋�", suggestions.size());
return AjaxResult.success("鏌ヨ鎴愬姛", suggestions);
} catch (Exception e) {
- logger.error("鍦板潃鎼滅储鎻愮ず澶辫触", e);
+ logger.error("鍦板潃鎼滅储澶辫触", e);
return AjaxResult.error("鍦板潃鎼滅储澶辫触锛�" + e.getMessage());
}
}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/TaskUpdateVO.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/TaskUpdateVO.java
index b8e502b..9197068 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/TaskUpdateVO.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/TaskUpdateVO.java
@@ -2,6 +2,7 @@
import java.math.BigDecimal;
import java.util.Date;
+import java.util.List;
import com.fasterxml.jackson.annotation.JsonFormat;
/**
@@ -49,6 +50,21 @@
/** 鐩殑鍦扮含搴� */
private BigDecimal destinationLatitude;
+
+ /** 浠诲姟绫诲瀷 */
+ private String taskType;
+
+ /** 閮ㄩ棬ID */
+ private Long deptId;
+
+ /** 杞﹁締ID鍒楄〃 */
+ private List<Long> vehicleIds;
+
+ /** 鐥呮儏ID鍒楄〃锛堢敤浜庡悓姝ヨ皟搴﹀崟鐨凮rdICD_ID鍙傛暟锛� */
+ private List<Long> diseaseIds;
+
+ /** 鎬ユ晳杞繍浠诲姟鎵╁睍淇℃伅 */
+ private EmergencyInfoVO emergencyInfo;
public Long getTaskId() {
return taskId;
@@ -145,4 +161,314 @@
public void setDestinationLatitude(BigDecimal destinationLatitude) {
this.destinationLatitude = destinationLatitude;
}
+
+ public String getTaskType() {
+ return taskType;
+ }
+
+ public void setTaskType(String taskType) {
+ this.taskType = taskType;
+ }
+
+ public Long getDeptId() {
+ return deptId;
+ }
+
+ public void setDeptId(Long deptId) {
+ this.deptId = deptId;
+ }
+
+ public List<Long> getVehicleIds() {
+ return vehicleIds;
+ }
+
+ public void setVehicleIds(List<Long> vehicleIds) {
+ this.vehicleIds = vehicleIds;
+ }
+
+ public List<Long> getDiseaseIds() {
+ return diseaseIds;
+ }
+
+ public void setDiseaseIds(List<Long> diseaseIds) {
+ this.diseaseIds = diseaseIds;
+ }
+
+ public EmergencyInfoVO getEmergencyInfo() {
+ return emergencyInfo;
+ }
+
+ public void setEmergencyInfo(EmergencyInfoVO emergencyInfo) {
+ this.emergencyInfo = emergencyInfo;
+ }
+
+ /**
+ * 鎬ユ晳杞繍浠诲姟鎵╁睍淇℃伅鍐呴儴绫�
+ */
+ public static class EmergencyInfoVO {
+ /** 鎮h�呰仈绯讳汉 */
+ private String patientContact;
+
+ /** 鎮h�呰仈绯荤數璇� */
+ private String patientPhone;
+
+ /** 鎮h�呭鍚� */
+ private String patientName;
+
+ /** 鎮h�呮�у埆 */
+ private String patientGender;
+
+ /** 鎮h�呰韩浠借瘉鍙� */
+ private String patientIdCard;
+
+ /** 鎮h�呯梾鎯呮弿杩� */
+ private String patientCondition;
+
+ /** 杞嚭鍖婚櫌ID */
+ private Long hospitalOutId;
+
+ /** 杞嚭鍖婚櫌鍚嶇О */
+ private String hospitalOutName;
+
+ /** 杞嚭鍖婚櫌绉戝 */
+ private String hospitalOutDepartment;
+
+ /** 杞嚭鍖婚櫌绉戝ID */
+ private String hospitalOutDepartmentId;
+
+ /** 杞嚭鍖婚櫌搴婂彿 */
+ private String hospitalOutBedNumber;
+
+ /** 杞嚭鍖婚櫌鍦板潃 */
+ private String hospitalOutAddress;
+
+ /** 杞嚭鍖婚櫌缁忓害 */
+ private BigDecimal hospitalOutLongitude;
+
+ /** 杞嚭鍖婚櫌绾害 */
+ private BigDecimal hospitalOutLatitude;
+
+ /** 杞叆鍖婚櫌ID */
+ private Long hospitalInId;
+
+ /** 杞叆鍖婚櫌鍚嶇О */
+ private String hospitalInName;
+
+ /** 杞叆鍖婚櫌绉戝 */
+ private String hospitalInDepartment;
+
+ /** 杞叆鍖婚櫌绉戝ID */
+ private String hospitalInDepartmentId;
+
+ /** 杞叆鍖婚櫌搴婂彿 */
+ private String hospitalInBedNumber;
+
+ /** 杞叆鍖婚櫌鍦板潃 */
+ private String hospitalInAddress;
+
+ /** 杞叆鍖婚櫌缁忓害 */
+ private BigDecimal hospitalInLongitude;
+
+ /** 杞叆鍖婚櫌绾害 */
+ private BigDecimal hospitalInLatitude;
+
+ /** 杞繍鍏噷鏁� */
+ private BigDecimal transferDistance;
+
+ /** 杞繍璐圭敤 */
+ private BigDecimal transferPrice;
+
+ // Getters and Setters
+ public String getPatientContact() {
+ return patientContact;
+ }
+
+ public void setPatientContact(String patientContact) {
+ this.patientContact = patientContact;
+ }
+
+ public String getPatientPhone() {
+ return patientPhone;
+ }
+
+ public void setPatientPhone(String patientPhone) {
+ this.patientPhone = patientPhone;
+ }
+
+ public String getPatientName() {
+ return patientName;
+ }
+
+ public void setPatientName(String patientName) {
+ this.patientName = patientName;
+ }
+
+ public String getPatientGender() {
+ return patientGender;
+ }
+
+ public void setPatientGender(String patientGender) {
+ this.patientGender = patientGender;
+ }
+
+ public String getPatientIdCard() {
+ return patientIdCard;
+ }
+
+ public void setPatientIdCard(String patientIdCard) {
+ this.patientIdCard = patientIdCard;
+ }
+
+ public String getPatientCondition() {
+ return patientCondition;
+ }
+
+ public void setPatientCondition(String patientCondition) {
+ this.patientCondition = patientCondition;
+ }
+
+ public Long getHospitalOutId() {
+ return hospitalOutId;
+ }
+
+ public void setHospitalOutId(Long hospitalOutId) {
+ this.hospitalOutId = hospitalOutId;
+ }
+
+ public String getHospitalOutName() {
+ return hospitalOutName;
+ }
+
+ public void setHospitalOutName(String hospitalOutName) {
+ this.hospitalOutName = hospitalOutName;
+ }
+
+ public String getHospitalOutDepartment() {
+ return hospitalOutDepartment;
+ }
+
+ public void setHospitalOutDepartment(String hospitalOutDepartment) {
+ this.hospitalOutDepartment = hospitalOutDepartment;
+ }
+
+ public String getHospitalOutDepartmentId() {
+ return hospitalOutDepartmentId;
+ }
+
+ public void setHospitalOutDepartmentId(String hospitalOutDepartmentId) {
+ this.hospitalOutDepartmentId = hospitalOutDepartmentId;
+ }
+
+ public String getHospitalOutBedNumber() {
+ return hospitalOutBedNumber;
+ }
+
+ public void setHospitalOutBedNumber(String hospitalOutBedNumber) {
+ this.hospitalOutBedNumber = hospitalOutBedNumber;
+ }
+
+ public String getHospitalOutAddress() {
+ return hospitalOutAddress;
+ }
+
+ public void setHospitalOutAddress(String hospitalOutAddress) {
+ this.hospitalOutAddress = hospitalOutAddress;
+ }
+
+ public BigDecimal getHospitalOutLongitude() {
+ return hospitalOutLongitude;
+ }
+
+ public void setHospitalOutLongitude(BigDecimal hospitalOutLongitude) {
+ this.hospitalOutLongitude = hospitalOutLongitude;
+ }
+
+ public BigDecimal getHospitalOutLatitude() {
+ return hospitalOutLatitude;
+ }
+
+ public void setHospitalOutLatitude(BigDecimal hospitalOutLatitude) {
+ this.hospitalOutLatitude = hospitalOutLatitude;
+ }
+
+ public Long getHospitalInId() {
+ return hospitalInId;
+ }
+
+ public void setHospitalInId(Long hospitalInId) {
+ this.hospitalInId = hospitalInId;
+ }
+
+ public String getHospitalInName() {
+ return hospitalInName;
+ }
+
+ public void setHospitalInName(String hospitalInName) {
+ this.hospitalInName = hospitalInName;
+ }
+
+ public String getHospitalInDepartment() {
+ return hospitalInDepartment;
+ }
+
+ public void setHospitalInDepartment(String hospitalInDepartment) {
+ this.hospitalInDepartment = hospitalInDepartment;
+ }
+
+ public String getHospitalInDepartmentId() {
+ return hospitalInDepartmentId;
+ }
+
+ public void setHospitalInDepartmentId(String hospitalInDepartmentId) {
+ this.hospitalInDepartmentId = hospitalInDepartmentId;
+ }
+
+ public String getHospitalInBedNumber() {
+ return hospitalInBedNumber;
+ }
+
+ public void setHospitalInBedNumber(String hospitalInBedNumber) {
+ this.hospitalInBedNumber = hospitalInBedNumber;
+ }
+
+ public String getHospitalInAddress() {
+ return hospitalInAddress;
+ }
+
+ public void setHospitalInAddress(String hospitalInAddress) {
+ this.hospitalInAddress = hospitalInAddress;
+ }
+
+ public BigDecimal getHospitalInLongitude() {
+ return hospitalInLongitude;
+ }
+
+ public void setHospitalInLongitude(BigDecimal hospitalInLongitude) {
+ this.hospitalInLongitude = hospitalInLongitude;
+ }
+
+ public BigDecimal getHospitalInLatitude() {
+ return hospitalInLatitude;
+ }
+
+ public void setHospitalInLatitude(BigDecimal hospitalInLatitude) {
+ this.hospitalInLatitude = hospitalInLatitude;
+ }
+
+ public BigDecimal getTransferDistance() {
+ return transferDistance;
+ }
+
+ public void setTransferDistance(BigDecimal transferDistance) {
+ this.transferDistance = transferDistance;
+ }
+
+ public BigDecimal getTransferPrice() {
+ return transferPrice;
+ }
+
+ public void setTransferPrice(BigDecimal transferPrice) {
+ this.transferPrice = transferPrice;
+ }
+ }
}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTaskServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTaskServiceImpl.java
index 7e28b71..b939e42 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTaskServiceImpl.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTaskServiceImpl.java
@@ -2,10 +2,7 @@
import java.io.*;
import java.math.BigDecimal;
-import java.util.Collections;
-import java.util.Date;
-import java.util.List;
-import java.util.ArrayList;
+import java.util.*;
import java.util.stream.Collectors;
import java.net.HttpURLConnection;
import java.net.URL;
@@ -490,10 +487,51 @@
task.setUpdateTime(DateUtils.getNowDate());
task.setRemark(updateVO.getRemark());
+ // 濡傛灉鏇存柊浜嗛儴闂↖D
+ if (updateVO.getDeptId() != null) {
+ task.setDeptId(updateVO.getDeptId());
+ }
+
// 閲嶆柊璁$畻棰勮鍏噷鏁�
calculateEstimatedDistance(task);
int result = sysTaskMapper.updateSysTask(task);
+
+ // 鏇存柊杞﹁締鍏宠仈
+ if (result > 0 && updateVO.getVehicleIds() != null && !updateVO.getVehicleIds().isEmpty()) {
+ // 鏌ヨ鐜版湁鐨勮溅杈嗗叧鑱�
+ List<SysTaskVehicle> existingVehicles = sysTaskVehicleMapper.selectSysTaskVehicleByTaskId(updateVO.getTaskId());
+ List<Long> existingVehicleIds = existingVehicles.stream()
+ .map(SysTaskVehicle::getVehicleId)
+ .collect(Collectors.toList());
+
+ // 姣旇緝鏂版棫杞﹁締ID鍒楄〃锛屽垽鏂槸鍚︽湁鍙樺寲
+ boolean vehiclesChanged = !new HashSet<>(existingVehicleIds).equals(new HashSet<>(updateVO.getVehicleIds()));
+
+ // 鍙湁杞﹁締鍙戠敓鍙樺寲鏃舵墠鏇存柊
+ if (vehiclesChanged) {
+ // 鍒犻櫎鏃х殑杞﹁締鍏宠仈
+ sysTaskVehicleMapper.deleteSysTaskVehicleByTaskId(updateVO.getTaskId());
+
+ // 娣诲姞鏂扮殑杞﹁締鍏宠仈
+ Date now = DateUtils.getNowDate();
+ String currentUser = SecurityUtils.getUsername();
+ for (Long vehicleId : updateVO.getVehicleIds()) {
+ SysTaskVehicle taskVehicle = new SysTaskVehicle();
+ taskVehicle.setTaskId(updateVO.getTaskId());
+ taskVehicle.setVehicleId(vehicleId);
+ taskVehicle.setAssignTime(now);
+ taskVehicle.setAssignBy(currentUser);
+ taskVehicle.setCreateTime(now);
+ sysTaskVehicleMapper.insertSysTaskVehicle(taskVehicle);
+ }
+ }
+ }
+
+ // 鏇存柊鎬ユ晳杞繍鎵╁睍淇℃伅
+ if (result > 0 && "EMERGENCY_TRANSFER".equals(oldTask.getTaskType()) && updateVO.getEmergencyInfo() != null) {
+ updateEmergencyInfo(updateVO.getTaskId(), updateVO);
+ }
// 璁板綍鎿嶄綔鏃ュ織
if (result > 0) {
@@ -1454,6 +1492,124 @@
}
/**
+ * 鏇存柊鎬ユ晳杞繍浠诲姟鎵╁睍淇℃伅
+ *
+ * @param taskId 浠诲姟ID
+ * @param updateVO 浠诲姟鏇存柊瀵硅薄
+ */
+ private void updateEmergencyInfo(Long taskId, TaskUpdateVO updateVO) {
+ // 鏌ヨ鐜版湁鐨勬墿灞曚俊鎭�
+ SysTaskEmergency existingInfo = sysTaskEmergencyMapper.selectSysTaskEmergencyByTaskId(taskId);
+ if (existingInfo == null) {
+ // 濡傛灉涓嶅瓨鍦紝鍒欏垱寤烘柊鐨�
+ existingInfo = new SysTaskEmergency();
+ existingInfo.setTaskId(taskId);
+ existingInfo.setCreateTime(DateUtils.getNowDate());
+ existingInfo.setCreateBy(SecurityUtils.getUsername());
+ }
+
+ TaskUpdateVO.EmergencyInfoVO emergencyInfo = updateVO.getEmergencyInfo();
+
+ // 鏇存柊鎮h�呬俊鎭�
+ if (emergencyInfo.getPatientContact() != null) {
+ existingInfo.setPatientContact(emergencyInfo.getPatientContact());
+ }
+ if (emergencyInfo.getPatientPhone() != null) {
+ existingInfo.setPatientPhone(emergencyInfo.getPatientPhone());
+ }
+ if (emergencyInfo.getPatientName() != null) {
+ existingInfo.setPatientName(emergencyInfo.getPatientName());
+ }
+ if (emergencyInfo.getPatientGender() != null) {
+ existingInfo.setPatientGender(emergencyInfo.getPatientGender());
+ }
+ if (emergencyInfo.getPatientIdCard() != null) {
+ existingInfo.setPatientIdCard(emergencyInfo.getPatientIdCard());
+ }
+ if (emergencyInfo.getPatientCondition() != null) {
+ existingInfo.setPatientCondition(emergencyInfo.getPatientCondition());
+ }
+
+ // 鏇存柊杞嚭鍖婚櫌淇℃伅
+ if (emergencyInfo.getHospitalOutId() != null) {
+ existingInfo.setHospitalOutId(emergencyInfo.getHospitalOutId());
+ }
+ if (emergencyInfo.getHospitalOutName() != null) {
+ existingInfo.setHospitalOutName(emergencyInfo.getHospitalOutName());
+ }
+ if (emergencyInfo.getHospitalOutDepartment() != null) {
+ existingInfo.setHospitalOutDepartment(emergencyInfo.getHospitalOutDepartment());
+ }
+ if (emergencyInfo.getHospitalOutDepartmentId() != null) {
+ existingInfo.setHospitalOutDepartmentId(emergencyInfo.getHospitalOutDepartmentId());
+ }
+ if (emergencyInfo.getHospitalOutBedNumber() != null) {
+ existingInfo.setHospitalOutBedNumber(emergencyInfo.getHospitalOutBedNumber());
+ }
+ if (emergencyInfo.getHospitalOutAddress() != null) {
+ existingInfo.setHospitalOutAddress(emergencyInfo.getHospitalOutAddress());
+ }
+ if (emergencyInfo.getHospitalOutLongitude() != null) {
+ existingInfo.setHospitalOutLongitude(emergencyInfo.getHospitalOutLongitude());
+ }
+ if (emergencyInfo.getHospitalOutLatitude() != null) {
+ existingInfo.setHospitalOutLatitude(emergencyInfo.getHospitalOutLatitude());
+ }
+
+ // 鏇存柊杞叆鍖婚櫌淇℃伅
+ if (emergencyInfo.getHospitalInId() != null) {
+ existingInfo.setHospitalInId(emergencyInfo.getHospitalInId());
+ }
+ if (emergencyInfo.getHospitalInName() != null) {
+ existingInfo.setHospitalInName(emergencyInfo.getHospitalInName());
+ }
+ if (emergencyInfo.getHospitalInDepartment() != null) {
+ existingInfo.setHospitalInDepartment(emergencyInfo.getHospitalInDepartment());
+ }
+ if (emergencyInfo.getHospitalInDepartmentId() != null) {
+ existingInfo.setHospitalInDepartmentId(emergencyInfo.getHospitalInDepartmentId());
+ }
+ if (emergencyInfo.getHospitalInBedNumber() != null) {
+ existingInfo.setHospitalInBedNumber(emergencyInfo.getHospitalInBedNumber());
+ }
+ if (emergencyInfo.getHospitalInAddress() != null) {
+ existingInfo.setHospitalInAddress(emergencyInfo.getHospitalInAddress());
+ }
+ if (emergencyInfo.getHospitalInLongitude() != null) {
+ existingInfo.setHospitalInLongitude(emergencyInfo.getHospitalInLongitude());
+ }
+ if (emergencyInfo.getHospitalInLatitude() != null) {
+ existingInfo.setHospitalInLatitude(emergencyInfo.getHospitalInLatitude());
+ }
+
+ // 鏇存柊璐圭敤淇℃伅
+ if (emergencyInfo.getTransferDistance() != null) {
+ existingInfo.setTransferDistance(emergencyInfo.getTransferDistance());
+ }
+ if (emergencyInfo.getTransferPrice() != null) {
+ existingInfo.setTransferPrice(emergencyInfo.getTransferPrice());
+ }
+
+ // 鏇存柊鐥呮儏ID鍒楄〃
+ if (updateVO.getDiseaseIds() != null && !updateVO.getDiseaseIds().isEmpty()) {
+ String diseaseIdsStr = updateVO.getDiseaseIds().stream()
+ .map(String::valueOf)
+ .collect(Collectors.joining(","));
+ existingInfo.setDiseaseIds(diseaseIdsStr);
+ } else {
+ // 濡傛灉鐥呮儏ID鍒楄〃涓虹┖锛屾竻绌鸿瀛楁
+ existingInfo.setDiseaseIds(null);
+ }
+
+ // 绯荤粺瀛楁
+ existingInfo.setUpdateTime(DateUtils.getNowDate());
+ existingInfo.setUpdateBy(SecurityUtils.getUsername());
+
+ // 鎵ц鏇存柊
+ sysTaskEmergencyMapper.updateSysTaskEmergency(existingInfo);
+ }
+
+ /**
* 淇濆瓨绂忕杞︿换鍔℃墿灞曚俊鎭�
*
* @param taskId 浠诲姟ID
diff --git a/ruoyi-system/src/main/resources/areacode.json b/ruoyi-system/src/main/resources/areacode.json
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/ruoyi-system/src/main/resources/areacode.json
diff --git a/ruoyi-system/src/main/resources/mapper/system/SysTaskMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysTaskMapper.xml
index ebc0e2d..338d8e2 100644
--- a/ruoyi-system/src/main/resources/mapper/system/SysTaskMapper.xml
+++ b/ruoyi-system/src/main/resources/mapper/system/SysTaskMapper.xml
@@ -186,10 +186,6 @@
<if test="creatorId != null">creator_id,</if>
<if test="assigneeId != null">assignee_id,</if>
<if test="deptId != null">dept_id,</if>
- <if test="plannedStartTime!=null">planned_start_time,</if>
- <if test="plannedEndTime!=null">planned_end_time,</if>
- <if test="plannedStartTime!=null">planned_start_time,</if>
- <if test="plannedEndTime!=null">planned_end_time,</if>
<if test="createTime != null">create_time,</if>
update_time,
<if test="createBy != null">create_by,</if>
@@ -216,10 +212,6 @@
<if test="creatorId != null">#{creatorId},</if>
<if test="assigneeId != null">#{assigneeId},</if>
<if test="deptId != null">#{deptId},</if>
- <if test="plannedStartTime!=null">#{plannedStartTime},</if>
- <if test="plannedEndTime!=null">#{plannedEndTime},</if>
- <if test="actualStartTime!=null">#{actualStartTime},</if>
- <if test="actualEndTime!=null">#{actualEndTime},</if>
<if test="createTime != null">#{createTime},</if>
now(),
<if test="createBy != null">#{createBy},</if>
diff --git a/ruoyi-system/src/test/java/com/ruoyi/system/service/impl/LegacyTransferSyncServiceImplTest.java b/ruoyi-system/src/test/java/com/ruoyi/system/service/impl/LegacyTransferSyncServiceImplTest.java
deleted file mode 100644
index 57031af..0000000
--- a/ruoyi-system/src/test/java/com/ruoyi/system/service/impl/LegacyTransferSyncServiceImplTest.java
+++ /dev/null
@@ -1,113 +0,0 @@
-package com.ruoyi.system.service.impl;
-
-import com.ruoyi.system.domain.vo.TaskCreateVO;
-import com.ruoyi.system.service.ILegacyTransferSyncService;
-import org.junit.jupiter.api.Test;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.test.context.SpringBootTest;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import static org.junit.jupiter.api.Assertions.*;
-
-@SpringBootTest
-public class LegacyTransferSyncServiceImplTest {
-
- @Autowired
- private ILegacyTransferSyncService legacyTransferSyncService;
-
- @Test
- public void testBuildCreateTaskVo() {
- // 鍑嗗娴嬭瘯鏁版嵁
- String serviceOrdID = "12345";
- String dispatchOrdID = "67890";
-
- Map<String, Object> order = new HashMap<>();
- order.put("ServiceOrdID", serviceOrdID);
- order.put("DispatchOrdID", dispatchOrdID);
- order.put("ServiceOrdPtName", "寮犱笁");
- order.put("ServiceOrdCoPhone", "13800138000");
- order.put("ServiceOrdPtIDCard", "110101199001011234");
- order.put("ServiceOrdPtCondition", "鐥呮儏绋冲畾");
- order.put("ServiceOrdCoName", "鏉庡洓");
- order.put("ServiceOrdPtOutHospID", 1001L);
- order.put("ServiceOrdPtServicesID", "2001");
- order.put("ServiceOrdPtInHospID", 1002L);
- order.put("ServiceOrdPtInServicesID", "2002");
- order.put("ServiceOrdTraStreet", "鍖椾含甯傛湞闃冲尯鏌愭煇琛楅亾123鍙�");
- order.put("ServiceOrdTraEnd", "鍖椾含甯傛捣娣�鍖烘煇鏌愬尰闄�");
- order.put("ServiceOrdTraTxnPrice", "500.00");
- order.put("ServiceOrdClass", "A001");
- order.put("ServiceOrdType", "T001");
- order.put("DispatchOrdStartDate", "2025-11-20 09:00:00");
- order.put("DispatchOrd_NS_Time", "2025-11-19 14:30:00");
-
- // 璋冪敤鏂规硶
- TaskCreateVO taskCreateVO = legacyTransferSyncService.buildCreateTaskVo(serviceOrdID, dispatchOrdID, order);
-
- // 楠岃瘉缁撴灉
- assertNotNull(taskCreateVO);
- assertEquals("EMERGENCY_TRANSFER", taskCreateVO.getTaskType());
- assertEquals("浠庢棫绯荤粺鍚屾鐨勮浆杩愬崟", taskCreateVO.getTaskDescription());
-
- // 楠岃瘉鎮h�呬俊鎭�
- assertNotNull(taskCreateVO.getPatient());
- assertEquals("寮犱笁", taskCreateVO.getPatient().getName());
- assertEquals("13800138000", taskCreateVO.getPatient().getPhone());
- assertEquals("110101199001011234", taskCreateVO.getPatient().getIdCard());
- assertEquals("鐥呮儏绋冲畾", taskCreateVO.getPatient().getCondition());
- assertEquals("鏉庡洓", taskCreateVO.getPatient().getContact());
-
- // 楠岃瘉杞嚭鍖婚櫌淇℃伅
- assertNotNull(taskCreateVO.getHospitalOut());
- assertEquals(Long.valueOf(1001), taskCreateVO.getHospitalOut().getId());
- assertEquals("2001", taskCreateVO.getHospitalOut().getDepartmentId());
-
- // 楠岃瘉杞叆鍖婚櫌淇℃伅
- assertNotNull(taskCreateVO.getHospitalIn());
- assertEquals(Long.valueOf(1002), taskCreateVO.getHospitalIn().getId());
- assertEquals("2002", taskCreateVO.getHospitalIn().getDepartmentId());
-
- // 楠岃瘉鍦板潃淇℃伅
- assertEquals("鍖椾含甯傛湞闃冲尯鏌愭煇琛楅亾123鍙�", taskCreateVO.getDepartureAddress());
- assertEquals("鍖椾含甯傛捣娣�鍖烘煇鏌愬尰闄�", taskCreateVO.getDestinationAddress());
-
- // 楠岃瘉浠锋牸淇℃伅
- assertEquals("500.00", taskCreateVO.getPrice().toString());
-
- // 楠岃瘉鍗曟嵁绫诲瀷鍜屼换鍔$被鍨�
- assertEquals("A001", taskCreateVO.getDocumentTypeId());
- assertEquals("T001", taskCreateVO.getTaskTypeId());
-
- // 楠岃瘉澶囨敞淇℃伅
- assertTrue(taskCreateVO.getRemark().contains("鏈嶅姟鍗旾D: " + serviceOrdID));
- assertTrue(taskCreateVO.getRemark().contains("璋冨害鍗旾D: " + dispatchOrdID));
- }
-
- @Test
- public void testIsTransferOrderSyncedWithInvalidParams() {
- // 娴嬭瘯鏈嶅姟鍗旾D涓虹┖鐨勬儏鍐�
- boolean result1 = legacyTransferSyncService.isTransferOrderSynced(null, "12345");
- assertFalse(result1);
-
- // 娴嬭瘯鏈嶅姟鍗旾D涓虹┖瀛楃涓茬殑鎯呭喌
- boolean result2 = legacyTransferSyncService.isTransferOrderSynced("", "12345");
- assertFalse(result2);
-
- // 娴嬭瘯鏈嶅姟鍗旾D涓洪潪鏁板瓧瀛楃涓茬殑鎯呭喌
- boolean result3 = legacyTransferSyncService.isTransferOrderSynced("abc", "12345");
- assertFalse(result3);
- }
-
- @Test
- public void testSyncSingleTransferOrderWithInvalidParams() {
- // 娴嬭瘯鏈嶅姟鍗旾D涓虹┖鐨勬儏鍐�
- boolean result1 = legacyTransferSyncService.syncSingleTransferOrder(null, "12345");
- assertFalse(result1);
-
- // 娴嬭瘯鏈嶅姟鍗旾D涓虹┖瀛楃涓茬殑鎯呭喌
- boolean result2 = legacyTransferSyncService.syncSingleTransferOrder("", "12345");
- assertFalse(result2);
- }
-}
\ No newline at end of file
--
Gitblit v1.9.1