<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
|
}
|
|
// 设置地址坐标(使用mixin中的方法)
|
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) {
|
// 组件已经处理了selectedVehicleId的更新
|
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>
|