| New file |
| | |
| | | # GPS åæ®µéç¨é夿å
¥é®é¢ä¿®å¤è¯´æ |
| | | |
| | | ## é®é¢æè¿° |
| | | |
| | | 卿§è¡ GPS åæ®µéç¨è®¡ç®æ¶ï¼ç³»ç»æåºä»¥ä¸å¼å¸¸ï¼ |
| | | |
| | | ``` |
| | | org.springframework.jdbc.UncategorizedSQLException: |
| | | ### Cause: java.sql.SQLIntegrityConstraintViolationException: Duplicate entry '9-2026-03-15 06:10:00' for key 'tb_vehicle_gps_segment_mileage.uk_vehicle_time' |
| | | ``` |
| | | |
| | | ## æ ¹æ¬åå |
| | | |
| | | æ°æ®åºè¡¨ `tb_vehicle_gps_segment_mileage` å®ä¹äºå¯ä¸ç´¢å¼ `uk_vehicle_time (vehicle_id, segment_start_time)`ï¼ç¨äºç¡®ä¿åä¸è½¦è¾å¨å䏿¶é´æ®µçåæ®µéç¨è®°å½åªæä¸æ¡ã |
| | | |
| | | è½ç¶å¨ä»£ç å±é¢ï¼`VehicleGpsSegmentMileageServiceImpl.java` 第 390 è¡ï¼å·²ç»ææ£æ¥é»è¾ï¼ |
| | | |
| | | ```java |
| | | if (isSegmentAlreadyCalculated(vehicleId, segmentStartTime, segmentGpsList)) { |
| | | previousSegmentLastPoint = segmentGpsList.get(segmentGpsList.size() - 1); |
| | | continue; |
| | | } |
| | | ``` |
| | | |
| | | ä½å¨**å¹¶ååºæ¯**ä¸ï¼ä»å¯è½åºç°ç«ææ¡ä»¶ï¼Race Conditionï¼ï¼ |
| | | |
| | | 1. **çº¿ç¨ A** æ£æ¥æ¶é´æ®µ 2026-03-15 06:10:00ï¼åç°ä¸åå¨ |
| | | 2. **çº¿ç¨ B** åæ¶æ£æ¥å䏿¶é´æ®µï¼ä¹åç°ä¸åå¨ |
| | | 3. **çº¿ç¨ A** æ§è¡ INSERT |
| | | 4. **çº¿ç¨ B** å°è¯æ§è¡ INSERTï¼è¿åå¯ä¸ç´¢å¼çº¦æï¼æåºå¼å¸¸ |
| | | |
| | | ## è§£å³æ¹æ¡ |
| | | |
| | | ä¿®æ¹ MyBatis Mapper XML æä»¶ä¸ç INSERT è¯å¥ï¼ä½¿ç¨ MySQL ç `ON DUPLICATE KEY UPDATE` è¯æ³ï¼ |
| | | |
| | | ### ä¿®æ¹æä»¶ |
| | | - `ruoyi-system/src/main/resources/mapper/system/VehicleGpsSegmentMileageMapper.xml` |
| | | |
| | | ### ä¿®æ¹å
容 |
| | | |
| | | å¨åæç `insertVehicleGpsSegmentMileage` æ¹æ³ä¸æ·»å `ON DUPLICATE KEY UPDATE` åå¥ï¼ |
| | | |
| | | ```xml |
| | | <insert id="insertVehicleGpsSegmentMileage" parameterType="VehicleGpsSegmentMileage"> |
| | | INSERT INTO tb_vehicle_gps_segment_mileage |
| | | <trim prefix="(" suffix=")" suffixOverrides=","> |
| | | <!-- åæ®µå表 --> |
| | | </trim> |
| | | <trim prefix="values (" suffix=")" suffixOverrides=","> |
| | | <!-- å¼å表 --> |
| | | </trim> |
| | | ON DUPLICATE KEY UPDATE |
| | | vehicle_no = VALUES(vehicle_no), |
| | | segment_end_time = VALUES(segment_end_time), |
| | | start_longitude = VALUES(start_longitude), |
| | | start_latitude = VALUES(start_latitude), |
| | | end_longitude = VALUES(end_longitude), |
| | | end_latitude = VALUES(end_latitude), |
| | | segment_distance = VALUES(segment_distance), |
| | | gps_point_count = VALUES(gps_point_count), |
| | | gps_ids = VALUES(gps_ids), |
| | | task_id = VALUES(task_id), |
| | | task_code = VALUES(task_code), |
| | | calculate_method = VALUES(calculate_method), |
| | | update_time = NOW() |
| | | </insert> |
| | | ``` |
| | | |
| | | ## ææ¯ä¼å¿ |
| | | |
| | | ä½¿ç¨ `ON DUPLICATE KEY UPDATE` ç好å¤ï¼ |
| | | |
| | | 1. **ååæ§æä½**ï¼æ°æ®åºå±é¢ä¿è¯æå
¥ææ´æ°çååæ§ï¼é¿å
å¹¶åå²çª |
| | | 2. **æ éé¢å¤æ¥è¯¢**ï¼ä¸éè¦å
SELECT åå³å® INSERT è¿æ¯ UPDATE |
| | | 3. **æ§è½æ´ä¼**ï¼åå°ä¸æ¬¡æ°æ®åºæ¥è¯¢å¼é |
| | | 4. **代ç ç®æ´**ï¼ä¸éè¦å¤æçå¼å¸¸æè·åéè¯é»è¾ |
| | | 5. **æ°æ®ä¸è´æ§**ï¼å¦æåçéå¤ï¼èªå¨æ´æ°å·²æè®°å½è䏿¯æ¥é |
| | | |
| | | ## å½±åèå´ |
| | | |
| | | - **åå½±åçåè½**ï¼GPS åæ®µéç¨è®¡ç® |
| | | - **åå½±åç表**ï¼`tb_vehicle_gps_segment_mileage` |
| | | - **åå½±åçæ¥å£**ï¼ææè°ç¨ `insertVehicleGpsSegmentMileage` çæ¹æ³ |
| | | |
| | | ## æµè¯å»ºè®® |
| | | |
| | | 1. **å¹¶åæµè¯**ï¼æ¨¡æå¤ä¸ªçº¿ç¨åæ¶è®¡ç®åä¸è½¦è¾ç GPS åæ®µéç¨ |
| | | 2. **é夿°æ®æµè¯**ï¼æå¨æé éå¤çè½¦è¾ ID + æ¶é´æ®µå¼å§æ¶é´ï¼éªè¯æ¯å¦è½æ£ç¡®æ´æ° |
| | | 3. **å彿µè¯**ï¼ç¡®ä¿æ£å¸¸çæå
¥åè½ä¸åå½±å |
| | | |
| | | ## é¨ç½²æ¥éª¤ |
| | | |
| | | 1. éå¯åºç¨æå¡å¨å³å¯çæ |
| | | 2. æ éæ§è¡ä»»ä½ SQL èæ¬ |
| | | 3. æ éä¿®æ¹æ°æ®åºè¡¨ç»æ |
| | | |
| | | ## åç»ä¼å建议 |
| | | |
| | | 1. **çæ§æ¥å¿**ï¼è§å¯æ¯å¦è¿æå
¶ä»å¹¶ååºæ¯å¯¼è´ç类似é®é¢ |
| | | 2. **äºå¡ä¼å**ï¼å¯¹äºæ¹å¤çæä½ï¼èèæ·»å éå½çäºå¡éç¦»çº§å« |
| | | 3. **éæºå¶**ï¼å¦æé®é¢ä»ç¶åå¨ï¼å¯ä»¥èèä½¿ç¨æ°æ®åºè¡éæåå¸å¼é |
| | | |
| | | ## ç¸å
³æä»¶ |
| | | |
| | | - `ruoyi-system/src/main/resources/mapper/system/VehicleGpsSegmentMileageMapper.xml` |
| | | - `ruoyi-system/src/main/java/com/ruoyi/system/service/impl/VehicleGpsSegmentMileageServiceImpl.java` |
| | | - `ruoyi-system/src/main/java/com/ruoyi/system/domain/VehicleGpsSegmentMileage.java` |
| | | - `sql/vehicle_gps_segment_mileage.sql` |
| | | |
| | | --- |
| | | |
| | | **ä¿®å¤æ¥æ**: 2026-03-16 |
| | | **ä¿®å¤äººå**: AI Assistant |
| | | **é®é¢ç±»å**: å¹¶åæ°æ®ä¸è´æ§ |
| | |
| | | <view |
| | | class="task-status" |
| | | :class=" |
| | | task.taskStatus === 'PENDING' |
| | | task.taskStatus === TaskStatus.PENDING |
| | | ? 'status-pending' |
| | | : task.taskStatus === 'DEPARTING' |
| | | : task.taskStatus === TaskStatus.NOT_CONFIRMED |
| | | ? 'status-not-confirmed' |
| | | : task.taskStatus === TaskStatus.NOT_DEPARTED |
| | | ? 'status-not-departed' |
| | | : task.taskStatus === TaskStatus.PARTIALLY_CONFIRMED |
| | | ? 'status-partially-confirmed' |
| | | : task.taskStatus === TaskStatus.DEPARTING |
| | | ? 'status-departing' |
| | | : task.taskStatus === 'ARRIVED' |
| | | : task.taskStatus === TaskStatus.ARRIVED |
| | | ? 'status-arrived' |
| | | : task.taskStatus === 'RETURNING' |
| | | : task.taskStatus === TaskStatus.RETURNING |
| | | ? 'status-returning' |
| | | : task.taskStatus === 'COMPLETED' |
| | | : task.taskStatus === TaskStatus.COMPLETED |
| | | ? 'status-completed' |
| | | : task.taskStatus === 'CANCELLED' |
| | | : task.taskStatus === TaskStatus.CANCELLED |
| | | ? 'status-cancelled' |
| | | : task.taskStatus === 'IN_PROGRESS' |
| | | : task.taskStatus === TaskStatus.IN_PROGRESS |
| | | ? 'status-in-progress' |
| | | : 'status-default' |
| | | : 'status-pending' |
| | | " |
| | | > |
| | | {{ getStatusText(task.status) }} |
| | | {{ getStatusText(task.taskStatus) }} |
| | | </view> |
| | | </view> |
| | | |
| | |
| | | |
| | | <!-- æä½æé® --> |
| | | <view class="task-actions"> |
| | | <!-- å¾
å¤çç¶æ: æ¾ç¤ºåºåãåæ¶ --> |
| | | <template v-if="task.taskStatus === 'PENDING'"> |
| | | <!-- å¾
å¤çç¶æï¼æ¾ç¤ºåºåãåæ¶ --> |
| | | <template v-if="task.taskStatus === TaskStatus.PENDING || task.taskStatus === TaskStatus.NOT_DEPARTED || task.taskStatus === TaskStatus.NOT_CONFIRMED || task.taskStatus === TaskStatus.PARTIALLY_CONFIRMED"> |
| | | <button |
| | | class="action-btn primary" |
| | | @click="handleTaskAction(task, 'depart')" |
| | |
| | | </button> |
| | | </template> |
| | | |
| | | <!-- åºåä¸ç¶æ: æ¾ç¤ºå·²å°è¾¾ã强å¶ç»æ --> |
| | | <template v-else-if="task.taskStatus === 'DEPARTING'"> |
| | | <!-- åºåä¸ç¶æï¼æ¾ç¤ºå·²å°è¾¾ã强å¶ç»æ --> |
| | | <template v-else-if="task.taskStatus === TaskStatus.DEPARTING"> |
| | | <button |
| | | class="action-btn primary" |
| | | @click="handleTaskAction(task, 'arrive')" |
| | |
| | | </button> |
| | | </template> |
| | | |
| | | <!-- å·²å°è¾¾ç¶æ: æ¾ç¤ºå·²è¿ç¨ --> |
| | | <template v-else-if="task.taskStatus === 'ARRIVED'"> |
| | | <!-- å·²å°è¾¾ç¶æï¼æ¾ç¤ºå·²è¿ç¨ --> |
| | | <template v-else-if="task.taskStatus === TaskStatus.ARRIVED"> |
| | | <button |
| | | class="action-btn primary" |
| | | @click="handleTaskAction(task, 'return')" |
| | |
| | | </button> |
| | | </template> |
| | | |
| | | <!-- è¿ç¨ä¸ç¶æ: æ¾ç¤ºå·²å®æ --> |
| | | <template v-else-if="task.taskStatus === 'RETURNING'"> |
| | | <!-- è¿ç¨ä¸ç¶æï¼æ¾ç¤ºå·²å®æ --> |
| | | <template v-else-if="task.taskStatus === TaskStatus.RETURNING"> |
| | | <button |
| | | class="action-btn primary" |
| | | @click="handleTaskAction(task, 'complete')" |
| | |
| | | import { formatDateTime } from "@/utils/common"; |
| | | import subscribeManager from "@/utils/subscribe"; |
| | | import { checkTaskCanDepart } from "@/utils/taskValidator"; |
| | | import { getStatusText as getTaskStatusText, TaskStatus } from "@/utils/TaskUtil"; |
| | | |
| | | // ä»»å¡ç±»åæ å°ï¼ä¸´æ¶å®ä¹ï¼é¿å
导å
¥é®é¢ï¼ |
| | | const TASK_TYPE_MAP = { |
| | | MAINTENANCE: "ç»´ä¿®ä¿å
»", |
| | | FUEL: "å æ²¹", |
| | | OTHER: "å
¶ä»", |
| | | EMERGENCY_TRANSFER: "转è¿ä»»å¡", |
| | | WELFARE: "ç¦ç¥è½¦", |
| | | maintenance: "ç»´ä¿®ä¿å
»", |
| | | refuel: "å æ²¹", |
| | | inspection: "å·¡æ£", |
| | | emergency: "转è¿ä»»å¡", |
| | | welfare: "ç¦ç¥è½¦" |
| | | }; |
| | | |
| | | // ä»»å¡ç¶ææ å°ï¼ä¸´æ¶å®ä¹ï¼é¿å
导å
¥é®é¢ï¼ |
| | | const TASK_STATUS_MAP = { |
| | | PENDING: "å¾
å¤ç", |
| | | NOT_CONFIRMED: "å®å
¨æªç¡®è®¤", |
| | | NOT_DEPARTED: "å¾
åºå", |
| | | PARTIALLY_CONFIRMED: "é¨å确认", |
| | | DEPARTING: "åºåä¸", |
| | | ARRIVED: "å·²å°è¾¾", |
| | | RETURNING: "è¿ç¨ä¸", |
| | | COMPLETED: "已宿", |
| | | CANCELLED: "已忶", |
| | | IN_PROGRESS: "ä»»å¡ä¸" |
| | | }; |
| | | |
| | | export default { |
| | | data() { |
| | | return { |
| | | TaskStatus, // æ´é² TaskStatus ç»æ¨¡æ¿ä½¿ç¨ |
| | | // ç¨æ·ç»å®ç车è¾ä¿¡æ¯ |
| | | boundVehicle: "", |
| | | boundVehicleId: null, |
| | |
| | | runningTasks() { |
| | | return this.displayedTaskList.filter((task) => { |
| | | // å
å«å¾
å¤çãåºåä¸ãå·²å°è¾¾ãè¿ç¨ä¸çæææªå®æçç¶æ |
| | | return [ |
| | | "PENDING", |
| | | "DEPARTING", |
| | | "ARRIVED", |
| | | "RETURNING", |
| | | "IN_PROGRESS", |
| | | ].includes(task.taskStatus); |
| | | const activeStatuses = [ |
| | | TaskStatus.NOT_CONFIRMED, |
| | | TaskStatus.NOT_DEPARTED, |
| | | TaskStatus.PARTIALLY_CONFIRMED, |
| | | TaskStatus.PENDING, |
| | | TaskStatus.DEPARTING, |
| | | TaskStatus.ARRIVED, |
| | | TaskStatus.RETURNING, |
| | | TaskStatus.IN_PROGRESS, |
| | | ]; |
| | | return activeStatuses.includes(task.taskStatus); |
| | | }); |
| | | }, |
| | | |
| | |
| | | convertStatus(dbStatus) { |
| | | const statusMap = { |
| | | PENDING: "pending", |
| | | NOT_CONFIRMED: "pending", |
| | | NOT_DEPARTED: "pending", |
| | | PARTIALLY_CONFIRMED: "pending", |
| | | |
| | | DEPARTING: "processing", |
| | | ARRIVED: "processing", |
| | | RETURNING: "processing", |
| | |
| | | this.$modal |
| | | .confirm("ç¡®å®è¦åºååï¼") |
| | | .then(() => { |
| | | this.updateTaskStatus(task.taskId, "DEPARTING", "ä»»å¡å·²åºå"); |
| | | this.updateTaskStatus(task.taskId, TaskStatus.DEPARTING, "ä»»å¡å·²åºå"); |
| | | }) |
| | | .catch(() => {}); |
| | | } catch (error) { |
| | |
| | | this.$modal |
| | | .confirm("æ£æ¥ä»»å¡ç¶æå¤±è´¥ï¼æ¯å¦ç»§ç»åºåï¼") |
| | | .then(() => { |
| | | this.updateTaskStatus(task.taskId, "DEPARTING", "ä»»å¡å·²åºå"); |
| | | this.updateTaskStatus(task.taskId, TaskStatus.DEPARTING, "ä»»å¡å·²åºå"); |
| | | }) |
| | | .catch(() => {}); |
| | | } |
| | |
| | | this.$modal |
| | | .confirm("确认已å°è¾¾ç®çå°ï¼") |
| | | .then(() => { |
| | | this.updateTaskStatus(task.taskId, "ARRIVED", "å·²å°è¾¾ç®çå°"); |
| | | this.updateTaskStatus(task.taskId, TaskStatus.ARRIVED, "å·²å°è¾¾ç®çå°"); |
| | | }) |
| | | .catch(() => {}); |
| | | break; |
| | |
| | | this.$modal |
| | | .confirm("ç¡®å®è¦å¼ºå¶ç»ææ¤ä»»å¡åï¼") |
| | | .then(() => { |
| | | this.updateTaskStatus(task.taskId, "CANCELLED", "ä»»å¡å·²å¼ºå¶ç»æ"); |
| | | this.updateTaskStatus(task.taskId, TaskStatus.CANCELLED, "ä»»å¡å·²å¼ºå¶ç»æ"); |
| | | }) |
| | | .catch(() => {}); |
| | | break; |
| | |
| | | this.$modal |
| | | .confirm("确认å¼å§è¿ç¨ï¼") |
| | | .then(() => { |
| | | this.updateTaskStatus(task.taskId, "RETURNING", "å·²å¼å§è¿ç¨"); |
| | | this.updateTaskStatus(task.taskId, TaskStatus.RETURNING, "å·²å¼å§è¿ç¨"); |
| | | }) |
| | | .catch(() => {}); |
| | | break; |
| | |
| | | case "complete": |
| | | // 已宿 -> ç¶æåä¸ºå·²å®æ |
| | | // éè¦æ£æ¥æ¯å¦ä¸ä¼ äºç¥æ
åæä¹¦ |
| | | this.checkConsentAttachmentAndThen(task.taskId, "COMPLETED", "ä»»å¡å·²å®æ"); |
| | | this.checkConsentAttachmentAndThen(task.taskId, TaskStatus.COMPLETED, "ä»»å¡å·²å®æ"); |
| | | break; |
| | | } |
| | | }, |
| | |
| | | getLocationAndUpdateStatus(taskId, status, remark, cancelReason) { |
| | | const that = this; |
| | | |
| | | // 使ç¨uni.getLocationè·åGPSä½ç½® |
| | | // ä½¿ç¨ uni.getLocation è·å GPS ä½ç½® |
| | | uni.getLocation({ |
| | | type: "gcj02", |
| | | geocode: true, |
| | | altitude: true, |
| | | success: function (res) { |
| | | console.log("GPSå®ä½æå:", res); |
| | | |
| | | console.log("GPS å®ä½æå:", res); |
| | | |
| | | const statusData = { |
| | | taskStatus: status, |
| | | remark: remark, |
| | |
| | | }); |
| | | }, |
| | | |
| | | // è·åç¶ææ ·å¼ç±» |
| | | 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"; |
| | | }, |
| | | |
| | | getStatusText(status) { |
| | | // æ¯ææ°æ§ä¸¤ç§ç¶ææ ¼å¼ |
| | | const statusMap = { |
| | | // æ°æ ¼å¼ï¼æ°æ®åºç¶æï¼ |
| | | PENDING: "å¾
å¤ç", |
| | | DEPARTING: "åºåä¸", |
| | | ARRIVED: "å·²å°è¾¾", |
| | | RETURNING: "è¿ç¨ä¸", |
| | | COMPLETED: "已宿", |
| | | CANCELLED: "已忶", |
| | | IN_PROGRESS: "å¤çä¸", |
| | | // æ§æ ¼å¼ï¼UIç¶æï¼ |
| | | pending: "å¾
å¤ç", |
| | | processing: "å¤çä¸", |
| | | completed: "已宿", |
| | | }; |
| | | return statusMap[status] || "æªç¥"; |
| | | }, |
| | | |
| | | // è·åä»»å¡ç±»åææ¬ |
| | | getTaskTypeText(type) { |
| | | const typeMap = { |
| | | // æ°æ ¼å¼ï¼æ°æ®åºç±»åï¼ |
| | | MAINTENANCE: "ç»´ä¿®ä¿å
»", |
| | | FUEL: "å æ²¹", |
| | | OTHER: "å
¶ä»", |
| | | EMERGENCY_TRANSFER: "转è¿ä»»å¡", |
| | | WELFARE: "ç¦ç¥è½¦", |
| | | // æ§æ ¼å¼ï¼UIç±»åï¼ |
| | | maintenance: "ç»´ä¿®ä¿å
»", |
| | | refuel: "å æ²¹", |
| | | inspection: "å·¡æ£", |
| | | emergency: "转è¿ä»»å¡", |
| | | welfare: "ç¦ç¥è½¦", |
| | | }; |
| | | return typeMap[type] || "æªç¥ç±»å"; |
| | | return TASK_TYPE_MAP[type] || "æªç¥ç±»å"; |
| | | }, |
| | | |
| | | // è·åä»»å¡ç¶æææ¬ |
| | | getStatusText(status) { |
| | | return TASK_STATUS_MAP[status] || "æªç¥"; |
| | | }, |
| | | |
| | | clickConfirmsubscribeTaskNotify() { |
| | |
| | | background-color: #fff3e0; |
| | | color: #ff9500; |
| | | } |
| | | &.status-not-confirmed { |
| | | background-color: #fff3e0; |
| | | color: #ff9500; |
| | | } |
| | | &.status-not-departed { |
| | | background-color: #fff3e0; |
| | | color: #ff9500; |
| | | } |
| | | &.status-partially-confirmed { |
| | | background-color: #fff3e0; |
| | | color: #ff9500; |
| | | } |
| | | |
| | | // åºåä¸ - èè² |
| | | &.status-departing { |
| | |
| | | ? 'status-cancelled' |
| | | : task.taskStatus === 'IN_PROGRESS' |
| | | ? 'status-in-progress' |
| | | : 'status-default' |
| | | : 'status-pending' |
| | | " |
| | | > |
| | | {{ getStatusText(task.taskStatus) }} |
| | |
| | | <!-- æä½æé® --> |
| | | <view class="task-actions"> |
| | | <!-- å¾
å¤çç¶æ: æ¾ç¤ºåºåãåæ¶ --> |
| | | <template v-if="task.taskStatus === 'PENDING'"> |
| | | <template v-if="task.taskStatus === 'PENDING' |
| | | || task.taskStatus === 'NOT_DEPARTED' |
| | | || task.taskStatus === 'NOT_CONFIRMED' |
| | | || task.taskStatus === 'PARTIALLY_CONFIRMED'"> |
| | | <button |
| | | class="action-btn primary" |
| | | @click="handleTaskAction(task, 'depart')" |
| | |
| | | import { mapState } from "vuex"; |
| | | import { formatDateTime } from "@/utils/common"; |
| | | import { checkTaskCanDepart } from "@/utils/taskValidator"; |
| | | import { getStatusText as getTaskStatusText, getTaskStatusOptions, getTaskTypeText as getTaskTypeTextUtil } from "@/utils/TaskUtil"; |
| | | |
| | | // ä»»å¡ç±»åæ å°ï¼ä¸´æ¶å®ä¹ï¼é¿å
导å
¥é®é¢ï¼ |
| | | const TASK_TYPE_MAP = { |
| | | MAINTENANCE: "ç»´ä¿®ä¿å
»", |
| | | FUEL: "å æ²¹", |
| | | OTHER: "å
¶ä»", |
| | | EMERGENCY_TRANSFER: "转è¿ä»»å¡", |
| | | WELFARE: "ç¦ç¥è½¦", |
| | | maintenance: "ç»´ä¿®ä¿å
»", |
| | | refuel: "å æ²¹", |
| | | inspection: "å·¡æ£", |
| | | emergency: "转è¿ä»»å¡", |
| | | welfare: "ç¦ç¥è½¦" |
| | | }; |
| | | |
| | | // ä»»å¡ç¶ææ å°ï¼ä¸´æ¶å®ä¹ï¼é¿å
导å
¥é®é¢ï¼ |
| | | const TASK_STATUS_MAP = { |
| | | PENDING: "å¾
å¤ç", |
| | | NOT_CONFIRMED: "å®å
¨æªç¡®è®¤", |
| | | NOT_DEPARTED: "å¾
åºå", |
| | | PARTIALLY_CONFIRMED: "é¨å确认", |
| | | DEPARTING: "åºåä¸", |
| | | ARRIVED: "å·²å°è¾¾", |
| | | RETURNING: "è¿ç¨ä¸", |
| | | COMPLETED: "已宿", |
| | | CANCELLED: "已忶", |
| | | IN_PROGRESS: "ä»»å¡ä¸" |
| | | }; |
| | | |
| | | export default { |
| | | components: { |
| | |
| | | vehicle: "", |
| | | taskNo: "", |
| | | }, |
| | | statusOptions: ["å
¨é¨ç¶æ", "å¾
å¤ç", "å¤çä¸", "已宿", "已忶"], |
| | | statusValues: ["", "pending", "processing", "completed", "cancelled"], |
| | | statusOptions: ["å
¨é¨ç¶æ", ...getTaskStatusOptions().map(opt => opt.label)], |
| | | statusValues: ["", ...getTaskStatusOptions().map(opt => opt.value)], |
| | | selectedStatus: "", |
| | | selectedStatusText: "", |
| | | startDate: "", |
| | |
| | | queryParams.taskStatus = "PENDING"; |
| | | } else if (this.currentFilter === "processing") { |
| | | queryParams.taskStatusList = [ |
| | | "NOT_CONFIRMED", |
| | | "NOT_DEPARTED", |
| | | "PARTIALLY_CONFIRMED", |
| | | "DEPARTING", |
| | | "ARRIVED", |
| | | "RETURNING", |
| | |
| | | const statusMap = { |
| | | pending: "PENDING", |
| | | processing: [ |
| | | "NOT_CONFIRMED", |
| | | "NOT_DEPARTED", |
| | | "PARTIALLY_CONFIRMED", |
| | | "DEPARTING", |
| | | "ARRIVED", |
| | | "RETURNING", |
| | |
| | | queryParams.taskStatus = "PENDING"; |
| | | } else if (this.currentFilter === "processing") { |
| | | queryParams.taskStatusList = [ |
| | | "NOT_CONFIRMED", |
| | | "NOT_DEPARTED", |
| | | "PARTIALLY_CONFIRMED", |
| | | "DEPARTING", |
| | | "ARRIVED", |
| | | "RETURNING", |
| | |
| | | }); |
| | | }, |
| | | |
| | | getStatusText(status) { |
| | | const statusMap = { |
| | | PENDING: "å¾
å¤ç", |
| | | DEPARTING: "åºåä¸", |
| | | ARRIVED: "å·²å°è¾¾", |
| | | RETURNING: "è¿ç¨ä¸", |
| | | COMPLETED: "已宿", |
| | | CANCELLED: "已忶", |
| | | IN_PROGRESS: "å¤çä¸", // å
¼å®¹æ§æ°æ® |
| | | }; |
| | | return statusMap[status] || "æªç¥"; |
| | | }, |
| | | |
| | | // ä½¿ç¨ TaskUtil ä¸ç getStatusText æ¹æ³ |
| | | // getStatusText å·²å¨ utils/TaskUtil.js ä¸å®ä¹ |
| | | |
| | | // è·åç¶ææ ·å¼ç±» |
| | | getStatusClass(status) { |
| | | const statusClassMap = { |
| | |
| | | }; |
| | | return statusClassMap[status] || "status-default"; |
| | | }, |
| | | |
| | | // ä½¿ç¨ TaskUtil ä¸ç getTaskTypeText æ¹æ³ |
| | | // getTaskTypeText å·²å¨ utils/TaskUtil.js ä¸å®ä¹ |
| | | |
| | | // è·åä»»å¡ç±»åææ¬ |
| | | getTaskTypeText(type) { |
| | | const typeMap = { |
| | | MAINTENANCE: "ç»´ä¿®ä¿å
»", |
| | | FUEL: "å æ²¹", |
| | | OTHER: "å
¶ä»", |
| | | EMERGENCY_TRANSFER: "转è¿ä»»å¡", |
| | | WELFARE: "ç¦ç¥è½¦", |
| | | }; |
| | | return typeMap[type] || "æªç¥ç±»å"; |
| | | return TASK_TYPE_MAP[type] || "æªç¥ç±»å"; |
| | | }, |
| | | |
| | | // è·åä»»å¡ç¶æææ¬ |
| | | getStatusText(status) { |
| | | return TASK_STATUS_MAP[status] || "æªç¥"; |
| | | }, |
| | | }, |
| | | }; |
| | |
| | | </view> |
| | | <!-- å½åç»å½äººæ¯è¯¥æ§è¡äººä¸æªå°±ç»ªæ¶æ¾ç¤ºå°±ç»ªæé® --> |
| | | <view |
| | | v-if="showAssigneeReadyFeature() && isAssigneeSelf(assignee) && !isAssigneeReady(assignee) && taskDetail.taskStatus === 'PENDING'" |
| | | v-if="showAssigneeReadyFeature() && isAssigneeSelf(assignee) && !isAssigneeReady(assignee) && taskDetail.taskStatus === TaskStatus.PENDING" |
| | | class="assignee-ready-btn" |
| | | :data-user-id="assignee.userId || assignee.oaUserId" |
| | | :data-user-name="assignee.userName" |
| | |
| | | </view> |
| | | |
| | | <!-- åæ¶ä¿¡æ¯ï¼ä»
å¨ä»»å¡å·²åæ¶ä¸æåæ¶åå æ¶æ¾ç¤ºï¼ --> |
| | | <view class="detail-section" v-if="taskDetail.taskStatus === 'CANCELLED' && taskDetail.emergencyInfo && taskDetail.emergencyInfo.cancelReason"> |
| | | <view class="detail-section" v-if="taskDetail.taskStatus === TaskStatus.CANCELLED && taskDetail.emergencyInfo && taskDetail.emergencyInfo.cancelReason"> |
| | | <view class="section-title">åæ¶ä¿¡æ¯</view> |
| | | <view class="info-item"> |
| | | <view class="label">åæ¶åå </view> |
| | |
| | | |
| | | <!-- æä½æé®åºå --> |
| | | <view class="action-buttons" v-if="taskDetail"> |
| | | <!-- å¾
å¤çç¶æ: æ¾ç¤ºåºåãåæ¶ã强å¶å®æ --> |
| | | <template v-if="taskDetail.taskStatus === 'PENDING' "> |
| | | <!-- å¾
å¤çç¶æï¼æ¾ç¤ºåºåãåæ¶ã强å¶å®æ --> |
| | | <template v-if="taskDetail.taskStatus === TaskStatus.PENDING |
| | | || taskDetail.taskStatus === TaskStatus.NOT_DEPARTED |
| | | || taskDetail.taskStatus === TaskStatus.NOT_CONFIRMED |
| | | || taskDetail.taskStatus === TaskStatus.PARTIALLY_CONFIRMED"> |
| | | <button |
| | | v-if="canOperateTask()" |
| | | class="action-btn primary" |
| | |
| | | 强å¶å®æ |
| | | </button> |
| | | </template> |
| | | |
| | | <!-- åºåä¸ç¶æ: æ¾ç¤ºå·²å°è¾¾ã强å¶ç»æã强å¶å®æ --> |
| | | <template v-else-if="taskDetail.taskStatus === 'DEPARTING'"> |
| | | |
| | | <!-- åºåä¸ç¶æï¼æ¾ç¤ºå·²å°è¾¾ã强å¶ç»æã强å¶å®æ --> |
| | | <template v-else-if="taskDetail.taskStatus === TaskStatus.DEPARTING"> |
| | | <template v-if="canOperateTask()"> |
| | | <button |
| | | class="action-btn primary" |
| | |
| | | </template> |
| | | </template> |
| | | |
| | | <!-- å·²å°è¾¾ç¶æ: æ¾ç¤ºå·²è¿ç¨ --> |
| | | <template v-else-if="taskDetail.taskStatus === 'ARRIVED'"> |
| | | <!-- å·²å°è¾¾ç¶æï¼æ¾ç¤ºå·²è¿ç¨ --> |
| | | <template v-else-if="taskDetail.taskStatus === TaskStatus.ARRIVED"> |
| | | <template v-if="canOperateTask()"> |
| | | <button |
| | | class="action-btn primary" |
| | |
| | | </template> |
| | | </template> |
| | | |
| | | <!-- è¿ç¨ä¸ç¶æ: æ¾ç¤ºå·²å®æ --> |
| | | <template v-else-if="taskDetail.taskStatus === 'RETURNING'"> |
| | | <!-- è¿ç¨ä¸ç¶æï¼æ¾ç¤ºå·²å®æ --> |
| | | <template v-else-if="taskDetail.taskStatus === TaskStatus.RETURNING"> |
| | | <template v-if="canOperateTask()"> |
| | | <button |
| | | class="action-btn primary" |
| | |
| | | </template> |
| | | </template> |
| | | |
| | | <!-- å¤çä¸ç¶æ: æ¾ç¤ºå¼ºå¶å®æãåæ¶ --> |
| | | <template v-else-if="taskDetail.taskStatus === 'IN_PROGRESS'"> |
| | | <!-- å¤çä¸ç¶æï¼æ¾ç¤ºå¼ºå¶å®æãåæ¶ --> |
| | | <template v-else-if="taskDetail.taskStatus === TaskStatus.IN_PROGRESS"> |
| | | <template v-if="canOperateTask()"> |
| | | <button |
| | | class="action-btn primary" |
| | |
| | | import { checkTaskInvoice } from '@/api/invoice' |
| | | import { formatDateTime } from '@/utils/common' |
| | | import { validateTaskForDepart, validateTaskForSettlement, getTaskVehicleId, checkTaskCanDepart } from '@/utils/taskValidator' |
| | | import { getStatusText as getTaskStatusText, getTaskTypeText as getTaskTypeTextUtil, TaskStatus } from '@/utils/TaskUtil' |
| | | import AttachmentUpload from './components/AttachmentUpload.vue' |
| | | import config from '@/config' |
| | | |
| | |
| | | }, |
| | | data() { |
| | | return { |
| | | TaskStatus, // æ´é² TaskStatus ç»æ¨¡æ¿ä½¿ç¨ |
| | | taskDetail: null, |
| | | taskId: null, |
| | | paymentInfo: null, // æ¯ä»ä¿¡æ¯ |
| | |
| | | return '' |
| | | } |
| | | const status = this.taskDetail.taskStatus |
| | | if (status === 'PENDING') return 'pending' |
| | | if (['DEPARTING', 'ARRIVED', 'RETURNING', 'IN_PROGRESS'].includes(status)) return 'in_progress' |
| | | if (status === 'COMPLETED') return 'completed' |
| | | if (status === 'CANCELLED') return 'cancelled' |
| | | if (status === TaskStatus.PENDING || status === TaskStatus.NOT_CONFIRMED || status === TaskStatus.NOT_DEPARTED || status === TaskStatus.PARTIALLY_CONFIRMED) return 'pending' |
| | | if ([TaskStatus.DEPARTING, TaskStatus.ARRIVED, TaskStatus.RETURNING, TaskStatus.IN_PROGRESS].includes(status)) return 'in_progress' |
| | | if (status === TaskStatus.COMPLETED) return 'completed' |
| | | if (status === TaskStatus.CANCELLED) return 'cancelled' |
| | | return '' |
| | | }, |
| | | // æ¾ç¤ºè®¡åå¼å§æ¶é´ |
| | |
| | | |
| | | // è·åç¶æææ¬ |
| | | getStatusText(status) { |
| | | const statusMap = { |
| | | 'PENDING': 'å¾
å¤ç', |
| | | 'DEPARTING': 'åºåä¸', |
| | | 'ARRIVED': 'å·²å°è¾¾', |
| | | 'RETURNING': 'è¿ç¨ä¸', |
| | | 'COMPLETED': '已宿', |
| | | 'CANCELLED': '已忶', |
| | | 'IN_PROGRESS': 'å¤çä¸' // å
¼å®¹æ§æ°æ® |
| | | } |
| | | return statusMap[status] || 'æªç¥' |
| | | return getTaskStatusText(status) |
| | | }, |
| | | |
| | | // è·åä»»å¡ç±»åææ¬ |
| | | getTaskTypeText(type) { |
| | | const typeMap = { |
| | | 'MAINTENANCE': 'ç»´ä¿®ä¿å
»', |
| | | 'FUEL': 'å æ²¹', |
| | | 'OTHER': 'å
¶ä»', |
| | | 'EMERGENCY_TRANSFER': '转è¿ä»»å¡', |
| | | 'WELFARE': 'ç¦ç¥è½¦' |
| | | } |
| | | return typeMap[type] || 'æªç¥ç±»å' |
| | | return getTaskTypeTextUtil(type) |
| | | }, |
| | | |
| | | // è·åç¨æ·ç±»åæ ç¾ |
| New file |
| | |
| | | /** |
| | | * ä»»å¡å·¥å
·ç±» |
| | | * æä¾ä»»å¡ç¸å
³çéç¨å·¥å
·æ¹æ³ |
| | | */ |
| | | |
| | | /** |
| | | * ä»»å¡ç¶ææä¸¾ |
| | | */ |
| | | export const TaskStatus = { |
| | | /** å¾
å¤ç */ |
| | | PENDING: 'PENDING', |
| | | |
| | | /** é¨å确认 */ |
| | | PARTIALLY_CONFIRMED: 'PARTIALLY_CONFIRMED', |
| | | |
| | | /** å®å
¨æªç¡®è®¤ */ |
| | | NOT_CONFIRMED: 'NOT_CONFIRMED', |
| | | |
| | | /** æªåºè½¦ */ |
| | | NOT_DEPARTED: 'NOT_DEPARTED', |
| | | |
| | | /** åºåä¸ */ |
| | | DEPARTING: 'DEPARTING', |
| | | |
| | | /** å·²å°è¾¾ */ |
| | | ARRIVED: 'ARRIVED', |
| | | |
| | | /** è¿ç¨ä¸ */ |
| | | RETURNING: 'RETURNING', |
| | | |
| | | /** 已宿 */ |
| | | COMPLETED: 'COMPLETED', |
| | | |
| | | /** 已忶 */ |
| | | CANCELLED: 'CANCELLED', |
| | | |
| | | /** ä»»å¡ä¸ (å
¼å®¹æ§æ°æ®) */ |
| | | IN_PROGRESS: 'IN_PROGRESS' |
| | | }; |
| | | |
| | | /** |
| | | * ä»»å¡ç¶æææ¬æ å° |
| | | */ |
| | | const STATUS_TEXT_MAP = { |
| | | [TaskStatus.PENDING]: 'å¾
å¤ç', |
| | | [TaskStatus.PARTIALLY_CONFIRMED]: 'é¨å确认', |
| | | [TaskStatus.NOT_CONFIRMED]: 'å®å
¨æªç¡®è®¤', |
| | | [TaskStatus.NOT_DEPARTED]: 'æªåºè½¦', |
| | | [TaskStatus.DEPARTING]: 'åºåä¸', |
| | | [TaskStatus.ARRIVED]: 'å·²å°è¾¾', |
| | | [TaskStatus.RETURNING]: 'è¿ç¨ä¸', |
| | | [TaskStatus.COMPLETED]: '已宿', |
| | | [TaskStatus.CANCELLED]: '已忶', |
| | | [TaskStatus.IN_PROGRESS]: 'ä»»å¡ä¸' // å
¼å®¹æ§æ°æ® |
| | | }; |
| | | |
| | | /** |
| | | * è·åä»»å¡ç¶æææ¬ |
| | | * @param {string} status - ä»»å¡ç¶æä»£ç |
| | | * @returns {string} ä»»å¡ç¶æææ¬ |
| | | */ |
| | | export function getStatusText(status) { |
| | | return STATUS_TEXT_MAP[status] || 'æªç¥'; |
| | | } |
| | | |
| | | /** |
| | | * è·åææä»»å¡ç¶æé项ï¼éç¨äºéæ©å¨ï¼ |
| | | * @returns {Array} ç¶æé项æ°ç» |
| | | */ |
| | | export function getTaskStatusOptions() { |
| | | return Object.keys(TaskStatus).map(key => ({ |
| | | value: TaskStatus[key], |
| | | label: STATUS_TEXT_MAP[TaskStatus[key]] |
| | | })); |
| | | } |
| | | |
| | | /** |
| | | * 夿任塿¯å¦å·²å®æ |
| | | * @param {string} status - ä»»å¡ç¶æä»£ç |
| | | * @returns {boolean} æ¯å¦å·²å®æ |
| | | */ |
| | | export function isTaskCompleted(status) { |
| | | return status === TaskStatus.COMPLETED; |
| | | } |
| | | |
| | | /** |
| | | * 夿任塿¯å¦å·²åæ¶ |
| | | * @param {string} status - ä»»å¡ç¶æä»£ç |
| | | * @returns {boolean} æ¯å¦å·²åæ¶ |
| | | */ |
| | | export function isTaskCancelled(status) { |
| | | return status === TaskStatus.CANCELLED; |
| | | } |
| | | |
| | | /** |
| | | * 夿任塿¯å¦å¤äºè¿è¡ä¸ç¶æï¼å
æ¬å¾
å¤çãåºåä¸ãå·²å°è¾¾ãè¿ç¨ä¸çï¼ |
| | | * @param {string} status - ä»»å¡ç¶æä»£ç |
| | | * @returns {boolean} æ¯å¦è¿è¡ä¸ |
| | | */ |
| | | export function isTaskInProgress(status) { |
| | | const activeStatuses = [ |
| | | TaskStatus.PENDING, |
| | | TaskStatus.PARTIALLY_CONFIRMED, |
| | | TaskStatus.NOT_CONFIRMED, |
| | | TaskStatus.NOT_DEPARTED, |
| | | TaskStatus.DEPARTING, |
| | | TaskStatus.ARRIVED, |
| | | TaskStatus.RETURNING, |
| | | TaskStatus.IN_PROGRESS |
| | | ]; |
| | | return activeStatuses.includes(status); |
| | | } |
| | | |
| | | /** |
| | | * ä»»å¡ç±»åæä¸¾ |
| | | */ |
| | | export const TaskType = { |
| | | /** ç»´ä¿®ä¿å
» */ |
| | | MAINTENANCE: 'MAINTENANCE', |
| | | |
| | | /** å æ²¹ */ |
| | | FUEL: 'FUEL', |
| | | |
| | | /** å
¶ä» */ |
| | | OTHER: 'OTHER', |
| | | |
| | | /** 转è¿ä»»å¡ */ |
| | | EMERGENCY_TRANSFER: 'EMERGENCY_TRANSFER', |
| | | |
| | | /** ç¦ç¥è½¦ */ |
| | | WELFARE: 'WELFARE', |
| | | |
| | | // æ§æ ¼å¼ï¼å
¼å®¹ç¨ï¼ |
| | | /** ç»´ä¿®ä¿å
»ï¼æ§ï¼ */ |
| | | maintenance: 'maintenance', |
| | | |
| | | /** å æ²¹ï¼æ§ï¼ */ |
| | | refuel: 'refuel', |
| | | |
| | | /** å·¡æ£ï¼æ§ï¼ */ |
| | | inspection: 'inspection', |
| | | |
| | | /** 转è¿ä»»å¡ï¼æ§ï¼ */ |
| | | emergency: 'emergency', |
| | | |
| | | /** ç¦ç¥è½¦ï¼æ§ï¼ */ |
| | | welfare: 'welfare' |
| | | }; |
| | | |
| | | /** |
| | | * ä»»å¡ç±»åææ¬æ å° |
| | | */ |
| | | const TYPE_TEXT_MAP = { |
| | | // æ°æ ¼å¼ï¼æ°æ®åºç±»åï¼ |
| | | [TaskType.MAINTENANCE]: 'ç»´ä¿®ä¿å
»', |
| | | [TaskType.FUEL]: 'å æ²¹', |
| | | [TaskType.OTHER]: 'å
¶ä»', |
| | | [TaskType.EMERGENCY_TRANSFER]: '转è¿ä»»å¡', |
| | | [TaskType.WELFARE]: 'ç¦ç¥è½¦', |
| | | // æ§æ ¼å¼ï¼UI ç±»åï¼ |
| | | [TaskType.maintenance]: 'ç»´ä¿®ä¿å
»', |
| | | [TaskType.refuel]: 'å æ²¹', |
| | | [TaskType.inspection]: 'å·¡æ£', |
| | | [TaskType.emergency]: '转è¿ä»»å¡', |
| | | [TaskType.welfare]: 'ç¦ç¥è½¦' |
| | | }; |
| | | |
| | | /** |
| | | * è·åä»»å¡ç±»åææ¬ |
| | | * @param {string} type - ä»»å¡ç±»å代ç |
| | | * @returns {string} ä»»å¡ç±»åææ¬ |
| | | */ |
| | | export function getTaskTypeText(type) { |
| | | return TYPE_TEXT_MAP[type] || 'æªç¥ç±»å'; |
| | | } |
| | | |
| | | /** |
| | | * è·åææä»»å¡ç±»åé项ï¼éç¨äºéæ©å¨ï¼ |
| | | * @returns {Array} ç±»åé项æ°ç» |
| | | */ |
| | | export function getTaskTypeOptions() { |
| | | return Object.keys(TaskType).map(key => ({ |
| | | value: TaskType[key], |
| | | label: TYPE_TEXT_MAP[TaskType[key]] |
| | | })); |
| | | } |
| | | |
| | | // é»è®¤å¯¼åº |
| | | const TaskUtil = { |
| | | TaskStatus, |
| | | TaskType, |
| | | getStatusText, |
| | | getTaskStatusOptions, |
| | | getTaskTypeText, |
| | | getTaskTypeOptions, |
| | | isTaskCompleted, |
| | | isTaskCancelled, |
| | | isTaskInProgress |
| | | }; |
| | | |
| | | export default TaskUtil; |
| New file |
| | |
| | | åå
¬å¸è¦é
ç½®åºåå°å |
| | | æ´æ°è¡¨æ°æ® |
| | | select ServiceBranch,ServiceAddress,ServiceAddress_lat,ServiceAddress_lng,UnitName,UnitShort,ServiceMinPrice,ServiceUnitPrice,ServiceLong from IntroducerUnitData where UnitState>0 and ServiceAddress_lat is not null and ServiceAddress_lng is not null and ServiceBranch='SZ' |
| | | |
| | | |
| | | update IntroducerUnitData set ServiceAddress='æ·±å³å¸é¾å²åºå¹³æ¹å¤§è¡159å·åé£å±
', ServiceAddress_lat=22.684596,ServiceAddress_lng=114.155988 where UnitID=80 |
| | |
| | | basename: i18n/messages |
| | | profiles: |
| | | # ç¯å¢ dev|test|prod |
| | | active: prod |
| | | active: dev |
| | | # æä»¶ä¸ä¼ |
| | | servlet: |
| | | multipart: |
| | |
| | | public class CleanVehicleGpsTask { |
| | | private static final Logger log = LoggerFactory.getLogger(CleanVehicleGpsTask.class); |
| | | |
| | | /** æ¯æ¹å 餿°é */ |
| | | private static final int BATCH_SIZE = 10000; |
| | | /** æ¯æ¹é´éæ¶é´ï¼æ¯«ç§ï¼ï¼é¿å
è¿ç»å é¤å¯¹æ°æ®åºååè¿å¤§ */ |
| | | private static final long BATCH_INTERVAL_MS = 500; |
| | | |
| | | @Autowired |
| | | private IVehicleGpsService vehicleGpsService; |
| | | |
| | | /** |
| | | * æ¸
ç车è¾GPSå岿°æ® |
| | | * æ¸
ç车è¾GPSå岿°æ®ï¼ä¿çæè¿2个æï¼åæ¹å é¤ï¼ |
| | | */ |
| | | public void cleanVehicleGpsData() { |
| | | try { |
| | | // log.info("å¼å§æ¸
ç车è¾GPSå岿°æ®"); |
| | | int count = vehicleGpsService.deleteVehicleGpsBeforeDate(); |
| | | // log.info("æ¸
ç车è¾GPSå岿°æ®å®æï¼å
±æ¸
ç{}æ¡è®°å½", count); |
| | | log.info("å¼å§æ¸
ç车è¾GPSå岿°æ®ï¼ä¿çæè¿2个æï¼æ¯æ¹ {} æ¡ï¼", BATCH_SIZE); |
| | | int totalCount = 0; |
| | | int batchCount; |
| | | int round = 0; |
| | | do { |
| | | batchCount = vehicleGpsService.deleteVehicleGpsBeforeDateBatch(BATCH_SIZE); |
| | | totalCount += batchCount; |
| | | round++; |
| | | log.info("第 {} æ¹æ¸
çå®æï¼æ¬æ¹å é¤ {} æ¡ï¼å·²å é¤å计 {} æ¡", round, batchCount, totalCount); |
| | | if (batchCount == BATCH_SIZE) { |
| | | // è¿ææ°æ®ï¼ç¨ä½ä¼ç åç»§ç» |
| | | Thread.sleep(BATCH_INTERVAL_MS); |
| | | } |
| | | } while (batchCount == BATCH_SIZE); |
| | | |
| | | log.info("æ¸
ç车è¾GPSå岿°æ®å®æï¼å
± {} æ¹ï¼å é¤ {} æ¡è®°å½", round, totalCount); |
| | | |
| | | if (totalCount > 0) { |
| | | log.info("å¼å§æ§è¡ OPTIMIZE TABLEï¼åæ¶ç£ç空é´ï¼æ¤æä½èæ¶è¾é¿ï¼è¯·å¿ä¸æï¼"); |
| | | vehicleGpsService.optimizeVehicleGpsTable(); |
| | | log.info("OPTIMIZE TABLE æ§è¡å®æ"); |
| | | } else { |
| | | log.info("æ¬æ¬¡æ 坿¸
ççè®°å½ï¼è·³è¿ OPTIMIZE TABLE"); |
| | | } |
| | | } catch (Exception e) { |
| | | log.error("æ¸
ç车è¾GPSå岿°æ®å¼å¸¸", e); |
| | | } |
| | |
| | | |
| | | /** å¾
å¤ç */ |
| | | PENDING("PENDING", "å¾
å¤ç"), |
| | | |
| | | |
| | | /** |
| | | * é¨å确认 |
| | | */ |
| | | PARTIALLY_CONFIRMED("PARTIALLY_CONFIRMED", "é¨å确认"), |
| | | /** |
| | | * å®å
¨æªç¡®è®¤ |
| | | */ |
| | | NOT_CONFIRMED("NOT_CONFIRMED", "å®å
¨æªç¡®è®¤"), |
| | | /** |
| | | * æªåºè½¦ |
| | | */ |
| | | NOT_DEPARTED("NOT_DEPARTED", "æªåºè½¦"), |
| | | |
| | | /** åºåä¸ */ |
| | | DEPARTING("DEPARTING", "åºåä¸"), |
| | | |
| | |
| | | public int deleteVehicleGpsBeforeDate(); |
| | | |
| | | /** |
| | | * åæ¹å 餿宿¥æä¹åç车è¾GPSæ°æ®ï¼å¸¦ LIMITï¼ |
| | | * |
| | | * @param batchSize æ¯æ¹å 餿¡æ° |
| | | * @return æ¬æ¹å é¤çè®°å½æ° |
| | | */ |
| | | public int deleteVehicleGpsBeforeDateBatch(@Param("batchSize") int batchSize); |
| | | |
| | | /** |
| | | * ä¼å表ï¼åæ¶DELETEåçç£çç¢çç©ºé´ |
| | | */ |
| | | public void optimizeVehicleGpsTable(); |
| | | |
| | | /** |
| | | * æ¥è¯¢è½¦è¾å¨æå®æ¶é´èå´å
çGPSæ°æ®ï¼æééæ¶é´æåºï¼ |
| | | * |
| | | * @param vehicleId 车è¾ID |
| | |
| | | * @return å é¤çè®°å½æ° |
| | | */ |
| | | public int deleteVehicleGpsBeforeDate(); |
| | | |
| | | /** |
| | | * åæ¹å 餿宿¥æä¹åç车è¾GPSæ°æ® |
| | | * |
| | | * @param batchSize æ¯æ¹å 餿¡æ° |
| | | * @return æ¬æ¹å é¤çè®°å½æ° |
| | | */ |
| | | public int deleteVehicleGpsBeforeDateBatch(int batchSize); |
| | | |
| | | /** |
| | | * ä¼å表ï¼åæ¶DELETEåçç£çç¢çç©ºé´ |
| | | */ |
| | | public void optimizeVehicleGpsTable(); |
| | | } |
| | |
| | | public int deleteVehicleGpsBeforeDate() { |
| | | return vehicleGpsMapper.deleteVehicleGpsBeforeDate(); |
| | | } |
| | | |
| | | /** |
| | | * åæ¹å 餿宿¥æä¹åç车è¾GPSæ°æ® |
| | | */ |
| | | @Override |
| | | public int deleteVehicleGpsBeforeDateBatch(int batchSize) { |
| | | return vehicleGpsMapper.deleteVehicleGpsBeforeDateBatch(batchSize); |
| | | } |
| | | |
| | | /** |
| | | * ä¼å表ï¼åæ¶DELETEåçç£çç¢çç©ºé´ |
| | | */ |
| | | @Override |
| | | public void optimizeVehicleGpsTable() { |
| | | vehicleGpsMapper.optimizeVehicleGpsTable(); |
| | | } |
| | | } |
| | |
| | | |
| | | switch (legacyStatusCode) { |
| | | case 0: // æ°è°åº¦åï¼æªä¸åï¼ |
| | | case 1: // å®å
¨æªç¡®è®¤ |
| | | case 2: // é¨å已确认 |
| | | case 3: // æªåºè½¦ |
| | | return TaskStatus.PENDING; |
| | | |
| | | case 1: // å®å
¨æªç¡®è®¤ |
| | | return TaskStatus.NOT_CONFIRMED; |
| | | case 2: // é¨å已确认 |
| | | return TaskStatus.PARTIALLY_CONFIRMED; |
| | | case 3: // æªåºè½¦ |
| | | return TaskStatus.NOT_DEPARTED; |
| | | case 4: // å·²åºè½¦ï¼å»æ¥æ£è
éä¸ï¼ |
| | | return TaskStatus.DEPARTING; |
| | | |
| | |
| | | log.warn("æ°ç³»ç»ä»»å¡ç¶æä¸ºç©º"); |
| | | return null; |
| | | } |
| | | |
| | | /** |
| | | * 0 0 - æ°è°åº¦åï¼æªä¸åï¼ |
| | | * 1 1 - å®å
¨æªç¡®è®¤ |
| | | * 2 2 - é¨å已确认 |
| | | * 3 æªåºè½¦ |
| | | * 4 3 - å·²åºè½¦ï¼å»æ¥æ£è
éä¸ï¼ |
| | | * 5 å·²åºè½¦ï¼çå¾
æ£è
ï¼ |
| | | * 6 4 - å·²åºè½¦ï¼æå¡ä¸ï¼ |
| | | * 7 5 - å·²éè¾¾ï¼åç¨ä¸ï¼ |
| | | * 8 å·²è¿å |
| | | * 9 è·ç©ºåï¼å·²è¿å |
| | | * 10 åæ¶ |
| | | * 11 å·²æäº¤ï¼çå¾
å®¡æ ¸ |
| | | * 12 å®¡æ ¸å®æ |
| | | * 13 å®¡æ ¸ä¸éè¿ |
| | | * 14 å·²é©»ç¹ |
| | | */ |
| | | switch (taskStatus) { |
| | | case PENDING: |
| | | case NOT_DEPARTED: |
| | | return 3; // æªåºè½¦ |
| | | |
| | | case NOT_CONFIRMED: |
| | | return 1; // å®å
¨æªç¡®è®¤ |
| | | case PARTIALLY_CONFIRMED: |
| | | return 2; // é¨å确认 |
| | | case PENDING: |
| | | return 0; // æªåºè½¦ |
| | | case DEPARTING: |
| | | return 4; // å·²åºè½¦ï¼å»æ¥æ£è
éä¸ï¼ |
| | | |
| | |
| | | </select> |
| | | |
| | | <delete id="deleteVehicleGpsBeforeDate"> |
| | | delete g from tb_vehicle_gps g |
| | | where g.collect_time < ( |
| | | select date_sub(max(collect_time), interval 2 day) |
| | | from tb_vehicle_gps g2 |
| | | where g2.vehicle_id = g.vehicle_id |
| | | ) |
| | | delete from tb_vehicle_gps |
| | | where collect_time < DATE_SUB(NOW(), INTERVAL 2 MONTH) |
| | | </delete> |
| | | |
| | | <delete id="deleteVehicleGpsBeforeDateBatch"> |
| | | delete from tb_vehicle_gps |
| | | where collect_time < DATE_SUB(NOW(), INTERVAL 2 MONTH) |
| | | LIMIT #{batchSize} |
| | | </delete> |
| | | |
| | | <update id="optimizeVehicleGpsTable"> |
| | | OPTIMIZE TABLE tb_vehicle_gps |
| | | </update> |
| | | |
| | | <select id="selectGpsDataByTimeRange" resultMap="VehicleGpsResult"> |
| | | select gps_id, vehicle_id, device_id, longitude, latitude, altitude, speed, direction, |
| | | collect_time, device_report_time, platform_process_time, create_time |
| | |
| | | WHERE task_id = #{taskId} |
| | | </select> |
| | | |
| | | <!-- æå
¥ææ´æ°å段éç¨è®°å½ï¼é¿å
é夿å
¥ï¼ --> |
| | | <insert id="insertVehicleGpsSegmentMileage" parameterType="VehicleGpsSegmentMileage"> |
| | | INSERT INTO tb_vehicle_gps_segment_mileage |
| | | <trim prefix="(" suffix=")" suffixOverrides=","> |
| | |
| | | <if test="taskCode != null">#{taskCode},</if> |
| | | <if test="calculateMethod != null">#{calculateMethod},</if> |
| | | </trim> |
| | | ON DUPLICATE KEY UPDATE |
| | | vehicle_no = VALUES(vehicle_no), |
| | | segment_end_time = VALUES(segment_end_time), |
| | | start_longitude = VALUES(start_longitude), |
| | | start_latitude = VALUES(start_latitude), |
| | | end_longitude = VALUES(end_longitude), |
| | | end_latitude = VALUES(end_latitude), |
| | | segment_distance = VALUES(segment_distance), |
| | | gps_point_count = VALUES(gps_point_count), |
| | | gps_ids = VALUES(gps_ids), |
| | | task_id = VALUES(task_id), |
| | | task_code = VALUES(task_code), |
| | | calculate_method = VALUES(calculate_method), |
| | | update_time = NOW() |
| | | </insert> |
| | | |
| | | <update id="updateVehicleGpsSegmentMileage" parameterType="VehicleGpsSegmentMileage"> |
| | |
| | | -- ---------------------------- |
| | | -- æ¸
ç车è¾GPSå岿°æ®å®æ¶ä»»å¡é
ç½® |
| | | -- 说æï¼æ¯å¤©åæ¨2ç¹æ§è¡ï¼ä¿çæè¿2ä¸ªææ°æ®ï¼è¶
åºé¨ååæ¹å é¤ï¼æ¯æ¹1䏿¡ï¼ |
| | | -- ---------------------------- |
| | | |
| | | -- 妿已åå¨ååä»»å¡å
å é¤ï¼é¿å
é夿å
¥ |
| | | DELETE FROM sys_job |
| | | WHERE job_name = 'æ¸
ç车è¾GPSå岿°æ®' AND job_group = 'DEFAULT'; |
| | | |
| | | INSERT INTO sys_job ( |
| | | job_name, |
| | | job_group, |
| | | invoke_target, |
| | | cron_expression, |
| | | misfire_policy, |
| | | concurrent, |
| | | status, |
| | | create_by, |
| | | create_time, |
| | | update_by, |
| | | update_time, |
| | | job_name, |
| | | job_group, |
| | | invoke_target, |
| | | cron_expression, |
| | | misfire_policy, |
| | | concurrent, |
| | | status, |
| | | create_by, |
| | | create_time, |
| | | update_by, |
| | | update_time, |
| | | remark |
| | | ) VALUES ( |
| | | 'æ¸
ç车è¾GPSå岿°æ®', |
| | | 'DEFAULT', |
| | | 'cleanVehicleGpsTask.cleanVehicleGpsData()', |
| | | '0 0 1 * * ?', |
| | | '1', |
| | | '0 0 2 * * ?', |
| | | '3', |
| | | '1', |
| | | '0', |
| | | 'admin', |
| | | sysdate(), |
| | | 'admin', |
| | | sysdate(), |
| | | 'æ¯å¤©åæ¨1ç¹æ¸
ç车è¾GPSå岿°æ®ï¼åªä¿çæ¯å°è½¦æå2å¤©çæ°æ®' |
| | | 'æ¯å¤©åæ¨2ç¹æ§è¡ï¼åæ¹å é¤tb_vehicle_gpsä¸è¶
è¿2个æçå岿°æ®ï¼æ¯æ¹1䏿¡ï¼æ¹æ¬¡é´é500msï¼ï¼å é¤å®æåæ§è¡OPTIMIZE TABLEåæ¶ç£ç空é´' |
| | | ); |