app/pages/index.vue
@@ -101,7 +101,8 @@ <view class="task-header"> <view class="task-title"> {{ getTaskTypeText(task.type) }} - {{ task.vehicle }} <text v-if="task.isHeadPush === '1'" class="head-push-tag">总</text> <text v-if="task.emergencyInfo && task.emergencyInfo.serviceOrdVip === '1'" class="vip-tag">VIP</text> <text v-if="task.emergencyInfo && task.emergencyInfo.fromHq2Is === '1'" class="hq-tag">广总</text> </view> <view class="task-status" @@ -127,9 +128,10 @@ </view> </view> <!-- 任务编号单独一行 --> <!-- 任务编号和开始时间在同一行显示,但分开一些 --> <view class="task-code-row"> <text class="task-code">{{ task.showTaskCode }}</text> <text class="task-time">{{ task.startTime }}</text> </view> <!-- 任务详细信息 --> @@ -137,18 +139,18 @@ <view class="info-row"> <view class="info-item"> <view class="label">出发地:</view> <view class="value">{{ task.startLocation }}</view> <view class="value">{{ getStartLocationDisplay(task) }}</view> </view> <view class="info-item"> <view class="label">目的地:</view> <view class="value">{{ task.endLocation }}</view> </view> </view> <view class="info-row"> <view class="info-item"> <view class="label">出发时间:</view> <view class="value">{{ task.startTime }}</view> <view class="label">目的地:</view> <view class="value">{{ getEndLocationDisplay(task) }}</view> </view> </view> <view class="info-row"> <view class="info-item"> <view class="label">执行人员:</view> <view class="value">{{ task.assignee }}</view> @@ -505,12 +507,8 @@ type: task.taskType, vehicle: vehicleInfo, vehicleList: task.assignedVehicles || [], startLocation: this.formatAddress( task.departureAddress || task.startLocation || "未设置" ), endLocation: this.formatAddress( task.destinationAddress || task.endLocation || "未设置" ), startLocation: task.departureAddress || task.startLocation || "未设置", endLocation: task.destinationAddress || task.endLocation || "未设置", startTime: task.plannedStartTime ? formatDateTime(task.plannedStartTime, "YYYY-MM-DD HH:mm") : "未设置", @@ -553,6 +551,33 @@ return address.substring(0, dashIndex); } return address; }, // 获取出发地显示内容(转运任务显示转出医院名称) getStartLocationDisplay(task) { // 如果是转运任务且有emergencyInfo信息 if (task.taskType === 'EMERGENCY_TRANSFER' && task.emergencyInfo && task.emergencyInfo.hospitalOutName) { return task.emergencyInfo.hospitalOutName; } // 其他情况使用原来的startLocation return this.formatAddress(task.startLocation || "未设置"); }, // 获取目的地显示内容(转运任务显示转入医院名称或详细地址) getEndLocationDisplay(task) { // 如果是转运任务且有emergencyInfo信息 if (task.taskType === 'EMERGENCY_TRANSFER' && task.emergencyInfo) { // 优先显示转入医院名称 if (task.emergencyInfo.hospitalInName) { if(task.emergencyInfo.hospitalInName.includes("家中")){ return task.emergencyInfo.destinationAddress; } return task.emergencyInfo.hospitalInName; } } // 其他情况使用原来的endLocation return this.formatAddress(task.endLocation || "未设置"); }, // 转换状态格式(将数据库状态转换为UI使用的状态) @@ -824,17 +849,6 @@ * { -ms-overflow-style: none; /* IE 10+ */ } } // 总部推送标记样式 .head-push-tag { color: #ff0000; font-size: 24rpx; font-weight: bold; margin-left: 10rpx; padding: 2rpx 8rpx; border: 1rpx solid #ff0000; border-radius: 4rpx; } // 用户信息区域 @@ -1115,13 +1129,22 @@ } } // 任务编号单独一行 // 任务编号和时间在同一行显示 .task-code-row { margin-bottom: 15rpx; padding: 10rpx 0; border-bottom: 1rpx dashed #e0e0e0; display: flex; justify-content: space-between; .task-code { font-size: 28rpx; color: #333; font-weight: 500; font-family: monospace; } .task-time { font-size: 28rpx; color: #333; font-weight: 500; @@ -1220,6 +1243,28 @@ color: #666; } } .vip-tag { display: inline-block; padding: 2rpx 8rpx; font-size: 20rpx; color: #fff; background-color: #ff0000; border-radius: 4rpx; margin-left: 10rpx; vertical-align: middle; } .hq-tag { display: inline-block; padding: 2rpx 8rpx; font-size: 20rpx; color: #fff; background-color: #5856d6; border-radius: 4rpx; margin-left: 10rpx; vertical-align: middle; } } } </style> app/pages/task/index.vue
@@ -6,7 +6,10 @@ <view class="header-title">任务列表</view> <view class="header-actions"> <button class="search-toggle-btn" @click="toggleSearch"> <uni-icons :type="showSearch ? 'close' : 'search'" size="20"></uni-icons> <uni-icons :type="showSearch ? 'close' : 'search'" size="20" ></uni-icons> </button> <button class="refresh-btn" @click="refreshList"> <uni-icons type="refresh" size="20"></uni-icons> @@ -19,9 +22,13 @@ <view class="search-form"> <view class="form-item"> <view class="form-label">任务状态</view> <picker mode="selector" :range="statusOptions" @change="onStatusChange"> <picker mode="selector" :range="statusOptions" @change="onStatusChange" > <view class="form-input picker-input"> {{ selectedStatusText || '全部状态' }} {{ selectedStatusText || "全部状态" }} <uni-icons type="arrowright" size="16" color="#999"></uni-icons> </view> </picker> @@ -108,22 +115,60 @@ <scroll-view class="task-list-scroll" scroll-y="true"> <view class="task-list"> <view class="task-item" v-for="task in filteredTaskList" :key="task.taskId"> <view class="task-item" v-for="task in filteredTaskList" :key="task.taskId" > <view class="task-main" @click="viewTaskDetail(task)"> <!-- 任务头部:标题和状态标签 --> <view class="task-header"> <view class="task-title"> {{ getTaskTypeText(task.taskType) }} - {{ task.vehicle }} <text v-if="task.isHeadPush === '1'" class="head-push-tag">总</text> <text v-if=" task.emergencyInfo && task.emergencyInfo.serviceOrdVip === '1' " class="vip-tag" >VIP</text > <text v-if=" task.emergencyInfo && task.emergencyInfo.fromHq2Is === '1' " class="hq-tag" >广总</text > </view> <view class="task-status" :class="task.taskStatus === 'PENDING' ? 'status-pending' : task.taskStatus === 'DEPARTING' ? 'status-departing' : task.taskStatus === 'ARRIVED' ? 'status-arrived' : task.taskStatus === 'RETURNING' ? 'status-returning' : task.taskStatus === 'COMPLETED' ? 'status-completed' : task.taskStatus === 'CANCELLED' ? 'status-cancelled' : task.taskStatus === 'IN_PROGRESS' ? 'status-in-progress' : 'status-default'"> <view class="task-status" :class=" task.taskStatus === 'PENDING' ? 'status-pending' : task.taskStatus === 'DEPARTING' ? 'status-departing' : task.taskStatus === 'ARRIVED' ? 'status-arrived' : task.taskStatus === 'RETURNING' ? 'status-returning' : task.taskStatus === 'COMPLETED' ? 'status-completed' : task.taskStatus === 'CANCELLED' ? 'status-cancelled' : task.taskStatus === 'IN_PROGRESS' ? 'status-in-progress' : 'status-default' " > {{ getStatusText(task.taskStatus) }} </view> </view> <!-- 任务编号单独一行 --> <!-- 任务编号和开始时间在同一行显示,但分开一些 --> <view class="task-code-row"> <text class="task-code">{{ task.showTaskCode }}</text> <text class="task-time">出发时间:{{ task.startTime }}</text> </view> <!-- 任务详细信息 --> @@ -131,18 +176,16 @@ <view class="info-row"> <view class="info-item"> <view class="label">出发地:</view> <view class="value">{{ task.startLocation }}</view> </view> <view class="info-item"> <view class="label">目的地:</view> <view class="value">{{ task.endLocation }}</view> <view class="value">{{ getStartLocationDisplay(task) }}</view> </view> </view> <view class="info-row"> <view class="info-item"> <view class="label">出发时间:</view> <view class="value">{{ task.startTime }}</view> <view class="label">目的地:</view> <view class="value">{{ getEndLocationDisplay(task) }}</view> </view> </view> <view class="info-row"> <view class="info-item"> <view class="label">执行人员:</view> <view class="value">{{ task.assignee }}</view> @@ -218,7 +261,10 @@ <uni-icons type="spinner-cycle" size="20" color="#999"></uni-icons> <text>正在加载更多数据...</text> </view> <view class="load-more no-more" v-else-if="filteredTaskList.length > 0 && !hasMore"> <view class="load-more no-more" v-else-if="filteredTaskList.length > 0 && !hasMore" > <text>没有更多数据了</text> </view> </view> @@ -228,15 +274,15 @@ </template> <script> import uniDatetimePicker from '@/uni_modules/uni-datetime-picker/components/uni-datetime-picker/uni-datetime-picker.vue' import { listTask, changeTaskStatus } from '@/api/task' import { mapState } from 'vuex' import { formatDateTime } from '@/utils/common' import { checkTaskCanDepart } from '@/utils/taskValidator' import uniDatetimePicker from "@/uni_modules/uni-datetime-picker/components/uni-datetime-picker/uni-datetime-picker.vue"; import { listTask, changeTaskStatus } from "@/api/task"; import { mapState } from "vuex"; import { formatDateTime } from "@/utils/common"; import { checkTaskCanDepart } from "@/utils/taskValidator"; export default { components: { uniDatetimePicker uniDatetimePicker, }, data() { return { @@ -245,16 +291,16 @@ // 查询条件 searchForm: { vehicle: '', taskNo: '' vehicle: "", taskNo: "", }, statusOptions: ['全部状态', '待处理', '处理中', '已完成'], statusValues: ['', 'pending', 'processing', 'completed'], selectedStatus: '', selectedStatusText: '', startDate: '', endDate: '', currentFilter: 'all', statusOptions: ["全部状态", "待处理", "处理中", "已完成"], statusValues: ["", "pending", "processing", "completed"], selectedStatus: "", selectedStatusText: "", startDate: "", endDate: "", currentFilter: "all", // 任务列表 taskList: [], @@ -265,143 +311,137 @@ currentPage: 1, pageSize: 10, total: 0, hasMore: true } hasMore: true, }; }, computed: { ...mapState({ currentUser: state => state.user currentUser: (state) => state.user, }), filteredTaskList() { let filtered = this.taskList; // 应用筛选器 if (this.currentFilter !== 'all') { filtered = filtered.filter(task => { if (this.currentFilter === 'pending') return task.taskStatus === 'PENDING'; if (this.currentFilter === 'processing') return ['DEPARTING', 'ARRIVED', 'RETURNING', 'IN_PROGRESS'].includes(task.taskStatus); if (this.currentFilter === 'completed') return task.taskStatus === 'COMPLETED'; return true; }); } // 应用状态筛选 if (this.selectedStatus) { const statusMap = { 'pending': ['PENDING'], 'processing': ['DEPARTING', 'ARRIVED', 'RETURNING', 'IN_PROGRESS'], 'completed': ['COMPLETED'] } const validStatuses = statusMap[this.selectedStatus]; if (validStatuses) { filtered = filtered.filter(task => validStatuses.includes(task.taskStatus)); } } // 应用车牌号筛选 - 搜索assignedVehicles数组中的车辆 if (this.searchForm.vehicle) { filtered = filtered.filter(task => { // 在车辆列表中查找匹配的车牌号 if (task.vehicleList && task.vehicleList.length > 0) { return task.vehicleList.some(vehicle => vehicle.vehicleNo && vehicle.vehicleNo.includes(this.searchForm.vehicle) ) } return false }); } // 应用任务编号筛选 - 使用taskCode而不是taskNo if (this.searchForm.taskNo) { filtered = filtered.filter(task => task.showTaskCode && task.showTaskCode.includes(this.searchForm.taskNo) ); } // 应用时间范围筛选 if (this.startDate) { filtered = filtered.filter(task => task.plannedStartTime && task.plannedStartTime >= this.startDate ); } if (this.endDate) { // 结束日期加一天,以便包含当天的数据 const end = new Date(this.endDate); end.setDate(end.getDate() + 1); const endDateStr = end.toISOString().split('T')[0]; filtered = filtered.filter(task => task.plannedStartTime && task.plannedStartTime < endDateStr ); } return filtered; } // 注意:这里不再进行前端过滤,而是直接返回从服务器加载的数据 // 实际的筛选将在请求服务器时完成 return this.taskList; }, }, onLoad() { this.loadTaskList() this.loadTaskList(); // 监听任务列表刷新事件 uni.$on('refreshTaskList', this.handleRefreshEvent) uni.$on("refreshTaskList", this.handleRefreshEvent); }, onShow() { // 页面显示时刷新列表(从其他页面返回时) this.loadTaskList() this.loadTaskList(); }, onUnload() { // 页面销毁时移除事件监听 uni.$off('refreshTaskList', this.handleRefreshEvent) uni.$off("refreshTaskList", this.handleRefreshEvent); }, onPullDownRefresh() { this.refreshList() this.refreshList(); }, // 监听滚动到底部事件 onReachBottom() { if (this.hasMore && !this.loading) { this.loadMore() this.loadMore(); } }, methods: { // 处理刷新事件 handleRefreshEvent() { console.log('收到刷新任务列表事件') this.refreshList() console.log("收到刷新任务列表事件"); this.refreshList(); }, // 加载任务列表 loadTaskList() { this.loading = true this.loading = true; // 重置分页参数 this.currentPage = 1 this.hasMore = true this.taskList = [] this.currentPage = 1; this.hasMore = true; this.taskList = []; // 后端会自动获取当前用户信息,实现综合查询 // 综合查询:当前用户所在机构任务 + 当前用户创建的任务 + 分配给当前用户的任务 const queryParams = { pageNum: this.currentPage, pageSize: this.pageSize, orderByColumn: 'create_time', isAsc: 'desc' orderByColumn: "create_time", isAsc: "desc", }; // 根据筛选条件添加状态参数(优先使用顶部tab筛选条件) if (this.currentFilter === "pending") { queryParams.taskStatus = "PENDING"; } else if (this.currentFilter === "processing") { queryParams.taskStatusList = [ "DEPARTING", "ARRIVED", "RETURNING", "IN_PROGRESS", ].join(","); } else if (this.currentFilter === "completed") { queryParams.taskStatus = "COMPLETED"; } else { // 如果没有使用顶部tab筛选,则使用查询条件中的状态筛选 if (this.selectedStatus) { const statusMap = { pending: "PENDING", processing: [ "DEPARTING", "ARRIVED", "RETURNING", "IN_PROGRESS", ].join(","), completed: "COMPLETED", }; if (statusMap[this.selectedStatus]) { if ( this.selectedStatus === "pending" || this.selectedStatus === "completed" ) { queryParams.taskStatus = statusMap[this.selectedStatus]; } else { queryParams.taskStatusList = statusMap[this.selectedStatus]; } } } } listTask(queryParams).then(response => { this.loading = false const data = response.data || response.rows || [] // 设置总数和是否有更多数据 this.total = response.total || data.length || 0 this.hasMore = data.length === this.pageSize if (this.searchForm.vehicle) { queryParams.vehicleNo = this.searchForm.vehicle; } this.taskList = data.map(task => { if (this.searchForm.taskNo) { queryParams.showTaskCode = this.searchForm.taskNo; } if (this.startDate) { queryParams.startDate = this.startDate; } if (this.endDate) { queryParams.endDate = this.endDate; } listTask(queryParams) .then((response) => { this.loading = false; const data = response.data || response.rows || []; // 设置总数和是否有更多数据 this.total = response.total || data.length || 0; this.hasMore = data.length === this.pageSize; this.taskList = data.map((task) => { // 从assignedVehicles数组中获取车辆信息 let vehicleInfo = '未分配车辆' let vehicleInfo = "未分配车辆"; if (task.assignedVehicles && task.assignedVehicles.length > 0) { // 如果有多个车辆,显示第一个,并标注数量 const firstVehicle = task.assignedVehicles[0] vehicleInfo = firstVehicle.vehicleNo || '未知车牌' const firstVehicle = task.assignedVehicles[0]; vehicleInfo = firstVehicle.vehicleNo || "未知车牌"; if (task.assignedVehicles.length > 1) { vehicleInfo += ` 等${task.assignedVehicles.length}辆` vehicleInfo += ` 等${task.assignedVehicles.length}辆`; } } @@ -410,48 +450,110 @@ // 格式化显示字段 - 使用后端返回的assignedVehicles数据 vehicle: vehicleInfo, vehicleList: task.assignedVehicles || [], startLocation: this.formatAddress(task.departureAddress || task.startLocation || '未设置'), endLocation: this.formatAddress(task.destinationAddress || task.endLocation || '未设置'), startTime: task.plannedStartTime ? formatDateTime(task.plannedStartTime, 'YYYY-MM-DD HH:mm') : '未设置', assignee: task.assigneeName || '未分配' } startLocation: this.formatAddress( task.departureAddress || task.startLocation || "未设置" ), endLocation: this.formatAddress( task.destinationAddress || task.endLocation || "未设置" ), startTime: task.plannedStartTime ? formatDateTime(task.plannedStartTime, "YYYY-MM-DD HH:mm") : "未设置", assignee: task.assigneeName || "未分配", }; }); }) }).catch(error => { this.loading = false console.error('加载任务列表失败:', error) this.$modal.showToast('加载任务列表失败') }) .catch((error) => { this.loading = false; console.error("加载任务列表失败:", error); this.$modal.showToast("加载任务列表失败"); }); }, // 加载更多数据 loadMore() { if (!this.hasMore || this.loading) return if (!this.hasMore || this.loading) return; this.loading = true this.currentPage++ this.loading = true; this.currentPage++; const queryParams = { pageNum: this.currentPage, pageSize: this.pageSize, orderByColumn: 'create_time', isAsc: 'desc' orderByColumn: "create_time", isAsc: "desc", }; // 根据筛选条件添加状态参数(优先使用顶部tab筛选条件) if (this.currentFilter === "pending") { queryParams.taskStatus = "PENDING"; } else if (this.currentFilter === "processing") { queryParams.taskStatusList = [ "DEPARTING", "ARRIVED", "RETURNING", "IN_PROGRESS", ].join(","); } else if (this.currentFilter === "completed") { queryParams.taskStatus = "COMPLETED"; } else { // 如果没有使用顶部tab筛选,则使用查询条件中的状态筛选 if (this.selectedStatus) { const statusMap = { pending: "PENDING", processing: [ "DEPARTING", "ARRIVED", "RETURNING", "IN_PROGRESS", ].join(","), completed: "COMPLETED", }; if (statusMap[this.selectedStatus]) { if ( this.selectedStatus === "pending" || this.selectedStatus === "completed" ) { queryParams.taskStatus = statusMap[this.selectedStatus]; } else { queryParams.taskStatusList = statusMap[this.selectedStatus]; } } } } listTask(queryParams).then(response => { this.loading = false const data = response.data || response.rows || [] // 更新是否有更多数据 this.hasMore = data.length === this.pageSize if (this.searchForm.vehicle) { queryParams.vehicleNo = this.searchForm.vehicle; } const newTasks = data.map(task => { if (this.searchForm.taskNo) { queryParams.showTaskCode = this.searchForm.taskNo; } if (this.startDate) { queryParams.startDate = this.startDate; } if (this.endDate) { queryParams.endDate = this.endDate; } listTask(queryParams) .then((response) => { this.loading = false; const data = response.data || response.rows || []; // 更新是否有更多数据 this.hasMore = data.length === this.pageSize; const newTasks = data.map((task) => { // 从assignedVehicles数组中获取车辆信息 let vehicleInfo = '未分配车辆' let vehicleInfo = "未分配车辆"; if (task.assignedVehicles && task.assignedVehicles.length > 0) { // 如果有多个车辆,显示第一个,并标注数量 const firstVehicle = task.assignedVehicles[0] vehicleInfo = firstVehicle.vehicleNo || '未知车牌' const firstVehicle = task.assignedVehicles[0]; vehicleInfo = firstVehicle.vehicleNo || "未知车牌"; if (task.assignedVehicles.length > 1) { vehicleInfo += ` 等${task.assignedVehicles.length}辆` vehicleInfo += ` 等${task.assignedVehicles.length}辆`; } } @@ -460,32 +562,65 @@ // 格式化显示字段 - 使用后端返回的assignedVehicles数据 vehicle: vehicleInfo, vehicleList: task.assignedVehicles || [], startLocation: this.formatAddress(task.departureAddress || task.startLocation || '未设置'), endLocation: this.formatAddress(task.destinationAddress || task.endLocation || '未设置'), startTime: task.plannedStartTime ? formatDateTime(task.plannedStartTime, 'YYYY-MM-DD HH:mm') : '未设置', assignee: task.assigneeName || '未分配' } }) startLocation: this.formatAddress( task.departureAddress || task.startLocation || "未设置" ), endLocation: this.formatAddress( task.destinationAddress || task.endLocation || "未设置" ), startTime: task.plannedStartTime ? formatDateTime(task.plannedStartTime, "YYYY-MM-DD HH:mm") : "未设置", assignee: task.assigneeName || "未分配", }; }); // 将新数据追加到现有列表中 this.taskList = [...this.taskList, ...newTasks] }).catch(error => { this.loading = false this.currentPage-- // 出错时回退页码 console.error('加载更多任务失败:', error) this.$modal.showToast('加载更多任务失败') this.taskList = [...this.taskList, ...newTasks]; }) .catch((error) => { this.loading = false; this.currentPage--; // 出错时回退页码 console.error("加载更多任务失败:", error); this.$modal.showToast("加载更多任务失败"); }); }, // 格式化地址 - 只显示-前面的部分 formatAddress(address) { if (!address) return '未设置' if (!address) return "未设置"; // 如果地址包含-,只返回-前面的部分 const dashIndex = address.indexOf('-') const dashIndex = address.indexOf("-"); if (dashIndex > 0) { return address.substring(0, dashIndex) return address.substring(0, dashIndex); } return address return address; }, // 获取出发地显示内容(转运任务显示转出医院名称) getStartLocationDisplay(task) { // 如果是转运任务且有emergencyInfo信息 if (task.taskType === 'EMERGENCY_TRANSFER' && task.emergencyInfo && task.emergencyInfo.hospitalOutName) { return task.emergencyInfo.hospitalOutName; } // 其他情况使用原来的startLocation return this.formatAddress(task.startLocation || "未设置"); }, // 获取目的地显示内容(转运任务显示转入医院名称或详细地址) getEndLocationDisplay(task) { // 如果是转运任务且有emergencyInfo信息 if (task.taskType === 'EMERGENCY_TRANSFER' && task.emergencyInfo) { // 优先显示转入医院名称 if (task.emergencyInfo.hospitalInName) { if(task.emergencyInfo.hospitalInName.includes("家中")){ return task.emergencyInfo.destinationAddress; } return task.emergencyInfo.hospitalInName; } } // 其他情况使用原来的endLocation return this.formatAddress(task.endLocation || "未设置"); }, // 切换查询界面显示/隐藏 @@ -501,171 +636,197 @@ // 查询 handleSearch() { this.loadTaskList() this.$modal.showToast('查询成功'); this.loadTaskList(); this.$modal.showToast("查询成功"); // 查询完成后隐藏查询界面 this.showSearch = false; }, // 重置查询条件 resetSearch() { this.selectedStatus = ''; this.selectedStatusText = ''; this.startDate = ''; this.endDate = ''; this.searchForm.vehicle = ''; this.searchForm.taskNo = ''; this.selectedStatus = ""; this.selectedStatusText = ""; this.startDate = ""; this.endDate = ""; this.searchForm.vehicle = ""; this.searchForm.taskNo = ""; }, // 刷新列表 refreshList() { this.refreshing = true this.loadTaskList() this.refreshing = true; this.loadTaskList(); setTimeout(() => { this.refreshing = false this.refreshing = false; // this.$modal.showToast('列表已刷新'); // 停止下拉刷新 uni.stopPullDownRefresh() }, 1000) uni.stopPullDownRefresh(); }, 1000); }, // 筛选 changeFilter(filter) { this.currentFilter = filter; // 重新加载数据 this.loadTaskList(); }, // 查看任务详情 viewTaskDetail(task) { // 防御性检查 if (!task || !task.taskId) { console.error('任务数据无效:', task) this.$modal.showToast('任务数据异常') return console.error("任务数据无效:", task); this.$modal.showToast("任务数据异常"); return; } // 跳转到任务详情页面 - 使用uni.navigateTo uni.navigateTo({ url: `/pagesTask/detail?id=${task.taskId}` url: `/pagesTask/detail?id=${task.taskId}`, }); }, // 处理任务操作 async handleTaskAction(task, action) { switch (action) { case 'depart': case "depart": // 出发 -> 状态变为出发中 // 显示加载提示 uni.showLoading({ title: '检查任务状态...' title: "检查任务状态...", }); try { // 调用工具类检查任务是否可以出发(包含基本校验和冲突检查) const checkResult = await checkTaskCanDepart(task) const checkResult = await checkTaskCanDepart(task); uni.hideLoading(); console.log('出发检查结果:', checkResult); console.log('valid:', checkResult.valid); console.log('conflicts:', checkResult.conflicts); console.log("出发检查结果:", checkResult); console.log("valid:", checkResult.valid); console.log("conflicts:", checkResult.conflicts); if (!checkResult.valid) { // 校验失败,显示提示信息并提供跳转选项 const conflicts = checkResult.conflicts || []; const conflictInfo = conflicts.length > 0 ? conflicts[0] : null; console.log('冲突信息:', conflictInfo); console.log("冲突信息:", conflictInfo); // 如果有冲突任务信息,提供跳转按钮 if (conflictInfo && conflictInfo.taskId) { console.log('显示带跳转按钮的弹窗,任务ID:', conflictInfo.taskId); console.log( "显示带跳转按钮的弹窗,任务ID:", conflictInfo.taskId ); const conflictTaskId = conflictInfo.taskId; const message = checkResult.message || conflictInfo.message || '存在冲突任务'; const message = checkResult.message || conflictInfo.message || "存在冲突任务"; uni.showModal({ title: '提示', title: "提示", content: message, confirmText: '去处理', cancelText: '知道了', confirmText: "去处理", cancelText: "知道了", success: function(res) { console.log('弹窗点击结果:', res); console.log("弹窗点击结果:", res); if (res.confirm) { // 用户点击"现在去处理",跳转到冲突任务详情页 console.log('准备跳转到任务详情页:', conflictTaskId); console.log("准备跳转到任务详情页:", conflictTaskId); uni.navigateTo({ url: `/pagesTask/detail?id=${conflictTaskId}` url: `/pagesTask/detail?id=${conflictTaskId}`, }); } }, fail: function(err) { console.error('显示弹窗失败:', err); } console.error("显示弹窗失败:", err); }, }); } else { // 没有冲突任务ID,只显示提示 console.log('显示普通提示弹窗'); console.log("显示普通提示弹窗"); uni.showModal({ title: '提示', content: checkResult.message || '任务校验失败', title: "提示", content: checkResult.message || "任务校验失败", showCancel: false, confirmText: '知道了', confirmText: "知道了", fail: function(err) { console.error('显示弹窗失败:', err); } console.error("显示弹窗失败:", err); }, }); } return; } // 所有检查通过,可以出发 this.$modal.confirm('确定要出发吗?').then(() => { this.updateTaskStatus(task.taskId, 'DEPARTING', '任务已出发') }).catch(() => {}); this.$modal .confirm("确定要出发吗?") .then(() => { this.updateTaskStatus(task.taskId, "DEPARTING", "任务已出发"); }) .catch(() => {}); } catch (error) { uni.hideLoading(); console.error('检查任务状态失败:', error); console.error("检查任务状态失败:", error); // 检查失败时,仍然允许出发 this.$modal.confirm('检查任务状态失败,是否继续出发?').then(() => { this.updateTaskStatus(task.taskId, 'DEPARTING', '任务已出发') }).catch(() => {}); this.$modal .confirm("检查任务状态失败,是否继续出发?") .then(() => { this.updateTaskStatus(task.taskId, "DEPARTING", "任务已出发"); }) .catch(() => {}); } break; case 'cancel': case "cancel": // 取消 -> 二次确认后状态变为已取消 this.$modal.confirm('确定要取消此任务吗?').then(() => { this.updateTaskStatus(task.taskId, 'CANCELLED', '任务已取消') }).catch(() => {}); this.$modal .confirm("确定要取消此任务吗?") .then(() => { this.updateTaskStatus(task.taskId, "CANCELLED", "任务已取消"); }) .catch(() => {}); break; case 'arrive': case "arrive": // 已到达 -> 状态变为已到达 this.$modal.confirm('确认已到达目的地?').then(() => { this.updateTaskStatus(task.taskId, 'ARRIVED', '已到达目的地') }).catch(() => {}); this.$modal .confirm("确认已到达目的地?") .then(() => { this.updateTaskStatus(task.taskId, "ARRIVED", "已到达目的地"); }) .catch(() => {}); break; case 'forceCancel': case "forceCancel": // 强制结束 -> 状态变为已取消 this.$modal.confirm('确定要强制结束此任务吗?').then(() => { this.updateTaskStatus(task.taskId, 'CANCELLED', '任务已强制结束') }).catch(() => {}); this.$modal .confirm("确定要强制结束此任务吗?") .then(() => { this.updateTaskStatus(task.taskId, "CANCELLED", "任务已强制结束"); }) .catch(() => {}); break; case 'return': case "return": // 已返程 -> 状态变为返程中 this.$modal.confirm('确认开始返程?').then(() => { this.updateTaskStatus(task.taskId, 'RETURNING', '已开始返程') }).catch(() => {}); this.$modal .confirm("确认开始返程?") .then(() => { this.updateTaskStatus(task.taskId, "RETURNING", "已开始返程"); }) .catch(() => {}); break; case 'complete': case "complete": // 已完成 -> 状态变为已完成 this.$modal.confirm('确认任务已完成?').then(() => { this.updateTaskStatus(task.taskId, 'COMPLETED', '任务已完成') }).catch(() => {}); this.$modal .confirm("确认任务已完成?") .then(() => { this.updateTaskStatus(task.taskId, "COMPLETED", "任务已完成"); }) .catch(() => {}); break; } }, @@ -673,106 +834,115 @@ // 更新任务状态 updateTaskStatus(taskId, status, remark) { // 获取GPS位置信息 this.getLocationAndUpdateStatus(taskId, status, remark) this.getLocationAndUpdateStatus(taskId, status, remark); }, // 获取位置信息并更新状态 getLocationAndUpdateStatus(taskId, status, remark) { const that = this const that = this; // 使用uni.getLocation获取GPS位置 uni.getLocation({ type: 'gcj02', type: "gcj02", geocode: true, altitude: true, success: function(res) { console.log('GPS定位成功:', res) console.log("GPS定位成功:", res); const statusData = { taskStatus: status, remark: remark, latitude: res.latitude, longitude: res.longitude, locationAddress: res.address ? res.address.street || res.address.poiName || '' : '', locationProvince: res.address ? res.address.province || '' : '', locationCity: res.address ? res.address.city || '' : '', locationDistrict: res.address ? res.address.district || '' : '', locationAddress: res.address ? res.address.street || res.address.poiName || "" : "", locationProvince: res.address ? res.address.province || "" : "", locationCity: res.address ? res.address.city || "" : "", locationDistrict: res.address ? res.address.district || "" : "", gpsAccuracy: res.accuracy, altitude: res.altitude, speed: res.speed, heading: res.direction || res.heading } heading: res.direction || res.heading, }; changeTaskStatus(taskId, statusData).then(response => { that.$modal.showToast('状态更新成功') changeTaskStatus(taskId, statusData) .then((response) => { that.$modal.showToast("状态更新成功"); // 刷新任务列表 that.loadTaskList() }).catch(error => { console.error('更新任务状态失败:', error) that.$modal.showToast('状态更新失败,请重试') that.loadTaskList(); }) .catch((error) => { console.error("更新任务状态失败:", error); that.$modal.showToast("状态更新失败,请重试"); }); }, fail: function(err) { console.error('GPS定位失败:', err) console.error("GPS定位失败:", err); that.$modal.confirm('GPS定位失败,是否继续更新状态?').then(() => { that.$modal .confirm("GPS定位失败,是否继续更新状态?") .then(() => { const statusData = { taskStatus: status, remark: remark } remark: remark, }; changeTaskStatus(taskId, statusData).then(response => { that.$modal.showToast('状态更新成功') changeTaskStatus(taskId, statusData) .then((response) => { that.$modal.showToast("状态更新成功"); // 刷新任务列表 that.loadTaskList() }).catch(error => { console.error('更新任务状态失败:', error) that.$modal.showToast('状态更新失败,请重试') that.loadTaskList(); }) }).catch(() => {}) } .catch((error) => { console.error("更新任务状态失败:", error); that.$modal.showToast("状态更新失败,请重试"); }); }) .catch(() => {}); }, }); }, getStatusText(status) { const statusMap = { 'PENDING': '待处理', 'DEPARTING': '出发中', 'ARRIVED': '已到达', 'RETURNING': '返程中', 'COMPLETED': '已完成', 'CANCELLED': '已取消', 'IN_PROGRESS': '处理中' // 兼容旧数据 } return statusMap[status] || '未知' PENDING: "待处理", DEPARTING: "出发中", ARRIVED: "已到达", RETURNING: "返程中", COMPLETED: "已完成", CANCELLED: "已取消", IN_PROGRESS: "处理中", // 兼容旧数据 }; return statusMap[status] || "未知"; }, // 获取状态样式类 getStatusClass(status) { const statusClassMap = { 'PENDING': 'status-pending', 'DEPARTING': 'status-departing', 'ARRIVED': 'status-arrived', 'RETURNING': 'status-returning', 'COMPLETED': 'status-completed', 'CANCELLED': 'status-cancelled', 'IN_PROGRESS': 'status-in-progress' } return statusClassMap[status] || 'status-default' PENDING: "status-pending", DEPARTING: "status-departing", ARRIVED: "status-arrived", RETURNING: "status-returning", COMPLETED: "status-completed", CANCELLED: "status-cancelled", IN_PROGRESS: "status-in-progress", }; return statusClassMap[status] || "status-default"; }, getTaskTypeText(type) { const typeMap = { 'MAINTENANCE': '维修保养', 'FUEL': '加油', 'OTHER': '其他', 'EMERGENCY_TRANSFER': '转运任务', 'WELFARE': '福祉车' } return typeMap[type] || '未知类型' } } } MAINTENANCE: "维修保养", FUEL: "加油", OTHER: "其他", EMERGENCY_TRANSFER: "转运任务", WELFARE: "福祉车", }; return typeMap[type] || "未知类型"; }, }, }; </script> <style lang="scss"> @@ -801,17 +971,6 @@ } } // 总部推送标记样式 .head-push-tag { color: #ff0000; font-size: 24rpx; font-weight: bold; margin-left: 10rpx; padding: 2rpx 8rpx; border: 1rpx solid #ff0000; border-radius: 4rpx; } // 任务列表区域 .task-list-section { flex: 1; @@ -838,7 +997,8 @@ .header-actions { display: flex; .search-toggle-btn, .refresh-btn { .search-toggle-btn, .refresh-btn { width: 60rpx; height: 60rpx; border-radius: 50%; @@ -913,7 +1073,8 @@ display: flex; margin-top: 20rpx; .search-btn, .reset-btn { .search-btn, .reset-btn { flex: 1; height: 70rpx; border-radius: 10rpx; @@ -922,7 +1083,7 @@ } .search-btn { background-color: #007AFF; background-color: #007aff; color: white; } } @@ -962,7 +1123,7 @@ font-size: 28rpx; &.active { background-color: #007AFF; background-color: #007aff; color: white; } } @@ -1032,7 +1193,7 @@ // 出发中 - 蓝色 &.status-departing { background-color: #e3f2fd; color: #007AFF; color: #007aff; } // 已到达 - 紫色 @@ -1050,7 +1211,7 @@ // 已完成 - 绿色 &.status-completed { background-color: #e8f5e9; color: #34C759; color: #34c759; } // 已取消 - 灰色 @@ -1062,7 +1223,7 @@ // 处理中 (兼容旧数据) - 蓝色 &.status-in-progress { background-color: #e3f2fd; color: #007AFF; color: #007aff; } // 默认样式 @@ -1073,13 +1234,22 @@ } } // 任务编号单独一行 // 任务编号和时间在同一行显示 .task-code-row { margin-bottom: 15rpx; padding: 10rpx 0; border-bottom: 1rpx dashed #e0e0e0; display: flex; justify-content: space-between; .task-code { font-size: 28rpx; color: #333; font-weight: 500; font-family: monospace; } .task-time { font-size: 28rpx; color: #333; font-weight: 500; @@ -1131,7 +1301,7 @@ color: #333; &.primary { background-color: #007AFF; background-color: #007aff; color: white; } @@ -1178,5 +1348,27 @@ color: #666; } } .vip-tag { display: inline-block; padding: 2rpx 8rpx; font-size: 20rpx; color: #fff; background-color: #ff0000; border-radius: 4rpx; margin-left: 10rpx; vertical-align: middle; } .hq-tag { display: inline-block; padding: 2rpx 8rpx; font-size: 20rpx; color: #fff; background-color: #5856d6; border-radius: 4rpx; margin-left: 10rpx; vertical-align: middle; } } </style> app/pagesTask/components/DepartmentSelector.vue
@@ -227,3 +227,4 @@ } } } </style> app/pagesTask/detail.vue
@@ -14,7 +14,8 @@ <view class="label">任务编号</view> <view class="value"> {{ taskDetail.showTaskCode }} <text v-if="taskDetail.isHeadPush === '1'" class="head-push-tag">总</text> <text v-if="taskDetail.emergencyInfo && taskDetail.emergencyInfo.serviceOrdVip === '1'" class="vip-tag">VIP</text> <text v-if="taskDetail.emergencyInfo && taskDetail.emergencyInfo.fromHq2Is === '1'" class="hq-tag">广总</text> </view> </view> <view class="info-item"> @@ -54,21 +55,12 @@ <view class="assignee-role"> <view class="role-tag" :class="{ 'role-driver': assignee.userType === 'driver', 'role-doctor': assignee.userType === 'doctor', 'role-nurse': assignee.userType === 'nurse' }" > :class="{'role-driver': assignee.userType === 'driver','role-doctor': assignee.userType === 'doctor','role-nurse': assignee.userType === 'nurse'}"> {{ getUserTypeLabel(assignee.userType) }} </view> <view class="ready-badge" :class="{ 'ready': isAssigneeReady(assignee), 'unready': !isAssigneeReady(assignee) }" > :class="{'ready': isAssigneeReady(assignee),'unready': !isAssigneeReady(assignee)}"> {{ isAssigneeReady(assignee) ? '已就绪' : '未就绪' }} </view> </view> @@ -105,13 +97,13 @@ <view class="section-title">位置信息</view> <!-- 转运任务:显示转出/转入医院地址 --> <template v-if="taskDetail.taskType === 'EMERGENCY_TRANSFER' && taskDetail.emergencyInfo"> <view class="info-item" v-if="taskDetail.emergencyInfo.hospitalOutAddress"> <view class="info-item" v-if="taskDetail.emergencyInfo.hospitalOutName"> <view class="label">转出医院</view> <view class="value">{{ taskDetail.emergencyInfo.hospitalOutAddress }}</view> <view class="value">{{ taskDetail.emergencyInfo.hospitalOutName }}</view> </view> <view class="info-item" v-if="taskDetail.emergencyInfo.hospitalInAddress"> <view class="info-item" v-if="taskDetail.emergencyInfo.hospitalInName"> <view class="label">转入医院</view> <view class="value">{{ taskDetail.emergencyInfo.hospitalInAddress }}</view> <view class="value">{{ taskDetail.emergencyInfo.hospitalInName }}</view> </view> </template> <!-- 福祉车任务:显示接送/目的地址 --> @@ -499,7 +491,19 @@ } return ['COMPLETED', 'CANCELLED'].includes(this.taskDetail.taskStatus) }, // 显示任务类型 // 生成执行人员角色标签的类名 getRoleTagClass() { return (userType) => { const baseClass = 'role-tag' const roleClasses = { 'driver': 'role-driver', 'doctor': 'role-doctor', 'nurse': 'role-nurse' } return [baseClass, roleClasses[userType] || ''] } }, // 显示任务类型 displayTaskType() { if (!this.taskDetail || !this.taskDetail.taskType) { return '未设置' @@ -594,13 +598,7 @@ 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('转运任务信息 (emergencyInfo):', this.taskDetail.emergencyInfo) // 如果是转运任务,加载支付信息 if (this.taskDetail.taskType === 'EMERGENCY_TRANSFER') { @@ -1464,17 +1462,6 @@ } } // 总部推送标记样式 .head-push-tag { color: #ff0000; font-size: 24rpx; font-weight: bold; margin-left: 10rpx; padding: 2rpx 8rpx; border: 1rpx solid #ff0000; border-radius: 4rpx; } .detail-content { padding: 20rpx; height: calc(100vh - 220rpx); // 减去header(100rpx)和按钮区域(120rpx)的高度 @@ -1816,5 +1803,27 @@ } } } .vip-tag { display: inline-block; padding: 2rpx 8rpx; font-size: 20rpx; color: #fff; background-color: #ff0000; border-radius: 4rpx; margin-left: 10rpx; vertical-align: middle; } .hq-tag { display: inline-block; padding: 2rpx 8rpx; font-size: 20rpx; color: #fff; background-color: #5856d6; border-radius: 4rpx; margin-left: 10rpx; vertical-align: middle; } } </style> app/pagesTask/edit-emergency.vue
@@ -39,6 +39,26 @@ /> <view class="form-item"> <view class="form-label required">任务类型</view> <picker mode="selector" :range="emergencyTaskTypeOptions" range-key="text" @change="onEmergencyTaskTypeChange"> <view class="form-input picker-input"> {{ selectedEmergencyTaskType || '请选择任务类型' }} <uni-icons type="arrowright" size="16" color="#999"></uni-icons> </view> </picker> </view> <view class="form-item"> <view class="form-label required">单据类型</view> <picker mode="selector" :range="documentTypeOptions" range-key="text" @change="onDocumentTypeChange"> <view class="form-input picker-input"> {{ selectedDocumentType || '请选择单据类型' }} <uni-icons type="arrowright" size="16" color="#999"></uni-icons> </view> </picker> </view> <view class="form-item"> <view class="form-label required">转运时间</view> <uni-datetime-picker v-model="taskForm.transferTime" @@ -233,6 +253,7 @@ import { getTask, updateTask } from "@/api/task" import { tiandituDistanceByAddress } from "@/api/map" import { calculateTransferPrice } from "@/api/price" import { getServiceOrdAreaTypes, getServiceOrderTypes } from "@/api/dictionary" import MapSelector from './components/map-selector.vue' import VehicleSelector from './components/VehicleSelector.vue' import OrganizationSelector from './components/OrganizationSelector.vue' @@ -280,6 +301,17 @@ departureLatitude: null, selectedDiseases: [], // 已选择的病情列表(确保初始化为空数组) selectedStaff: [], // 已选择的人员列表(确保初始化为空数组) // 任务类型和单据类型相关 selectedEmergencyTaskType: '', // 选中的任务类型文本 selectedEmergencyTaskTypeId: null, // 选中的任务类型ID selectedDocumentType: '', // 选中的单据类型文本 selectedDocumentTypeId: null, // 选中的单据类型ID pendingTaskTypeId: null, // 等待设置的任务类型ID pendingDocumentTypeId: null, // 等待设置的单据类型ID emergencyTaskTypes: [], // 任务类型列表(从 SQL Server 动态加载) emergencyTaskTypeOptions: [], // 任务类型选项(用于picker显示) documentTypes: [], // 单据类型列表 documentTypeOptions: [], // 单据类型选项(用于picker显示) taskForm: { transferTime: '', patient: { @@ -326,6 +358,10 @@ if (options.id) { this.taskId = options.id this.loadTaskDetail() // 加载任务类型数据 this.loadEmergencyTaskTypes() // 加载单据类型数据 this.loadDocumentTypes() } else { this.$modal.showToast('任务ID不能为空') setTimeout(() => { @@ -420,6 +456,31 @@ // 转运距离和价格 this.taskForm.transferDistance = info.transferDistance ? String(info.transferDistance) : '' this.taskForm.price = info.transferPrice ? String(info.transferPrice) : '' // 任务类型和单据类型 if (info.taskTypeId) { // 直接设置任务类型,如果选项还未加载完成,则在加载完成后再次设置 const taskType = this.emergencyTaskTypeOptions.find(option => option.id == info.taskTypeId) if (taskType) { this.selectedEmergencyTaskType = taskType.text this.selectedEmergencyTaskTypeId = taskType.id } else { // 如果选项还未加载完成,标记需要设置的ID this.pendingTaskTypeId = info.taskTypeId } } if (info.documentTypeId) { // 直接设置单据类型,如果选项还未加载完成,则在加载完成后再次设置 const docType = this.documentTypeOptions.find(option => option.id == info.documentTypeId) if (docType) { this.selectedDocumentType = docType.text this.selectedDocumentTypeId = docType.id } else { // 如果选项还未加载完成,标记需要设置的ID this.pendingDocumentTypeId = info.documentTypeId } } } else { console.warn('任务详情中没有emergencyInfo字段,尝试从主对象获取数据') // 兼容处理:如果emergencyInfo不存在,尝试从主对象获取 @@ -509,6 +570,92 @@ // 车辆选择变化 onVehicleChange(vehicle) { console.log('选中车辆:', vehicle) }, // 加载任务类型数据(从 SQL Server) loadEmergencyTaskTypes() { getServiceOrderTypes().then(response => { const list = response.data || [] this.emergencyTaskTypes = list this.emergencyTaskTypeOptions = list.map(item => ({ id: item.vID, text: item.vtext })) // 如果任务详情已加载,设置当前选中的任务类型 if (this.taskDetail && this.taskDetail.emergencyInfo && this.taskDetail.emergencyInfo.taskTypeId) { const currentType = this.emergencyTaskTypeOptions.find(option => option.id == this.taskDetail.emergencyInfo.taskTypeId) if (currentType) { this.selectedEmergencyTaskType = currentType.text this.selectedEmergencyTaskTypeId = currentType.id } } // 检查是否有待设置的任务类型ID if (this.pendingTaskTypeId) { const pendingType = this.emergencyTaskTypeOptions.find(option => option.id == this.pendingTaskTypeId) if (pendingType) { this.selectedEmergencyTaskType = pendingType.text this.selectedEmergencyTaskTypeId = pendingType.id this.pendingTaskTypeId = null } } }).catch(error => { console.error('加载任务类型失败:', error) this.emergencyTaskTypes = [] this.emergencyTaskTypeOptions = [] }) }, // 任务类型选择 onEmergencyTaskTypeChange(e) { const index = e.detail.value const selected = this.emergencyTaskTypeOptions[index] this.selectedEmergencyTaskType = selected.text this.selectedEmergencyTaskTypeId = selected.id }, // 加载单据类型数据 loadDocumentTypes() { getServiceOrdAreaTypes().then(response => { const list = response.data || [] this.documentTypes = list this.documentTypeOptions = list.map(item => ({ id: item.vID, text: item.vtext })) // 如果任务详情已加载,设置当前选中的单据类型 if (this.taskDetail && this.taskDetail.emergencyInfo && this.taskDetail.emergencyInfo.documentTypeId) { const currentType = this.documentTypeOptions.find(option => option.id == this.taskDetail.emergencyInfo.documentTypeId) if (currentType) { this.selectedDocumentType = currentType.text this.selectedDocumentTypeId = currentType.id } } // 检查是否有待设置的单据类型ID if (this.pendingDocumentTypeId) { const pendingType = this.documentTypeOptions.find(option => option.id == this.pendingDocumentTypeId) if (pendingType) { this.selectedDocumentType = pendingType.text this.selectedDocumentTypeId = pendingType.id this.pendingDocumentTypeId = null } } }).catch(error => { console.error('加载单据类型失败:', error) this.documentTypes = [] this.documentTypeOptions = [] }) }, // 单据类型选择 onDocumentTypeChange(e) { const index = e.detail.value const selected = this.documentTypeOptions[index] this.selectedDocumentType = selected.text this.selectedDocumentTypeId = selected.id }, // 加载所有机构ID @@ -815,6 +962,16 @@ return false } if (!this.selectedEmergencyTaskType) { this.$modal.showToast('请选择任务类型') return false } if (!this.selectedDocumentType) { this.$modal.showToast('请选择单据类型') return false } if (!this.taskForm.patient.contact) { this.$modal.showToast('请输入联系人') return false @@ -940,6 +1097,9 @@ deptId: this.selectedOrganizationId, vehicleIds: this.selectedVehicleId ? [this.selectedVehicleId] : [], plannedStartTime: this.taskForm.transferTime, // 任务类型和单据类型 taskTypeId: this.selectedEmergencyTaskTypeId, documentTypeId: this.selectedDocumentTypeId, // 出发地地址和坐标(使用转出医院地址) departureAddress: this.departureAddress || this.taskForm.hospitalOut.address, @@ -1178,6 +1338,7 @@ } } } </script> <style lang="scss" scoped> @@ -1390,3 +1551,4 @@ } } } </style> ruoyi-common/src/main/java/com/ruoyi/common/utils/IntegerUtil.java
New file @@ -0,0 +1,27 @@ package com.ruoyi.common.utils; import com.sun.org.apache.xpath.internal.operations.Bool; public class IntegerUtil { public static Boolean isInteger(String str) { try { Integer.parseInt(str); return true; } catch (Exception e) { return false; } } /** * 为空或小于0 * @param integer * @return */ public static Boolean isEmpty(Integer integer){ return integer==null || integer<=0; } public static Boolean isNotEmpty(Integer integer){ return !isEmpty(integer); } } ruoyi-system/src/main/java/com/ruoyi/system/domain/SysTask.java
@@ -32,18 +32,7 @@ @Excel(name = "任务状态", readConverterExp = "PENDING=待开始,IN_PROGRESS=任务中,COMPLETED=已完成,CANCELLED=已取消") private String taskStatus; /** 是否总部推送 */ @Excel(name = "是否总部推送", readConverterExp = "0=否,1=是") private String isHeadPush; public void setIsHeadPush(String isHeadPush) { this.isHeadPush = isHeadPush; } public String getIsHeadPush() { return isHeadPush; } /** 任务描述 */ @Excel(name = "任务描述") private String taskDescription; ruoyi-system/src/main/java/com/ruoyi/system/domain/SysTaskEmergency.java
@@ -151,6 +151,12 @@ /** 旧系统服务单分类 */ private String legacyServiceOrdClass; /** 是否VIP客户(0否 1是) */ private String serviceOrdVip; /** 是否广州总部推送(0否 1是) */ private String fromHq2Is; public String getServiceCode(){ if(this.legacyServiceOrdClass!=null && this.legacyServiceNsTime!=null && this.legacyServiceOrdNo!=null) { String nstime = DateUtils.parseDateToStr(DateUtils.YYYYMMDD, this.legacyServiceNsTime); @@ -540,6 +546,22 @@ this.legacyServiceOrdClass = legacyServiceOrdClass; } public String getServiceOrdVip() { return serviceOrdVip; } public void setServiceOrdVip(String serviceOrdVip) { this.serviceOrdVip = serviceOrdVip; } public String getFromHq2Is() { return fromHq2Is; } public void setFromHq2Is(String fromHq2Is) { this.fromHq2Is = fromHq2Is; } @Override public String toString() { return "SysTaskEmergency{" + ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/TaskCreateVO.java
@@ -141,6 +141,34 @@ private String taskStatus; private String serviceOrdVIP; public String getServiceOrdVIP() { if(serviceOrdVIP != null) return serviceOrdVIP; else { return "0"; } } public void setServiceOrdVIP(String serviceOrdVIP) { this.serviceOrdVIP = serviceOrdVIP; } /** 旧系统是否来自HQ2 */ private String FromHQ2_is; public String getFromHQ2_is() { if(FromHQ2_is != null) return FromHQ2_is; else { return "0"; } } public void setFromHQ2_is(String fromHQ2_is) { FromHQ2_is = fromHQ2_is; } // 执行人员信息内部类 public static class AssigneeInfo { /** 用户ID */ ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/TaskQueryVO.java
@@ -23,6 +23,9 @@ /** 任务状态 */ private String taskStatus; /** 任务状态列表 */ private String taskStatusList; /** 车牌号 */ private String vehicleNo; @@ -160,4 +163,12 @@ public void setOverdue(Boolean overdue) { this.overdue = overdue; } public String getTaskStatusList() { return taskStatusList; } public void setTaskStatusList(String taskStatusList) { this.taskStatusList = taskStatusList; } } ruoyi-system/src/main/java/com/ruoyi/system/service/impl/LegacyTransferSyncServiceImpl.java
@@ -2,10 +2,7 @@ import com.ruoyi.common.core.domain.entity.SysDept; import com.ruoyi.common.core.domain.entity.SysUser; import com.ruoyi.common.utils.DateUtils; import com.ruoyi.common.utils.LongUtil; import com.ruoyi.common.utils.MapValueUtils; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.*; import com.ruoyi.system.domain.SysTaskEmergency; import com.ruoyi.system.domain.VehicleInfo; import com.ruoyi.system.domain.enums.TaskStatus; @@ -471,8 +468,21 @@ createTaskVo.setTaskTypeId(serviceOrdType); } // 设置区域类型 String serviceOrdAreaType = MapValueUtils.getStringValue(order, "ServiceOrdAreaType"); String serviceOrdVIP = MapValueUtils.getStringValue(order, "ServiceOrdVIP"); if(serviceOrdVIP!=null){ createTaskVo.setServiceOrdVIP(serviceOrdVIP); }else{ createTaskVo.setServiceOrdVIP("0"); } Integer FromHQ2_is = MapValueUtils.getIntegerValue(order, "FromHQ2_is"); if(IntegerUtil.isNotEmpty(FromHQ2_is)){ createTaskVo.setFromHQ2_is("1"); }else{ createTaskVo.setFromHQ2_is("0"); } // 设置用户ID Long serviceOrdUserID = MapValueUtils.getLongValue(order, "ServiceOrdUserID"); ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysEmergencyTaskServiceImpl.java
@@ -44,6 +44,8 @@ Long serviceOrderId, Long dispatchOrderId, String serviceOrdNo) { SysTaskEmergency emergencyInfo = new SysTaskEmergency(); emergencyInfo.setTaskId(taskId); emergencyInfo.setServiceOrdVip(createVO.getServiceOrdVIP()); emergencyInfo.setFromHq2Is(createVO.getFromHQ2_is()); if (createVO.getPatient() != null) { emergencyInfo.setPatientContact(createVO.getPatient().getContact()); @@ -307,6 +309,9 @@ oldEmergency.setLegacyServiceOrdClass(updateVO.getLegacyServiceOrdClass()); } oldEmergency.setFromHq2Is(updateVO.getFromHQ2_is()); oldEmergency.setServiceOrdVip(updateVO.getServiceOrdVIP()); sysTaskEmergencyMapper.updateSysTaskEmergency(oldEmergency); } @@ -473,6 +478,8 @@ existingInfo.setLegacyServiceOrdClass(createVO.getLegacyServiceOrdClass()); } existingInfo.setServiceOrdVip(createVO.getServiceOrdVIP()); existingInfo.setFromHq2Is(createVO.getFromHQ2_is()); // 执行更新 sysTaskEmergencyMapper.updateSysTaskEmergency(existingInfo); } ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTaskServiceImpl.java
@@ -256,6 +256,7 @@ task.setPlannedStartTime(createVO.getPlannedStartTime()); task.setPlannedEndTime(createVO.getPlannedEndTime()); task.setAssigneeId(createVO.getAssigneeId()); task.setCreatorId(userId); // 优先使用前端传入的部门ID,如果没有则使用当前用户的部门ID task.setDeptId(createVO.getDeptId() != null ? createVO.getDeptId() : SecurityUtils.getDeptId()); @@ -266,7 +267,7 @@ task.setRemark(createVO.getRemark()); task.setDelFlag("0"); task.setIsHeadPush(isTaskHeaderPush(userId,task.getDeptId())?"1":"0"); // task.setIsHeadPush(isTaskHeaderPush(userId,task.getDeptId())?"1":"0"); // 设置地址和坐标信息 setAddressAndCoordinatesFromVO(task, createVO); @@ -371,12 +372,12 @@ task.setRemark(createVO.getRemark()); task.setDelFlag("0"); Boolean isHeadPush=this.isTaskHeaderPush(userId, deptId); if(isHeadPush){ task.setIsHeadPush("1"); }else{ task.setIsHeadPush("0"); } // Boolean isHeadPush=this.isTaskHeaderPush(userId, deptId); // if(isHeadPush){ // task.setIsHeadPush("1"); // }else{ // task.setIsHeadPush("0"); // } @@ -519,7 +520,7 @@ } Boolean hasSetDepartureFlag=false; //设置总部推送 task.setIsHeadPush(this.isTaskHeaderPush(task.getCreatorId(), task.getDeptId())?"1":"0"); // task.setIsHeadPush(this.isTaskHeaderPush(task.getCreatorId(), task.getDeptId())?"1":"0"); // 自动获取出发地GPS坐标(如果更新了地址但缺失坐标) if (updateVO.getDepartureAddress() != null && (updateVO.getDepartureLongitude() == null || updateVO.getDepartureLatitude() == null) && ruoyi-system/src/main/resources/mapper/system/LegacyTransferSyncMapper.xml
@@ -46,6 +46,8 @@ <result property="DispatchOrdState" column="DispatchOrdState" /> <result property="DispatchOrdNo" column="DispatchOrdNo" /> <result property="DispatchOrdClass" column="DispatchOrdClass" /> <result property="ServiceOrdVIP" column="ServiceOrdVIP" /> <result property="FromHQ2_is" column="FromHQ2_is" /> <result property="DispatchOrd_NS_Time" column="DispatchOrd_NS_Time" /> </resultMap> @@ -63,6 +65,8 @@ a.ServiceOrdID, a.Old_ServiceOrdID_TXT, a.ServiceOrdNo, a.FromHQ2_is, a.ServiceOrdVIP, a.ServiceOrdTraVia, a.ServiceOrdApptDate, a.ServiceOrd_NS_ID, @@ -115,6 +119,8 @@ a.ServiceOrdID, a.Old_ServiceOrdID_TXT, a.ServiceOrdTraVia, a.FromHQ2_is, a.ServiceOrdVIP, a.ServiceOrdNo, a.ServiceOrdApptDate, a.ServiceOrdUserID, @@ -165,6 +171,8 @@ SELECT a.ServiceOrdID, a.Old_ServiceOrdID_TXT, a.FromHQ2_is, a.ServiceOrdVIP, a.ServiceOrdTraVia, a.ServiceOrdNo, a.ServiceOrdApptDate, ruoyi-system/src/main/resources/mapper/system/SysTaskEmergencyMapper.xml
@@ -51,6 +51,8 @@ <result property="legacyDispatchNsTime" column="legacy_dispatch_ns_time" /> <result property="legacyDispatchOrdClass" column="legacy_dispatch_ord_class" /> <result property="legacyServiceOrdClass" column="legacy_service_ord_class" /> <result property="serviceOrdVip" column="service_ord_vip" /> <result property="fromHq2Is" column="from_hq2_is" /> <result property="createTime" column="create_time" /> <result property="updateTime" column="update_time" /> <result property="createBy" column="create_by" /> @@ -65,7 +67,7 @@ hospital_in_department_id, hospital_in_bed_number, hospital_in_address, hospital_in_longitude, hospital_in_latitude, transfer_distance, transfer_price, passenger_contact, passenger_phone, disease_ids, document_type_id, task_type_id, legacy_service_ord_id, legacy_dispatch_ord_id, sync_status, sync_time, sync_error_msg, dispatch_sync_status, dispatch_sync_time, dispatch_sync_error_msg, need_resync, legacy_service_ord_no, legacy_dispatch_ord_no, legacy_service_ns_time, legacy_dispatch_ns_time, legacy_dispatch_ord_class, legacy_service_ord_class, sync_status, sync_time, sync_error_msg, dispatch_sync_status, dispatch_sync_time, dispatch_sync_error_msg, need_resync, legacy_service_ord_no, legacy_dispatch_ord_no, legacy_service_ns_time, legacy_dispatch_ns_time, legacy_dispatch_ord_class, legacy_service_ord_class, service_ord_vip, from_hq2_is, create_time, update_time, create_by, update_by from sys_task_emergency </sql> @@ -128,6 +130,8 @@ <if test="legacyDispatchNsTime != null">legacy_dispatch_ns_time,</if> <if test="legacyDispatchOrdClass != null">legacy_dispatch_ord_class,</if> <if test="legacyServiceOrdClass != null">legacy_service_ord_class,</if> <if test="serviceOrdVip != null">service_ord_vip,</if> <if test="fromHq2Is != null">from_hq2_is,</if> <if test="createTime != null">create_time,</if> <if test="updateTime != null">update_time,</if> <if test="createBy != null">create_by,</if> @@ -179,6 +183,8 @@ <if test="legacyDispatchNsTime != null">#{legacyDispatchNsTime},</if> <if test="legacyDispatchOrdClass != null">#{legacyDispatchOrdClass},</if> <if test="legacyServiceOrdClass != null">#{legacyServiceOrdClass},</if> <if test="serviceOrdVip != null">#{serviceOrdVip},</if> <if test="fromHq2Is != null">#{fromHq2Is},</if> <if test="createTime != null">#{createTime},</if> <if test="updateTime != null">#{updateTime},</if> <if test="createBy != null">#{createBy},</if> @@ -233,6 +239,8 @@ <if test="legacyDispatchNsTime != null">legacy_dispatch_ns_time = #{legacyDispatchNsTime},</if> <if test="legacyDispatchOrdClass != null">legacy_dispatch_ord_class = #{legacyDispatchOrdClass},</if> <if test="legacyServiceOrdClass != null">legacy_service_ord_class = #{legacyServiceOrdClass},</if> <if test="serviceOrdVip != null">service_ord_vip = #{serviceOrdVip},</if> <if test="fromHq2Is != null">from_hq2_is = #{fromHq2Is},</if> <if test="updateTime != null">update_time = #{updateTime},</if> <if test="updateBy != null">update_by = #{updateBy},</if> </trim> ruoyi-system/src/main/resources/mapper/system/SysTaskMapper.xml
@@ -35,7 +35,6 @@ <result property="assigneeName" column="assignee_name" /> <result property="deptName" column="dept_name" /> <result property="vehicleNo" column="vehicle_no" /> <result property="isHeadPush" column="is_head_push" /> <collection property="assignedVehicles" ofType="SysTaskVehicle"> <result property="id" column="tv_id" /> <result property="taskId" column="tv_task_id" /> @@ -58,7 +57,6 @@ t.planned_start_time, t.planned_end_time, t.actual_start_time, t.actual_end_time, t.creator_id, t.assignee_id, t.dept_id, t.create_time, t.update_time, t.create_by, t.update_by, t.remark, t.del_flag, t.legacy_synced, t.is_head_push, u1.nick_name as creator_name, u2.nick_name as assignee_name, d.dept_name, ( select v2.vehicle_no @@ -88,6 +86,11 @@ <if test="taskCode != null and taskCode != ''"> and t.task_code like concat('%', #{taskCode}, '%')</if> <if test="taskType != null and taskType != ''"> and t.task_type = #{taskType}</if> <if test="taskStatus != null and taskStatus != ''"> and t.task_status = #{taskStatus}</if> <if test="taskStatusList != null and taskStatusList != ''"> and t.task_status in <foreach collection="taskStatusList.split(',')" item="status" open="(" separator="," close=")"> #{status} </foreach> </if> <if test="vehicleNo != null and vehicleNo != ''"> and v.vehicle_no like concat('%', #{vehicleNo}, '%')</if> <!-- 综合查询:当前用户所在机构 OR 当前用户创建 OR 分配给当前用户 --> <if test="(creatorId != null and creatorId != 0) or (assigneeId != null and assigneeId != 0) or (deptId != null and deptId != 0) or (deptIds != null and deptIds.size() > 0)"> @@ -236,7 +239,6 @@ <if test="creatorId != null">creator_id,</if> <if test="assigneeId != null">assignee_id,</if> <if test="deptId != null">dept_id,</if> <if test="isHeadPush != null">is_head_push,</if> <if test="createTime != null">create_time,</if> update_time, <if test="createBy != null">create_by,</if> @@ -294,7 +296,6 @@ <if test="creatorId != null">creator_id = #{creatorId},</if> <if test="assigneeId != null">assignee_id = #{assigneeId},</if> <if test="deptId != null">dept_id = #{deptId},</if> <if test="isHeadPush != null">is_head_push = #{isHeadPush},</if> <if test="updateTime != null">update_time = #{updateTime},</if> <if test="updateBy != null">update_by = #{updateBy},</if> <if test="remark != null">remark = #{remark},</if> sql/add_vip_and_hq_fields_to_sys_task_emergency.sql
New file @@ -0,0 +1,20 @@ -- ---------------------------- -- 在 sys_task_emergency 表中增加 ServiceOrdVIP 和 FromHQ2_is 字段 -- ServiceOrdVIP:是否VIP客户(0表示非VIP,1表示VIP) -- FromHQ2_is:是否广州总部推送标记(空或0表示非广州总部推送,1表示广州总部推送) -- ---------------------------- -- 添加 ServiceOrdVIP 字段 ALTER TABLE sys_task_emergency ADD COLUMN service_ord_vip CHAR(1) DEFAULT '0' COMMENT '是否VIP客户(0否 1是)'; -- 添加 FromHQ2_is 字段 ALTER TABLE sys_task_emergency ADD COLUMN from_hq2_is CHAR(1) DEFAULT '0' COMMENT '是否广州总部推送(0否 1是)'; -- 添加索引以提高查询性能 ALTER TABLE sys_task_emergency ADD INDEX idx_service_ord_vip (service_ord_vip); ALTER TABLE sys_task_emergency ADD INDEX idx_from_hq2_is (from_hq2_is); sql/remove_is_head_push_from_sys_task.sql
New file @@ -0,0 +1,5 @@ -- 删除 sys_task 表中的 is_head_push 字段 -- 用于移除任务是否由总部推送的标记 ALTER TABLE sys_task DROP COLUMN is_head_push;