| | |
| | | <!-- æä½æé®åºå --> |
| | | <view class="action-buttons" v-if="taskDetail"> |
| | | <!-- å¾
å¤çç¶æ: æ¾ç¤ºåºåãåæ¶ã强å¶å®æ --> |
| | | <template v-if="taskDetail.taskStatus === 'PENDING'"> |
| | | <template v-if="taskDetail.taskStatus === 'PENDING' "> |
| | | <button |
| | | v-if="isCurrentUserAssignee()" |
| | | v-if="canOperateTask()" |
| | | class="action-btn primary" |
| | | @click="handleDepartAction()" |
| | | > |
| | |
| | | åæ¶ |
| | | </button> |
| | | <button |
| | | v-if="isCurrentUserAssignee() && showForceCompleteFeature()" |
| | | v-if="canOperateTask() && showForceCompleteFeature()" |
| | | class="action-btn force-complete" |
| | | @click="showForceCompleteTimeDialog()" |
| | | > |
| | |
| | | |
| | | <!-- åºåä¸ç¶æ: æ¾ç¤ºå·²å°è¾¾ã强å¶ç»æ --> |
| | | <template v-else-if="taskDetail.taskStatus === 'DEPARTING'"> |
| | | <template v-if="isCurrentUserAssignee()"> |
| | | <template v-if="canOperateTask()"> |
| | | <button |
| | | class="action-btn primary" |
| | | @click="handleTaskAction('arrive')" |
| | |
| | | |
| | | <!-- å·²å°è¾¾ç¶æ: æ¾ç¤ºå·²è¿ç¨ --> |
| | | <template v-else-if="taskDetail.taskStatus === 'ARRIVED'"> |
| | | <template v-if="isCurrentUserAssignee()"> |
| | | <template v-if="canOperateTask()"> |
| | | <button |
| | | class="action-btn primary" |
| | | @click="handleTaskAction('return')" |
| | |
| | | |
| | | <!-- è¿ç¨ä¸ç¶æ: æ¾ç¤ºå·²å®æ --> |
| | | <template v-else-if="taskDetail.taskStatus === 'RETURNING'"> |
| | | <template v-if="isCurrentUserAssignee()"> |
| | | <template v-if="canOperateTask()"> |
| | | <button |
| | | class="action-btn primary" |
| | | @click="handleTaskAction('complete')" |
| | | > |
| | | 已宿 |
| | | </button> |
| | | </template> |
| | | </template> |
| | | |
| | | <!-- å¤çä¸ç¶æ: æ¾ç¤ºå¼ºå¶å®æãåæ¶ --> |
| | | <template v-else-if="taskDetail.taskStatus === 'IN_PROGRESS'"> |
| | | <template v-if="canOperateTask()"> |
| | | <button |
| | | class="action-btn primary" |
| | | @click="handleTaskAction('arrive')" |
| | | > |
| | | å·²å°è¾¾ |
| | | </button> |
| | | <button |
| | | v-if="showForceCompleteFeature()" |
| | | class="action-btn force-complete" |
| | | @click="showForceCompleteTimeDialog()" |
| | | > |
| | | 强å¶å®æ |
| | | </button> |
| | | </template> |
| | | </template> |
| | | |
| | |
| | | const list = (this.taskDetail && Array.isArray(this.taskDetail.assignees)) ? this.taskDetail.assignees : [] |
| | | return list.some(a => a && (a.userId === userId || a.oaUserId === userId)) |
| | | }, |
| | | |
| | | // æ¯å¦å½åç¨æ·å¯ä»¥æä½ä»»å¡ï¼æ§è¡äººæç®¡çåï¼ |
| | | canOperateTask() { |
| | | // æ£æ¥æ¯å¦æ¯ç®¡çåï¼canViewAllConsult === '1'ï¼ |
| | | |
| | | const canViewAllConsult = this.$store && this.$store.state && this.$store.state.user && this.$store.state.user.canViewAllConsult |
| | | console.log("å½åç¨æ·æ¯å¦æ¯ç®¡çå:", canViewAllConsult) |
| | | if (canViewAllConsult === '1') { |
| | | return true |
| | | } |
| | | // æ£æ¥æ¯å¦æ¯ä»»å¡æ§è¡äºº |
| | | return this.isCurrentUserAssignee() |
| | | }, |
| | | |
| | | // æ¯å¦å¤äººæ§è¡ |
| | | isMultipleAssignees() { |
| | |
| | | branchCompanyId: storage.get(constant.branchCompanyId), |
| | | branchCompanyName: storage.get(constant.branchCompanyName), |
| | | oaUserId: storage.get(constant.oaUserId), |
| | | canCreateTask: storage.get(constant.canCreateTask) |
| | | canCreateTask: storage.get(constant.canCreateTask), |
| | | canViewAllConsult: storage.get(constant.canViewAllConsult) |
| | | }, |
| | | |
| | | mutations: { |
| | |
| | | SET_CAN_CREATE_TASK: (state, canCreateTask) => { |
| | | state.canCreateTask = canCreateTask |
| | | storage.set(constant.canCreateTask, canCreateTask) |
| | | }, |
| | | SET_CAN_VIEW_ALL_CONSULT: (state, canViewAllConsult) => { |
| | | state.canViewAllConsult = canViewAllConsult |
| | | storage.set(constant.canViewAllConsult, canViewAllConsult) |
| | | } |
| | | }, |
| | | |
| | |
| | | commit('SET_BRANCH_COMPANY_NAME', res.branchCompanyName) |
| | | commit('SET_OA_USER_ID', res.oaUserId) |
| | | commit('SET_CAN_CREATE_TASK', res.canCreateTask) |
| | | commit('SET_CAN_VIEW_ALL_CONSULT', res.canViewAllConsult) |
| | | resolve(res) |
| | | }).catch(error => { |
| | | reject(error) |
| | |
| | | branchCompanyId: 'vuex_branchCompanyId', |
| | | branchCompanyName: 'vuex_branchCompanyName', |
| | | oaUserId: 'vuex_oaUserId', |
| | | canCreateTask: 'vuex_canCreateTask' |
| | | canCreateTask: 'vuex_canCreateTask', |
| | | canViewAllConsult: 'vuex_canViewAllConsult' |
| | | } |
| | | |
| | | export default constant |
| | |
| | | " | | \\ / \\ / \n" + |
| | | " ''-' `'-' `-..-' "); |
| | | } |
| | | |
| | | |
| | | } |
| | |
| | | ajax.put("branchCompanyName", branchCompanyName); |
| | | ajax.put("branchCompanies", branchCompanies); |
| | | ajax.put("oaUserId", user.getOaUserId()); |
| | | ajax.put("canViewAllConsult", user.getCanViewAllConsult()); |
| | | ajax.put("canCreateTask", user.getCanCreateTask()); |
| | | return ajax; |
| | | } |
| | |
| | | # åå§è¿æ¥æ° |
| | | initialSize: 5 |
| | | # æå°è¿æ¥æ± æ°é |
| | | minIdle: 10 |
| | | minIdle: 5 |
| | | # æå¤§è¿æ¥æ± æ°é |
| | | maxActive: 20 |
| | | # é
ç½®è·åè¿æ¥çå¾
è¶
æ¶çæ¶é´ |
| | |
| | | # é
ç½®ä¸ä¸ªè¿æ¥å¨æ± 䏿å°çåçæ¶é´ï¼å使¯æ¯«ç§ |
| | | minEvictableIdleTimeMillis: 300000 |
| | | # é
ç½®ä¸ä¸ªè¿æ¥å¨æ± 䏿大çåçæ¶é´ï¼å使¯æ¯«ç§ |
| | | maxEvictableIdleTimeMillis: 900000 |
| | | maxEvictableIdleTimeMillis: 600000 |
| | | # é
ç½®æ£æµè¿æ¥æ¯å¦ææ |
| | | validationQuery: SELECT 1 |
| | | testWhileIdle: true |
| | | testOnBorrow: false |
| | | testOnReturn: false |
| | | # æ¯å¦ç¼åpreparedStatementï¼ä¹å°±æ¯PSCacheï¼æåæ§è½ä½å¢å å
åï¼Oracle建议å¼å¯ï¼MySQL建议å
³éï¼ |
| | | poolPreparedStatements: false |
| | | # æ¯ä¸ªè¿æ¥çPSCache大å°ï¼MySQL建议å
³éPSCacheï¼è®¾ä¸º-1ï¼ |
| | | maxPoolPreparedStatementPerConnectionSize: -1 |
| | | # é
置移é¤åºå¼è¿æ¥ï¼é¿æ¶é´æªå½è¿çè¿æ¥ï¼ |
| | | removeAbandoned: true |
| | | # è¿æ¥è¢«å ç¨è¶
è¿æ¤æ¶é´ï¼ç§ï¼è§ä¸ºåºå¼ |
| | | removeAbandonedTimeout: 1800 |
| | | # æ¯å¦è®°å½åºå¼è¿æ¥çå æ ä¿¡æ¯ |
| | | logAbandoned: true |
| | | webStatFilter: |
| | | enabled: true |
| | | statViewServlet: |
| | |
| | | basename: i18n/messages |
| | | profiles: |
| | | # ç¯å¢ dev|test|prod |
| | | active: dev |
| | | active: prod |
| | | # æä»¶ä¸ä¼ |
| | | servlet: |
| | | multipart: |
| | |
| | | lettuce: |
| | | pool: |
| | | # è¿æ¥æ± ä¸çæå°ç©ºé²è¿æ¥ |
| | | min-idle: 0 |
| | | min-idle: 2 |
| | | # è¿æ¥æ± ä¸çæå¤§ç©ºé²è¿æ¥ |
| | | max-idle: 8 |
| | | # è¿æ¥æ± çæå¤§æ°æ®åºè¿æ¥æ° |
| | | max-active: 8 |
| | | max-active: 20 |
| | | # #è¿æ¥æ± æå¤§é»å¡çå¾
æ¶é´ï¼ä½¿ç¨è´å¼è¡¨ç¤ºæ²¡æéå¶ï¼ |
| | | max-wait: -1ms |
| | | shutdown-timeout: 100ms |
| | | |
| | | |
| | | # tokené
ç½® |
| | |
| | | package com.ruoyi.common.utils.http; |
| | | |
| | | import java.io.BufferedReader; |
| | | import java.io.IOException; |
| | | import java.io.InputStream; |
| | | import java.io.InputStreamReader; |
| | | import java.io.*; |
| | | import java.net.URLEncoder; |
| | | import java.nio.charset.StandardCharsets; |
| | | import javax.servlet.ServletRequest; |
| | | import org.apache.commons.lang3.exception.ExceptionUtils; |
| | | import org.slf4j.Logger; |
| | | import org.slf4j.LoggerFactory; |
| | | |
| | | import static java.util.Collections.replaceAll; |
| | | |
| | | /** |
| | | * éç¨httpå·¥å
·å°è£
|
| | |
| | | { |
| | | private static final Logger LOGGER = LoggerFactory.getLogger(HttpHelper.class); |
| | | |
| | | /** |
| | | * urlç¼ç + ç©ºæ ¼æ¿æ¢ä¸º %20 %3A æ¿æ¢ä¸º : ä¸»è¦æ¯å¤çæ¶é´è½¬æ¢é®é¢ |
| | | * @param str |
| | | * @param charset |
| | | * @return |
| | | * @throws UnsupportedEncodingException |
| | | */ |
| | | public static String UrlEncode(String str, String charset) throws UnsupportedEncodingException { |
| | | return URLEncoder.encode(str, charset).replaceAll("\\+", "%20").replaceAll("%3A", ":"); |
| | | } |
| | | |
| | | public static String getBodyString(ServletRequest request) |
| | | { |
| | | StringBuilder sb = new StringBuilder(); |
| | |
| | | * 忥GPSä½ç½® |
| | | */ |
| | | public void syncGpsData() { |
| | | List<VehicleInfo> vehicleList = null; |
| | | try { |
| | | // log.info("å¼å§åæ¥GPSæ°æ®..."); |
| | | |
| | | // 1. è·åææè½¦è¾ä¿¡æ¯ |
| | | List<VehicleInfo> vehicleList = vehicleInfoService.selectVehicleInfoList(new VehicleInfo()); |
| | | vehicleList = vehicleInfoService.selectVehicleInfoList(new VehicleInfo()); |
| | | |
| | | List<String> deviceIds = vehicleList.stream().map(VehicleInfo::getDeviceId).collect(Collectors.toList()); |
| | | if (vehicleList == null || vehicleList.isEmpty()) { |
| | | log.info("æ²¡ææ¾å°è½¦è¾ä¿¡æ¯"); |
| | | return; |
| | | } |
| | | |
| | | List<String> deviceIds = vehicleList.stream() |
| | | .map(VehicleInfo::getDeviceId) |
| | | .filter(id -> id != null && !id.isEmpty()) |
| | | .collect(Collectors.toList()); |
| | | |
| | | if (deviceIds.isEmpty()) { |
| | | log.info("æ²¡æææç设å¤ID"); |
| | | return; |
| | | } |
| | | |
| | | // 2. è·åææè½¦è¾çGPSæåä½ç½® |
| | | GpsLastPositionRequest request = new GpsLastPositionRequest(); |
| | | // request.setDeviceids(deviceIds); |
| | | GpsLastPositionResponse gpsLastPositionResponse = gpsCollectService.getLastPosition(request); |
| | | |
| | | if (gpsLastPositionResponse == null || gpsLastPositionResponse.getRecords() == null) { |
| | | log.warn("GPSæå¡è¿åç©ºæ°æ®"); |
| | | return; |
| | | } |
| | | |
| | | // 3. éå车è¾å表ï¼è·åæ¯ä¸ªè½¦è¾çGPSä½ç½® |
| | | for (VehicleInfo vehicle : vehicleList) { |
| | |
| | | // log.info("GPSæ°æ®åæ¥å®æ"); |
| | | } catch (Exception e) { |
| | | log.error("GPSæ°æ®åæ¥å¤±è´¥: {}", e.getMessage()); |
| | | } finally { |
| | | // æ¾å¼æ¸
空大对象å¼ç¨ï¼å¸®å©GC |
| | | vehicleList = null; |
| | | } |
| | | } |
| | | |
| | |
| | | // è¿ç¨ä¸ -> 已宿 |
| | | return newStatus == TaskStatus.COMPLETED; |
| | | case IN_PROGRESS: |
| | | // å
¼å®¹æ§æ°æ®ï¼ä»»å¡ä¸ -> 已宿ã已忶ãå¾
å¤ç |
| | | return newStatus == TaskStatus.COMPLETED || newStatus == TaskStatus.CANCELLED || newStatus == TaskStatus.PENDING; |
| | | // å
¼å®¹æ§æ°æ®ï¼ä»»å¡ä¸ -> 已宿ã已忶ãå¾
å¤çãå·²å°è¾¾ãè¿ç¨ä¸ |
| | | return newStatus == TaskStatus.COMPLETED |
| | | || newStatus == TaskStatus.CANCELLED |
| | | || newStatus == TaskStatus.PENDING |
| | | || newStatus == TaskStatus.ARRIVED |
| | | || newStatus == TaskStatus.RETURNING; |
| | | case COMPLETED: |
| | | case CANCELLED: |
| | | // 已宿ã已忶 -> ä¸å
许任ä½ç¶æåæ´ |
| | |
| | | * @param startDate å¼å§æ¥æ |
| | | * @return 转è¿åæ°æ®å表 |
| | | */ |
| | | List<Map<String, Object>> selectTransferOrders(@Param("startDate") String startDate); |
| | | List<Map<String, Object>> selectTransferOrders(@Param("startDate") String startDate, @Param("endDate") String endDate); |
| | | |
| | | /**ServiceOrdNo |
| | | * æ ¹æ®æå¡åIDåè°åº¦åIDæ¥è¯¢è½¬è¿åæ°æ® |
| | |
| | | * @return ç»æ |
| | | */ |
| | | @Override |
| | | @Transactional |
| | | |
| | | public int submitCustomerEvaluation(CustomerEvaluation customerEvaluation) { |
| | | // è®¡ç®æ»è¯å |
| | | BigDecimal totalScore = calculateTotalScore(customerEvaluation.getEvaluationDetails()); |
| | |
| | | * @return åæ¥ç»æ |
| | | */ |
| | | @Override |
| | | @Transactional |
| | | |
| | | public AjaxResult syncBranchDepartments(List<DepartmentSyncDTO> branchDepts,List<OrderClassDTO> serviceOrderList,List<OrderClassDTO> dispatchOrderList,List<Map<String, Object>> addressList) |
| | | { |
| | | try |
| | |
| | | * @return åæ¥ç»æ |
| | | */ |
| | | @Override |
| | | @Transactional |
| | | |
| | | public AjaxResult syncTransportDepartments(List<DepartmentSyncDTO> transportDepts, List<Map<String, Object>> addressList) |
| | | { |
| | | try |
| | |
| | | return gpsConfigMapper.selectGpsConfigList(gpsConfig); |
| | | } |
| | | |
| | | @Override |
| | | @Transactional |
| | | @Override |
| | | public int insertGpsConfig(SysGpsConfig gpsConfig) { |
| | | gpsConfig.setCreateTime(DateUtils.getNowDate()); |
| | | gpsConfig.setUpdateTime(DateUtils.getNowDate()); |
| | |
| | | } |
| | | |
| | | @Override |
| | | @Transactional |
| | | public int updateGpsConfig(SysGpsConfig gpsConfig) { |
| | | gpsConfig.setUpdateTime(DateUtils.getNowDate()); |
| | | return gpsConfigMapper.updateGpsConfig(gpsConfig); |
| | | } |
| | | |
| | | @Override |
| | | @Transactional |
| | | public int deleteGpsConfigByIds(Long[] configIds) { |
| | | return gpsConfigMapper.deleteGpsConfigByIds(configIds); |
| | | } |
| | | |
| | | @Override |
| | | @Transactional |
| | | public int deleteGpsConfigById(Long configId) { |
| | | return gpsConfigMapper.deleteGpsConfigById(configId); |
| | | } |
| | |
| | | // è®¡ç®æ¥æèå´ |
| | | Date startDate = DateUtils.addDays(new Date(), -daysAgo); |
| | | String startDateStr = DateUtils.parseDateToStr("yyyy-MM-dd", startDate); |
| | | String endDateStr = DateUtils.parseDateToStr("yyyy-MM-dd", new Date()); |
| | | |
| | | // ä»SQL Serveræ¥è¯¢è½¬è¿åæ°æ® |
| | | List<Map<String, Object>> transferOrders = legacyTransferSyncMapper.selectTransferOrders(startDateStr); |
| | | List<Map<String, Object>> transferOrders = legacyTransferSyncMapper.selectTransferOrders(startDateStr, endDateStr); |
| | | |
| | | if (transferOrders == null || transferOrders.isEmpty()) { |
| | | log.info("æªæ¥è¯¢å°{}天åç转è¿åæ°æ®", daysAgo); |
| | |
| | | * @return å建çè®°å½ï¼å¦æå·²åå¨åè¿ånull |
| | | */ |
| | | @Override |
| | | @Transactional |
| | | |
| | | public NotifySendLog tryCreateSendLog(Long taskId, Long userId, String userName, |
| | | String notifyType, String channel) { |
| | | // å
æ£æ¥æ¯å¦å·²åå¨ |
| | |
| | | * @return ç»æ |
| | | */ |
| | | @Override |
| | | @Transactional |
| | | public int updateDictType(SysDictType dict) |
| | | { |
| | | SysDictType oldDict = dictTypeMapper.selectDictTypeById(dict.getDictId()); |
| | |
| | | * @return ç»æ |
| | | */ |
| | | @Override |
| | | @Transactional |
| | | |
| | | public int insertRole(SysRole role) |
| | | { |
| | | // æ°å¢è§è²ä¿¡æ¯ |
| | |
| | | * @return ç»æ |
| | | */ |
| | | @Override |
| | | @Transactional |
| | | |
| | | public int updateRole(SysRole role) |
| | | { |
| | | // ä¿®æ¹è§è²ä¿¡æ¯ |
| | |
| | | * @return ç»æ |
| | | */ |
| | | @Override |
| | | @Transactional |
| | | |
| | | public int authDataScope(SysRole role) |
| | | { |
| | | // ä¿®æ¹è§è²ä¿¡æ¯ |
| | |
| | | * @return ç»æ |
| | | */ |
| | | @Override |
| | | @Transactional |
| | | |
| | | public int deleteRoleById(Long roleId) |
| | | { |
| | | // å é¤è§è²ä¸èåå
³è |
| | |
| | | * @return ç»æ |
| | | */ |
| | | @Override |
| | | @Transactional |
| | | |
| | | public int deleteRoleByIds(Long[] roleIds) |
| | | { |
| | | for (Long roleId : roleIds) |
| | |
| | | private ApplicationEventPublisher eventPublisher; |
| | | |
| | | @Override |
| | | @Transactional |
| | | |
| | | public void saveTaskAssignees(Long taskId, List<TaskCreateVO.AssigneeInfo> assignees, String userName) { |
| | | if (assignees == null || assignees.isEmpty()) { |
| | | return; |
| | |
| | | } |
| | | |
| | | @Override |
| | | @Transactional |
| | | |
| | | public boolean updateTaskAssignees(Long taskId, List<TaskCreateVO.AssigneeInfo> newAssignees, String userName) { |
| | | if (newAssignees == null) { |
| | | return false; |
| | |
| | | } |
| | | |
| | | @Override |
| | | @Transactional |
| | | |
| | | public int deleteAssigneesByTaskId(Long taskId) { |
| | | return sysTaskAssigneeMapper.deleteSysTaskAssigneeByTaskId(taskId); |
| | | } |
| | | |
| | | @Override |
| | | @Transactional |
| | | |
| | | public AjaxResult setAssigneeReady(Long taskId, Long userId) { |
| | | // 1. æ¥è¯¢æ§è¡äººå
³èä¿¡æ¯ |
| | | List<SysTaskAssignee> assignees = sysTaskAssigneeMapper.selectSysTaskAssigneeByTaskId(taskId); |
| | |
| | | } |
| | | |
| | | @Override |
| | | @Transactional |
| | | |
| | | public AjaxResult cancelAssigneeReady(Long taskId, Long userId) { |
| | | // æ¥è¯¢æ§è¡äººå
³èä¿¡æ¯ |
| | | List<SysTaskAssignee> assignees = sysTaskAssigneeMapper.selectSysTaskAssigneeByTaskId(taskId); |
| | |
| | | private ImageUrlConfig imageUrlConfig; |
| | | |
| | | @Override |
| | | @Transactional |
| | | |
| | | public Long uploadAttachment(Long taskId, MultipartFile file, String category) { |
| | | try { |
| | | String fileName = category + "_" + System.currentTimeMillis() + "_" + file.getOriginalFilename(); |
| | |
| | | } |
| | | |
| | | @Override |
| | | @Transactional |
| | | |
| | | public Long uploadAttachmentFromWechat(Long taskId, String accessToken, String mediaId, String category) { |
| | | try { |
| | | String wechatUrl = String.format( |
| | |
| | | } |
| | | |
| | | @Override |
| | | @Transactional |
| | | |
| | | public int deleteAttachment(Long attachmentId) { |
| | | SysTaskAttachment attachment = sysTaskAttachmentMapper.selectSysTaskAttachmentByAttachmentId(attachmentId); |
| | | if (attachment == null) { |
| | |
| | | } |
| | | |
| | | @Override |
| | | @Transactional |
| | | public BigDecimal addAdditionalFee(Long taskId, String feeType, String feeName, |
| | | BigDecimal unitAmount, Integer quantity, String remark) { |
| | | // éªè¯åæ° |
| | |
| | | } |
| | | |
| | | @Override |
| | | @Transactional |
| | | |
| | | public BigDecimal removeAdditionalFee(Long taskId, Long feeId) { |
| | | additionalFeeMapper.deleteById(feeId); |
| | | return calculateAdditionalAmount(taskId); |
| | | } |
| | | |
| | | @Override |
| | | @Transactional |
| | | public TaskPaymentResultVO createPayment(TaskPaymentCreateVO createVO) { |
| | | Long taskId = createVO.getTaskId(); |
| | | String paymentMethod = createVO.getPaymentMethod(); |
| | |
| | | } |
| | | |
| | | @Override |
| | | @Transactional |
| | | |
| | | public boolean handlePaymentCallback(String outTradeNo, String tradeNo, String provider) { |
| | | log.info("æ¶å°æ¯ä»åè°ï¼outTradeNo={}, tradeNo={}, provider={}", outTradeNo, tradeNo, provider); |
| | | |
| | |
| | | * @return ç»æ |
| | | */ |
| | | @Override |
| | | @Transactional |
| | | |
| | | public int deleteSysTaskByTaskIds(Long[] taskIds) { |
| | | int result = 0; |
| | | for (Long taskId : taskIds) { |
| | |
| | | * @return ç»æ |
| | | */ |
| | | @Override |
| | | @Transactional |
| | | |
| | | public int assignTask(Long taskId, Long assigneeId, String remark) { |
| | | SysTask task = sysTaskMapper.selectSysTaskByTaskId(taskId); |
| | | if (task == null) { |
| | |
| | | * @return ç»æ |
| | | */ |
| | | @Override |
| | | @Transactional |
| | | |
| | | public Long uploadAttachment(Long taskId, MultipartFile file, String category) { |
| | | return sysTaskAttachmentService.uploadAttachment(taskId, file, category); |
| | | } |
| | |
| | | * @return è¿åéä»¶ID |
| | | */ |
| | | @Override |
| | | @Transactional |
| | | |
| | | public Long uploadAttachmentFromWechat(Long taskId, String accessToken, String mediaId, String category) { |
| | | return sysTaskAttachmentService.uploadAttachmentFromWechat(taskId, accessToken, mediaId, category); |
| | | } |
| | |
| | | * @return ç»æ |
| | | */ |
| | | @Override |
| | | @Transactional |
| | | |
| | | public int deleteAttachment(Long attachmentId) { |
| | | return sysTaskAttachmentService.deleteAttachment(attachmentId); |
| | | } |
| | |
| | | * @return ç»æ |
| | | */ |
| | | @Override |
| | | @Transactional |
| | | |
| | | public int assignVehicleToTask(Long taskId, Long vehicleId, String remark,Long userId,String userName) { |
| | | int result = sysTaskVehicleService.assignVehicleToTask(taskId, vehicleId, remark, userId, userName); |
| | | |
| | |
| | | * @return ç»æ |
| | | */ |
| | | @Override |
| | | @Transactional |
| | | |
| | | public int unassignVehicleFromTask(Long taskId, Long vehicleId) { |
| | | int result = sysTaskVehicleService.unassignVehicleFromTask(taskId, vehicleId); |
| | | |
| | |
| | | * @return ç»æ |
| | | */ |
| | | @Override |
| | | @Transactional |
| | | |
| | | public int assignMultipleVehiclesToTask(Long taskId, List<Long> vehicleIds, String remark,Long userId,String userName) { |
| | | int result = sysTaskVehicleService.assignMultipleVehiclesToTask(taskId, vehicleIds, remark, userId, userName); |
| | | |
| | |
| | | * @return ç»æ |
| | | */ |
| | | @Override |
| | | @Transactional |
| | | |
| | | public AjaxResult setAssigneeReady(Long taskId, Long userId) { |
| | | return sysTaskAssigneeService.setAssigneeReady(taskId, userId); |
| | | } |
| | |
| | | * @return ç»æ |
| | | */ |
| | | @Override |
| | | @Transactional |
| | | |
| | | public AjaxResult cancelAssigneeReady(Long taskId, Long userId) { |
| | | return sysTaskAssigneeService.cancelAssigneeReady(taskId, userId); |
| | | } |
| | |
| | | } |
| | | |
| | | @Override |
| | | @Transactional |
| | | |
| | | public void saveTaskVehicles(Long taskId, List<Long> vehicleIds, String userName) { |
| | | saveTaskVehicles(taskId, vehicleIds, userName, |
| | | DateUtils.getNowDate(), DateUtils.getNowDate(), DateUtils.getNowDate()); |
| | | } |
| | | |
| | | @Override |
| | | @Transactional |
| | | |
| | | public void saveTaskVehicles(Long taskId, List<Long> vehicleIds, String userName, |
| | | Date assignTime, Date createTime, Date updateTime) { |
| | | if (vehicleIds == null || vehicleIds.isEmpty()) { |
| | |
| | | } |
| | | |
| | | @Override |
| | | @Transactional |
| | | |
| | | public boolean updateTaskVehicles(Long taskId, List<Long> newVehicleIds, String userName) { |
| | | if (newVehicleIds == null || newVehicleIds.isEmpty()) { |
| | | return false; |
| | |
| | | } |
| | | |
| | | @Override |
| | | @Transactional |
| | | |
| | | public int assignVehicleToTask(Long taskId, Long vehicleId, String remark, Long userId, String userName) { |
| | | // æ£æ¥æ¯å¦å·²ç»åé
|
| | | int exists = sysTaskVehicleMapper.checkTaskVehicleExists(taskId, vehicleId); |
| | |
| | | } |
| | | |
| | | @Override |
| | | @Transactional |
| | | |
| | | public int unassignVehicleFromTask(Long taskId, Long vehicleId) { |
| | | return sysTaskVehicleMapper.deleteSysTaskVehicleByTaskIdAndVehicleId(taskId, vehicleId); |
| | | } |
| | | |
| | | @Override |
| | | @Transactional |
| | | |
| | | public int assignMultipleVehiclesToTask(Long taskId, List<Long> vehicleIds, String remark, |
| | | Long userId, String userName) { |
| | | List<SysTaskVehicle> taskVehicles = new ArrayList<>(); |
| | |
| | | * @return ç»æ |
| | | */ |
| | | @Override |
| | | @Transactional |
| | | |
| | | public int insertUser(SysUser user) |
| | | { |
| | | // æ°å¢ç¨æ·ä¿¡æ¯ |
| | |
| | | * @return ç»æ |
| | | */ |
| | | @Override |
| | | @Transactional |
| | | |
| | | public int updateUser(SysUser user) |
| | | { |
| | | Long userId = user.getUserId(); |
| | |
| | | * @param roleIds è§è²ç» |
| | | */ |
| | | @Override |
| | | @Transactional |
| | | |
| | | public void insertUserAuth(Long userId, Long[] roleIds) |
| | | { |
| | | userRoleMapper.deleteUserRoleByUserId(userId); |
| | |
| | | * @return ç»æ |
| | | */ |
| | | @Override |
| | | @Transactional |
| | | |
| | | public int deleteUserById(Long userId) |
| | | { |
| | | // å é¤ç¨æ·ä¸è§è²å
³è |
| | |
| | | * @return ç»æ |
| | | */ |
| | | @Override |
| | | @Transactional |
| | | |
| | | public int deleteUserByIds(Long[] userIds) |
| | | { |
| | | for (Long userId : userIds) |
| | |
| | | |
| | | try { |
| | | int totalSuccessCount = 0; |
| | | int pageSize = 200; // æ¯é¡µ200æ¡ |
| | | int pageSize = 10; // æ¯é¡µ10æ¡ |
| | | int offset = 0; |
| | | |
| | | while (true) { |
| | |
| | | |
| | | try { |
| | | int totalSuccessCount = 0; |
| | | int pageSize = 10; // æ¯é¡µ200æ¡ |
| | | int pageSize = 10; // æ¯é¡µ10æ¡ |
| | | int offset = 0; |
| | | |
| | | while (true) { |
| | |
| | | import com.ruoyi.common.core.domain.entity.SysDept; |
| | | import com.ruoyi.common.core.domain.entity.SysUser; |
| | | import com.ruoyi.common.utils.StringUtils; |
| | | import com.ruoyi.common.utils.http.HttpHelper; |
| | | import com.ruoyi.system.domain.SysTask; |
| | | import com.ruoyi.system.domain.SysTaskEmergency; |
| | | import com.ruoyi.system.service.ISysDeptService; |
| | |
| | | } |
| | | postData.append(URLEncoder.encode(entry.getKey(), legacySystemConfig.getCharset())); |
| | | postData.append("="); |
| | | postData.append(URLEncoder.encode(entry.getValue().toString(), legacySystemConfig.getCharset())); |
| | | postData.append(HttpHelper.UrlEncode(entry.getValue().toString(), legacySystemConfig.getCharset())); |
| | | } |
| | | |
| | | // log.info("åéPOST请æ±å°æ§ç³»ç»ï¼URL: {}, åæ°: {}", urlString, postData.toString()); |
| | |
| | | * @return åæ¥ç»æ |
| | | */ |
| | | @Override |
| | | @Transactional |
| | | |
| | | public AjaxResult syncOaUsers(List<UserSyncDTO> oaUsers) |
| | | { |
| | | try |
| | |
| | | |
| | | import java.math.BigDecimal; |
| | | import java.math.RoundingMode; |
| | | import java.time.format.DateTimeFormatter; |
| | | import java.util.*; |
| | | |
| | | import com.ruoyi.common.utils.DateUtils; |
| | |
| | | |
| | | /** 天å°å¾æ¹éè·¯å¾è§åAPI */ |
| | | private static final String TIANDITU_ROUTE_API = "http://api.tianditu.gov.cn/drive"; |
| | | |
| | | /** 线ç¨å®å
¨çæ¥ææ ¼å¼åå¨ */ |
| | | private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); |
| | | |
| | | /** åæ¹å¤ç大å°ï¼é¿å
䏿¬¡æ§å è½½è¿å¤æ°æ® */ |
| | | private static final int BATCH_SIZE = 10; |
| | | |
| | | @Autowired |
| | | private VehicleGpsSegmentMileageMapper segmentMileageMapper; |
| | |
| | | return 0; |
| | | } |
| | | |
| | | logger.info("æ¾å° {} è¾æ´»è·è½¦è¾ï¼å¼å§éè¾è®¡ç®...", vehicleIds.size()); |
| | | logger.info("æ¾å° {} è¾æ´»è·è½¦è¾ï¼å¼å§åæ¹éè¾è®¡ç®...", vehicleIds.size()); |
| | | |
| | | int successCount = 0; |
| | | int failedCount = 0; |
| | | |
| | | // éè¾è®¡ç®ï¼å
å«é误å¤çåéè¯æºå¶ |
| | | for (int i = 0; i < vehicleIds.size(); i++) { |
| | | Long vehicleId = vehicleIds.get(i); |
| | | try { |
| | | // logger.info("æ£å¨å¤çè½¦è¾ {} ({}/{})", vehicleId, i + 1, vehicleIds.size()); |
| | | |
| | | int segmentCount = calculateVehicleSegmentMileage(vehicleId, startTime, endTime); |
| | | if (segmentCount > 0) { |
| | | successCount++; |
| | | // logger.info("è½¦è¾ {} è®¡ç®æåï¼çæ {} ä¸ªåæ®µè®°å½", vehicleId, segmentCount); |
| | | } else { |
| | | // logger.debug("è½¦è¾ {} æ ææ°çGPSåæ®µæ°æ®", vehicleId); |
| | | // åæ¹å¤çï¼é¿å
䏿¬¡æ§å¤çè¿å¤æ°æ®å¯¼è´å
åæº¢åº |
| | | for (int batchStart = 0; batchStart < vehicleIds.size(); batchStart += BATCH_SIZE) { |
| | | int batchEnd = Math.min(batchStart + BATCH_SIZE, vehicleIds.size()); |
| | | List<Long> batchVehicleIds = vehicleIds.subList(batchStart, batchEnd); |
| | | |
| | | logger.info("å¤çæ¹æ¬¡ {}-{}/{}", batchStart + 1, batchEnd, vehicleIds.size()); |
| | | |
| | | // éè¾è®¡ç®ï¼å
å«é误å¤çåéè¯æºå¶ |
| | | for (int i = 0; i < batchVehicleIds.size(); i++) { |
| | | Long vehicleId = batchVehicleIds.get(i); |
| | | int overallIndex = batchStart + i; |
| | | try { |
| | | int segmentCount = calculateVehicleSegmentMileage(vehicleId, startTime, endTime); |
| | | if (segmentCount > 0) { |
| | | successCount++; |
| | | } |
| | | } catch (Exception e) { |
| | | failedCount++; |
| | | logger.error("计ç®è½¦è¾ {} çåæ®µéç¨å¤±è´¥ ({}/{})", vehicleId, overallIndex + 1, vehicleIds.size(), e); |
| | | // ä¸ä¸ææ´ä¸ªæ¹å¤çï¼ç»§ç»å¤çä¸ä¸è¾è½¦ |
| | | } |
| | | } catch (Exception e) { |
| | | failedCount++; |
| | | logger.error("计ç®è½¦è¾ {} çåæ®µéç¨å¤±è´¥ ({}/{})", vehicleId, i + 1, vehicleIds.size(), e); |
| | | |
| | | // ä¸ä¸ææ´ä¸ªæ¹å¤çï¼ç»§ç»å¤çä¸ä¸è¾è½¦ |
| | | // æ¯å¤ç10è¾è½¦è¾åºä¸æ¬¡è¿åº¦ |
| | | if ((overallIndex + 1) % 10 == 0) { |
| | | logger.info("æ¹é计ç®è¿åº¦: {}/{}, æå: {}, 失败: {}", |
| | | overallIndex + 1, vehicleIds.size(), successCount, failedCount); |
| | | } |
| | | } |
| | | |
| | | // æ¯å¤ç10è¾è½¦è¾åºä¸æ¬¡è¿åº¦ |
| | | if ((i + 1) % 10 == 0) { |
| | | logger.info("æ¹é计ç®è¿åº¦: {}/{}, æå: {}, 失败: {}", |
| | | i + 1, vehicleIds.size(), successCount, failedCount); |
| | | // æ¹æ¬¡ç»æåï¼ä¸»å¨è§¦åGC建议ï¼ä¸å¼ºå¶ï¼ |
| | | if (batchEnd < vehicleIds.size()) { |
| | | System.gc(); |
| | | logger.debug("æ¹æ¬¡ {}-{} å¤ç宿ï¼å·²å»ºè®®JVMåæ¶å
å", batchStart + 1, batchEnd); |
| | | } |
| | | } |
| | | |
| | |
| | | |
| | | |
| | | String endTimeStr=DateUtils.formatDate(endTime, DateUtils.YYYY_MM_DD_HH_MM_SS); |
| | | for (Long vehicleId : vehicleIds) { |
| | | try { |
| | | // æ¥è¯¢è¯¥è½¦è¾æªè¢«è®¡ç®çGPSæ°æ® |
| | | List<VehicleGps> uncalculatedGps = vehicleGpsMapper.selectUncalculatedGps(vehicleId, startTimeStr, endTimeStr); |
| | | // åæ¹å¤ç车è¾ï¼é¿å
å
åæº¢åº |
| | | for (int batchStart = 0; batchStart < vehicleIds.size(); batchStart += BATCH_SIZE) { |
| | | int batchEnd = Math.min(batchStart + BATCH_SIZE, vehicleIds.size()); |
| | | List<Long> batchVehicleIds = vehicleIds.subList(batchStart, batchEnd); |
| | | |
| | | for (Long vehicleId : batchVehicleIds) { |
| | | try { |
| | | // æ¥è¯¢è¯¥è½¦è¾æªè¢«è®¡ç®çGPSæ°æ® |
| | | List<VehicleGps> uncalculatedGps = vehicleGpsMapper.selectUncalculatedGps(vehicleId, startTimeStr, endTimeStr); |
| | | |
| | | if (uncalculatedGps == null || uncalculatedGps.isEmpty()) { |
| | | logger.debug("è½¦è¾ {} æ²¡ææªè®¡ç®çGPSæ°æ®", vehicleId); |
| | |
| | | int segmentCount = calculateVehicleSegmentMileageWithGpsList( |
| | | vehicleId, uncalculatedGps, uncalculatedStartTime, uncalculatedEndTime); |
| | | |
| | | if (segmentCount > 0) { |
| | | successCount++; |
| | | logger.info("è½¦è¾ {} è¡¥å¿è®¡ç®å®æï¼çæ {} ä¸ªåæ®µè®°å½", vehicleId, segmentCount); |
| | | if (segmentCount > 0) { |
| | | successCount++; |
| | | logger.info("è½¦è¾ {} è¡¥å¿è®¡ç®å®æï¼çæ {} ä¸ªåæ®µè®°å½", vehicleId, segmentCount); |
| | | } |
| | | } catch (Exception e) { |
| | | logger.error("è½¦è¾ {} è¡¥å¿è®¡ç®å¤±è´¥", vehicleId, e); |
| | | } |
| | | } catch (Exception e) { |
| | | logger.error("è½¦è¾ {} è¡¥å¿è®¡ç®å¤±è´¥", vehicleId, e); |
| | | } |
| | | |
| | | // æ¯æ¹æ¬¡ç»æåï¼ä¸»å¨å»ºè®®GC |
| | | if (batchEnd < vehicleIds.size()) { |
| | | uncalculatedGps = null; // æ¾å¼æ¸
空å¼ç¨ |
| | | System.gc(); |
| | | logger.debug("è¡¥å¿è®¡ç®æ¹æ¬¡ {}-{} 宿ï¼å·²å»ºè®®JVMåæ¶å
å", batchStart + 1, batchEnd); |
| | | } |
| | | } |
| | | |
| | |
| | | * æ¶éGPS IDå表ï¼å
æ¬åç½®ç¹ï¼ |
| | | */ |
| | | private List<Long> collectGpsIds(List<VehicleGps> segmentGpsList, VehicleGps previousSegmentLastPoint) { |
| | | List<Long> gpsIdList = new ArrayList<>(); |
| | | // é¢åé
åç容éï¼åå°æ©å®¹å¼é |
| | | List<Long> gpsIdList = new ArrayList<>(segmentGpsList.size() + 1); |
| | | |
| | | // 妿æä¸ä¸æ®µçæåä¸ä¸ªç¹ï¼å
æ·»å å®çIDï¼ç¨äºè®¡ç®è·¨æ®µè·ç¦»ï¼ |
| | | if (previousSegmentLastPoint != null && previousSegmentLastPoint.getGpsId() != null) { |
| | |
| | | |
| | | /** |
| | | * è§£ææ¥ææ¶é´å符串 |
| | | * 使ç¨ThreadLocalçSimpleDateFormatï¼é¿å
æ¯æ¬¡å建æ°å¯¹è±¡ |
| | | */ |
| | | private static final ThreadLocal<java.text.SimpleDateFormat> DATE_FORMAT_THREAD_LOCAL = |
| | | ThreadLocal.withInitial(() -> { |
| | | java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); |
| | | sdf.setLenient(false); |
| | | return sdf; |
| | | }); |
| | | |
| | | private Date parseDateTime(String dateTimeStr) { |
| | | if (dateTimeStr == null || dateTimeStr.trim().isEmpty()) { |
| | | throw new RuntimeException("æ¥ææ¶é´å符串ä¸è½ä¸ºç©º"); |
| | | } |
| | | |
| | | try { |
| | | java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); |
| | | sdf.setLenient(false); |
| | | return sdf.parse(dateTimeStr.trim()); |
| | | return DATE_FORMAT_THREAD_LOCAL.get().parse(dateTimeStr.trim()); |
| | | } catch (Exception e) { |
| | | throw new RuntimeException("æ¥ææ¶é´æ ¼å¼é误: " + dateTimeStr + ", åºä¸º yyyy-MM-dd HH:mm:ss", e); |
| | | } |
| | |
| | | * @return ç»æ |
| | | */ |
| | | @Override |
| | | @Transactional |
| | | public int insertVehicleInfo(VehicleInfo vehicleInfo) { |
| | | int rows = vehicleInfoMapper.insertVehicleInfo(vehicleInfo); |
| | | |
| | |
| | | * @param vehicleInfo 车è¾ä¿¡æ¯ |
| | | * @return ç»æ |
| | | */ |
| | | @Override |
| | | @Transactional |
| | | @Override |
| | | public int updateVehicleInfo(VehicleInfo vehicleInfo) { |
| | | // åªæå½ deptIds ä¸ä¸º null æ¶ææ´æ°é¨é¨å
³è(é¿å
ä¸å¿
è¦çéç«äº) |
| | | if (vehicleInfo.getDeptIds() != null) { |
| | |
| | | * @return ç»æ |
| | | */ |
| | | @Override |
| | | @Transactional |
| | | |
| | | public int bindVehicleToUser(Long userId, Long vehicleId) { |
| | | // å
è§£ç»ç¨æ·çææè½¦è¾ï¼ä¸å¡é»è¾ï¼ä¸ä¸ªç¨æ·åæ¶åªè½ç»å®ä¸è¾è½¦ï¼ |
| | | vehicleInfoMapper.unbindAllVehiclesFromUser(userId); |
| | |
| | | * @return åæ¥ç»æ |
| | | */ |
| | | @Override |
| | | @Transactional |
| | | |
| | | public AjaxResult syncVehicles(List<VehicleSyncDTO> vehicles) |
| | | { |
| | | if (vehicles == null || vehicles.isEmpty()) |
| | |
| | | **ä¿®å¤å
容**ï¼ |
| | | ```java |
| | | @Override |
| | | @Transactional |
| | | |
| | | public int insertSysTaskVehicle(SysTaskVehicle sysTaskVehicle) { |
| | | // 设置åé
æ¶é´ååé
人 |
| | | if (sysTaskVehicle.getAssignTime() == null) { |
| | |
| | | returningTransitions.add(TaskStatus.COMPLETED); |
| | | ALLOWED_TRANSITIONS.put(TaskStatus.RETURNING, returningTransitions); |
| | | |
| | | // IN_PROGRESS -> COMPLETED, CANCELLED, PENDING (å
¼å®¹æ§æ°æ®) |
| | | // IN_PROGRESS -> COMPLETED, CANCELLED, PENDING, ARRIVED, RETURNING (å
¼å®¹æ§æ°æ®) |
| | | Set<TaskStatus> inProgressTransitions = new HashSet<>(); |
| | | inProgressTransitions.add(TaskStatus.COMPLETED); |
| | | inProgressTransitions.add(TaskStatus.CANCELLED); |
| | | inProgressTransitions.add(TaskStatus.PENDING); |
| | | inProgressTransitions.add(TaskStatus.ARRIVED); |
| | | inProgressTransitions.add(TaskStatus.RETURNING); |
| | | ALLOWED_TRANSITIONS.put(TaskStatus.IN_PROGRESS, inProgressTransitions); |
| | | |
| | | // COMPLETED -> ä¸å
许任ä½ç¶æåæ´ |
| | |
| | | FROM ServiceOrder as a |
| | | left JOIN DispatchOrd b on a.ServiceOrdID = b.ServiceOrdIDDt |
| | | WHERE a.ServiceOrdState <= 3 |
| | | AND a.ServiceOrd_CC_Time > #{startDate} |
| | | AND a.ServiceOrd_CC_Time > #{startDate} and a.ServiceOrd_CC_Time < #{endDate} |
| | | |
| | | </select> |
| | | |
| | |
| | | limit #{limit} |
| | | </if> |
| | | <if test="offset == null and limit == null"> |
| | | limit 200 |
| | | limit 10 |
| | | </if> |
| | | </select> |
| | | |
| | |
| | | </el-radio-group> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å¯å建任å¡å"> |
| | | <el-radio-group v-model="form.canCreateTask"> |
| | | <el-radio label="0">å¦</el-radio> |
| | | <el-radio label="1">æ¯</el-radio> |
| | | </el-radio-group> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å¯ç®¡çä»»å¡å"> |
| | | <el-radio-group v-model="form.canViewAllConsult"> |
| | | <el-radio label="0">å¦</el-radio> |
| | | <el-radio label="1">æ¯</el-radio> |
| | | </el-radio-group> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row> |
| | | <el-col :span="12"> |
| | |
| | | // è§è²é项 |
| | | roleOptions: [], |
| | | // 表ååæ° |
| | | form: {}, |
| | | form: { |
| | | canCreateTask: "0" |
| | | }, |
| | | defaultProps: { |
| | | children: "children", |
| | | label: "label" |
| | |
| | | remark: undefined, |
| | | postIds: [], |
| | | roleIds: [], |
| | | canViewAllConsult: "0" |
| | | canViewAllConsult: "0", |
| | | canCreateTask: "0" |
| | | }; |
| | | this.resetForm("form"); |
| | | }, |
| New file |
| | |
| | | -- ===================================================== |
| | | -- å
åä¼åç¸å
³æ°æ®åºç´¢å¼ä¼åèæ¬ |
| | | -- ç¨äºæåGPSç¸å
³æ¥è¯¢æ§è½ï¼åå°æ
¢æ¥è¯¢å¯¼è´çå
åå ç¨ |
| | | -- ===================================================== |
| | | -- æ§è¡å请å
å¤ä»½æ°æ®åºï¼ |
| | | -- æ§è¡æ¹å¼: mysql -u root -p æ°æ®åºå < optimize_memory_indexes.sql |
| | | -- ===================================================== |
| | | |
| | | USE `966120`; |
| | | |
| | | -- ===================================================== |
| | | -- 1. GPSæ°æ®è¡¨ç´¢å¼ä¼å |
| | | -- ===================================================== |
| | | |
| | | -- æ£æ¥ tb_vehicle_gps 表çç°æç´¢å¼ |
| | | SELECT |
| | | TABLE_NAME, |
| | | INDEX_NAME, |
| | | COLUMN_NAME, |
| | | SEQ_IN_INDEX, |
| | | INDEX_TYPE |
| | | FROM information_schema.STATISTICS |
| | | WHERE TABLE_SCHEMA = '966120' |
| | | AND TABLE_NAME = 'tb_vehicle_gps' |
| | | ORDER BY INDEX_NAME, SEQ_IN_INDEX; |
| | | |
| | | -- æ·»å 车è¾IDåééæ¶é´çç»åç´¢å¼ï¼ç¨äºGPSåæ®µæ¥è¯¢ï¼ |
| | | -- æ¤ç´¢å¼å¯å¤§å¹
æå selectActiveVehicleIds å selectGpsDataByTimeRange æ¥è¯¢æ§è½ |
| | | ALTER TABLE tb_vehicle_gps |
| | | ADD INDEX idx_vehicle_collect_time (vehicle_id, collect_time) |
| | | COMMENT 'GPSåæ®µæ¥è¯¢ä¼åç´¢å¼'; |
| | | |
| | | -- æ·»å ééæ¶é´åç¬ç´¢å¼ï¼ç¨äºæ¶é´èå´æ¥è¯¢ï¼ |
| | | ALTER TABLE tb_vehicle_gps |
| | | ADD INDEX idx_collect_time (collect_time) |
| | | COMMENT 'GPSæ¶é´èå´æ¥è¯¢ç´¢å¼'; |
| | | |
| | | -- æ·»å 设å¤IDç´¢å¼ï¼ç¨äºGPS忥æ¥è¯¢ï¼ |
| | | ALTER TABLE tb_vehicle_gps |
| | | ADD INDEX idx_device_id (device_id) |
| | | COMMENT 'GPS设å¤IDæ¥è¯¢ç´¢å¼'; |
| | | |
| | | -- ===================================================== |
| | | -- 2. GPSåæ®µéç¨è¡¨ç´¢å¼ä¼å |
| | | -- ===================================================== |
| | | |
| | | -- æ£æ¥ vehicle_gps_segment_mileage 表çç°æç´¢å¼ |
| | | SELECT |
| | | TABLE_NAME, |
| | | INDEX_NAME, |
| | | COLUMN_NAME, |
| | | SEQ_IN_INDEX, |
| | | INDEX_TYPE |
| | | FROM information_schema.STATISTICS |
| | | WHERE TABLE_SCHEMA = '966120' |
| | | AND TABLE_NAME = 'vehicle_gps_segment_mileage' |
| | | ORDER BY INDEX_NAME, SEQ_IN_INDEX; |
| | | |
| | | -- æ·»å 车è¾IDååæ®µå¼å§æ¶é´çç»åç´¢å¼ |
| | | ALTER TABLE vehicle_gps_segment_mileage |
| | | ADD INDEX idx_vehicle_segment_start (vehicle_id, segment_start_time) |
| | | COMMENT '车è¾å段æ¥è¯¢ç´¢å¼'; |
| | | |
| | | -- æ·»å ä»»å¡IDç´¢å¼ï¼ç¨äºä»»å¡å
³èæ¥è¯¢ï¼ |
| | | ALTER TABLE vehicle_gps_segment_mileage |
| | | ADD INDEX idx_task_id (task_id) |
| | | COMMENT 'ä»»å¡å
³èæ¥è¯¢ç´¢å¼'; |
| | | |
| | | -- æ·»å åæ®µæ¶é´èå´ç´¢å¼ï¼ç¨äºç»è®¡æ±æ»ï¼ |
| | | ALTER TABLE vehicle_gps_segment_mileage |
| | | ADD INDEX idx_segment_time_range (segment_start_time, segment_end_time) |
| | | COMMENT 'åæ®µæ¶é´èå´æ¥è¯¢ç´¢å¼'; |
| | | |
| | | -- ===================================================== |
| | | -- 3. GPS已计ç®è®°å½è¡¨ç´¢å¼ä¼å |
| | | -- ===================================================== |
| | | |
| | | -- æ£æ¥ vehicle_gps_calculated 表æ¯å¦åå¨ |
| | | SELECT COUNT(*) as table_exists |
| | | FROM information_schema.TABLES |
| | | WHERE TABLE_SCHEMA = '966120' |
| | | AND TABLE_NAME = 'vehicle_gps_calculated'; |
| | | |
| | | -- å¦æè¡¨åå¨ï¼æ·»å ç´¢å¼ |
| | | ALTER TABLE vehicle_gps_calculated |
| | | ADD INDEX idx_gps_id (gps_id) |
| | | COMMENT 'GPSç¹æ¥è¯¢ç´¢å¼'; |
| | | |
| | | ALTER TABLE vehicle_gps_calculated |
| | | ADD INDEX idx_vehicle_segment (vehicle_id, segment_id) |
| | | COMMENT '车è¾å段å
³èç´¢å¼'; |
| | | |
| | | -- ===================================================== |
| | | -- 4. ä»»å¡è¡¨ç´¢å¼ä¼å |
| | | -- ===================================================== |
| | | |
| | | -- æ·»å 车è¾IDåæ¶é´èå´çç»åç´¢å¼ï¼ç¨äºå
³è任塿¥è¯¢ï¼ |
| | | ALTER TABLE sys_task |
| | | ADD INDEX idx_vehicle_time_range ( |
| | | vehicle_id, |
| | | actual_start_time, |
| | | actual_end_time |
| | | ) COMMENT '车è¾ä»»å¡æ¶é´èå´æ¥è¯¢ç´¢å¼'; |
| | | |
| | | -- æ·»å ä»»å¡ç¶æåè®¡åæ¶é´ç´¢å¼ï¼ç¨äºå®æ¶ä»»å¡æ¥è¯¢ï¼ |
| | | ALTER TABLE sys_task |
| | | ADD INDEX idx_status_planned_time ( |
| | | task_status, |
| | | planned_start_time |
| | | ) COMMENT 'ä»»å¡ç¶ææ¶é´æ¥è¯¢ç´¢å¼'; |
| | | |
| | | -- ===================================================== |
| | | -- 5. æ¥æè½¬è¿ä»»å¡è¡¨ç´¢å¼ä¼å |
| | | -- ===================================================== |
| | | |
| | | -- æ·»å åæ¥ç¶æç´¢å¼ï¼ç¨äºæ§ç³»ç»åæ¥ä»»å¡ï¼ |
| | | ALTER TABLE sys_task_emergency |
| | | ADD INDEX idx_sync_status (sync_status) |
| | | COMMENT 'åæ¥ç¶ææ¥è¯¢ç´¢å¼'; |
| | | |
| | | -- æ·»å è°åº¦ååæ¥ç¶æç´¢å¼ |
| | | ALTER TABLE sys_task_emergency |
| | | ADD INDEX idx_dispatch_sync_status (dispatch_sync_status) |
| | | COMMENT 'è°åº¦ååæ¥ç¶ææ¥è¯¢ç´¢å¼'; |
| | | |
| | | -- æ·»å æ§ç³»ç»IDç»åç´¢å¼ï¼ç¨äºåå忥æ¥è¯¢ï¼ |
| | | ALTER TABLE sys_task_emergency |
| | | ADD INDEX idx_legacy_ids ( |
| | | legacy_service_ord_id, |
| | | legacy_dispatch_ord_id |
| | | ) COMMENT 'æ§ç³»ç»IDæ¥è¯¢ç´¢å¼'; |
| | | |
| | | -- ===================================================== |
| | | -- 6. 车è¾ä¿¡æ¯è¡¨ç´¢å¼ä¼å |
| | | -- ===================================================== |
| | | |
| | | -- æ·»å 设å¤IDç´¢å¼ï¼ç¨äºGPSå
³èæ¥è¯¢ï¼ |
| | | ALTER TABLE tb_vehicle_info |
| | | ADD INDEX idx_device_id (device_id) |
| | | COMMENT '设å¤IDæ¥è¯¢ç´¢å¼'; |
| | | |
| | | -- æ·»å 车çå·ç´¢å¼ï¼ç¨äºè½¦è¾æ¥è¯¢ï¼ |
| | | ALTER TABLE tb_vehicle_info |
| | | ADD INDEX idx_vehicle_no (vehicle_no) |
| | | COMMENT '车çå·æ¥è¯¢ç´¢å¼'; |
| | | |
| | | -- ===================================================== |
| | | -- 7. 车è¾éç¨ç»è®¡è¡¨ç´¢å¼ä¼å |
| | | -- ===================================================== |
| | | |
| | | -- æ£æ¥ vehicle_mileage_stats 表çç°æç´¢å¼ |
| | | SELECT |
| | | TABLE_NAME, |
| | | INDEX_NAME, |
| | | COLUMN_NAME, |
| | | SEQ_IN_INDEX, |
| | | INDEX_TYPE |
| | | FROM information_schema.STATISTICS |
| | | WHERE TABLE_SCHEMA = '966120' |
| | | AND TABLE_NAME = 'vehicle_mileage_stats' |
| | | ORDER BY INDEX_NAME, SEQ_IN_INDEX; |
| | | |
| | | -- æ·»å 车è¾IDåç»è®¡æ¥æçç»åç´¢å¼ |
| | | ALTER TABLE vehicle_mileage_stats |
| | | ADD INDEX idx_vehicle_stat_date (vehicle_id, stat_date) |
| | | COMMENT '车è¾ç»è®¡æ¥ææ¥è¯¢ç´¢å¼'; |
| | | |
| | | -- æ·»å ç»è®¡æ¥æç´¢å¼ï¼ç¨äºæ¹éæ¥è¯¢ï¼ |
| | | ALTER TABLE vehicle_mileage_stats |
| | | ADD INDEX idx_stat_date (stat_date) |
| | | COMMENT 'ç»è®¡æ¥ææ¥è¯¢ç´¢å¼'; |
| | | |
| | | -- ===================================================== |
| | | -- 8. éªè¯ç´¢å¼åå»ºç»æ |
| | | -- ===================================================== |
| | | |
| | | -- æ¥çæææ°å¢ç´¢å¼ |
| | | SELECT |
| | | TABLE_NAME as '表å', |
| | | INDEX_NAME as 'ç´¢å¼å', |
| | | GROUP_CONCAT(COLUMN_NAME ORDER BY SEQ_IN_INDEX) as 'ç´¢å¼å', |
| | | INDEX_TYPE as 'ç´¢å¼ç±»å', |
| | | COMMENT as '夿³¨' |
| | | FROM information_schema.STATISTICS |
| | | WHERE TABLE_SCHEMA = '966120' |
| | | AND TABLE_NAME IN ( |
| | | 'tb_vehicle_gps', |
| | | 'vehicle_gps_segment_mileage', |
| | | 'vehicle_gps_calculated', |
| | | 'sys_task', |
| | | 'sys_task_emergency', |
| | | 'tb_vehicle_info', |
| | | 'vehicle_mileage_stats' |
| | | ) |
| | | AND INDEX_NAME LIKE 'idx_%' |
| | | GROUP BY TABLE_NAME, INDEX_NAME |
| | | ORDER BY TABLE_NAME, INDEX_NAME; |
| | | |
| | | -- ===================================================== |
| | | -- 9. æ¥è¯¢æ§è½æµè¯ |
| | | -- ===================================================== |
| | | |
| | | -- æµè¯GPSåæ®µæ¥è¯¢æ§è½ |
| | | EXPLAIN SELECT vehicle_id |
| | | FROM tb_vehicle_gps |
| | | WHERE collect_time >= DATE_SUB(NOW(), INTERVAL 1 HOUR) |
| | | GROUP BY vehicle_id; |
| | | |
| | | -- æµè¯è½¦è¾å段éç¨æ¥è¯¢æ§è½ |
| | | EXPLAIN SELECT * |
| | | FROM vehicle_gps_segment_mileage |
| | | WHERE vehicle_id = 1 |
| | | AND segment_start_time >= DATE_SUB(NOW(), INTERVAL 1 DAY); |
| | | |
| | | -- æµè¯ä»»å¡å
³èæ¥è¯¢æ§è½ |
| | | EXPLAIN SELECT t.* |
| | | FROM sys_task t |
| | | WHERE t.vehicle_id = 1 |
| | | AND t.actual_start_time >= DATE_SUB(NOW(), INTERVAL 1 DAY) |
| | | AND t.actual_end_time <= NOW(); |
| | | |
| | | -- ===================================================== |
| | | -- 10. ç´¢å¼ä½¿ç¨ç»è®¡ï¼å¯éï¼ |
| | | -- ===================================================== |
| | | |
| | | -- å¯ç¨æ§è½ç»è®¡ï¼MySQL 8.0+ï¼ |
| | | -- UPDATE performance_schema.setup_instruments |
| | | -- SET ENABLED = 'YES', TIMED = 'YES' |
| | | -- WHERE NAME LIKE '%statement/%'; |
| | | |
| | | -- æ¥çæ
¢æ¥è¯¢ç»è®¡ |
| | | SELECT |
| | | SCHEMA_NAME as 'æ°æ®åº', |
| | | DIGEST_TEXT as 'æ¥è¯¢è¯å¥', |
| | | COUNT_STAR as 'æ§è¡æ¬¡æ°', |
| | | AVG_TIMER_WAIT/1000000000 as 'å¹³åèæ¶(ç§)', |
| | | SUM_ROWS_EXAMINED as 'æ«æè¡æ°' |
| | | FROM performance_schema.events_statements_summary_by_digest |
| | | WHERE SCHEMA_NAME = '966120' |
| | | ORDER BY AVG_TIMER_WAIT DESC |
| | | LIMIT 10; |
| | | |
| | | -- ===================================================== |
| | | -- 宿æç¤º |
| | | -- ===================================================== |
| | | |
| | | SELECT '====================================' as ''; |
| | | SELECT 'ç´¢å¼ä¼åèæ¬æ§è¡å®æï¼' as 'æç¤º'; |
| | | SELECT 'è¯·æ£æ¥ä¸è¿°éªè¯ç»æï¼ç¡®è®¤ç´¢å¼å·²æ£ç¡®å建' as '说æ'; |
| | | SELECT '建议éå¯åºç¨æå¡ï¼è®©æ°ç´¢å¼çæ' as '建议'; |
| | | SELECT '====================================' as ''; |
| | | |
| | | -- ===================================================== |
| | | -- åæ»èæ¬ï¼å¦éå é¤ç´¢å¼ï¼ |
| | | -- ===================================================== |
| | | /* |
| | | -- 妿éè¦åæ»ï¼æ§è¡ä»¥ä¸è¯å¥ï¼ |
| | | |
| | | ALTER TABLE tb_vehicle_gps DROP INDEX idx_vehicle_collect_time; |
| | | ALTER TABLE tb_vehicle_gps DROP INDEX idx_collect_time; |
| | | ALTER TABLE tb_vehicle_gps DROP INDEX idx_device_id; |
| | | |
| | | ALTER TABLE vehicle_gps_segment_mileage DROP INDEX idx_vehicle_segment_start; |
| | | ALTER TABLE vehicle_gps_segment_mileage DROP INDEX idx_task_id; |
| | | ALTER TABLE vehicle_gps_segment_mileage DROP INDEX idx_segment_time_range; |
| | | |
| | | ALTER TABLE vehicle_gps_calculated DROP INDEX idx_gps_id; |
| | | ALTER TABLE vehicle_gps_calculated DROP INDEX idx_vehicle_segment; |
| | | |
| | | ALTER TABLE sys_task DROP INDEX idx_vehicle_time_range; |
| | | ALTER TABLE sys_task DROP INDEX idx_status_planned_time; |
| | | |
| | | ALTER TABLE sys_task_emergency DROP INDEX idx_sync_status; |
| | | ALTER TABLE sys_task_emergency DROP INDEX idx_dispatch_sync_status; |
| | | ALTER TABLE sys_task_emergency DROP INDEX idx_legacy_ids; |
| | | |
| | | ALTER TABLE tb_vehicle_info DROP INDEX idx_device_id; |
| | | ALTER TABLE tb_vehicle_info DROP INDEX idx_vehicle_no; |
| | | |
| | | ALTER TABLE vehicle_mileage_stats DROP INDEX idx_vehicle_stat_date; |
| | | ALTER TABLE vehicle_mileage_stats DROP INDEX idx_stat_date; |
| | | */ |
| | |
| | | -- ä»»ä½ç¶æï¼COMPLETEDé¤å¤ï¼-> CANCELLEDï¼å·²åæ¶ï¼ |
| | | -- |
| | | -- å
¼å®¹æ§æ°æ®ï¼ |
| | | -- IN_PROGRESSï¼ä»»å¡ä¸ï¼å¯ä»¥è½¬æ¢ä¸º COMPLETEDãCANCELLED æ PENDING |
| | | -- IN_PROGRESSï¼ä»»å¡ä¸ï¼å¯ä»¥è½¬æ¢ä¸º COMPLETEDãCANCELLEDãPENDINGãARRIVEDãRETURNING |
| | | -- 说æï¼IN_PROGRESS æ¯ä¸ºäºå
¼å®¹æ§ç³»ç»çâæå¡ä¸âç¶æï¼å
许åå¤ä¸ªç¶æè½¬æ¢ |
| | | -- |
| | | -- =================================================================== |
| New file |
| | |
| | | # ä»»å¡ç¶ææµè½¬è§å说æ |
| | | |
| | | ## ð æ¦è¿° |
| | | |
| | | æ¬ææ¡£è¯´æè½¬è¿ä»»å¡çç¶ææµè½¬è§åï¼å
æ¬æ£å¸¸æµç¨åå
¼å®¹æ§æ°æ®çç¹æ®è§åã |
| | | |
| | | --- |
| | | |
| | | ## ð ç¶æå®ä¹ |
| | | |
| | | ### æ åç¶æï¼æ°ç³»ç»ï¼ |
| | | |
| | | | ç¶æç | ç¶æåç§° | 说æ | æ ·å¼ | |
| | | |--------|---------|------|------| |
| | | | `PENDING` | å¾
å¤ç | ä»»å¡å·²å建ï¼çå¾
åºå | warning | |
| | | | `DEPARTING` | åºåä¸ | ä»»å¡å·²åºåï¼åå¾ç®çå° | primary | |
| | | | `ARRIVED` | å·²å°è¾¾ | å·²å°è¾¾ç®çå° | primary | |
| | | | `RETURNING` | è¿ç¨ä¸ | ä»»å¡è¿ç¨ä¸ | primary | |
| | | | `COMPLETED` | 已宿 | ä»»å¡å·²å®æï¼ç»æï¼ | success | |
| | | | `CANCELLED` | 已忶 | ä»»å¡å·²åæ¶ï¼ç»æï¼ | danger | |
| | | |
| | | ### å
¼å®¹ç¶æï¼æ§ç³»ç»ï¼ |
| | | |
| | | | ç¶æç | ç¶æåç§° | 说æ | æ¥æº | |
| | | |--------|---------|------|------| |
| | | | `IN_PROGRESS` | ä»»å¡ä¸ | 任塿§è¡ä¸ï¼å
¼å®¹æ§æ°æ®ï¼ | æ§ç³»ç»ç¶æç 6 | |
| | | |
| | | --- |
| | | |
| | | ## ð¦ ç¶ææµè½¬è§å |
| | | |
| | | ### 1. æ£å¸¸æµç¨ |
| | | |
| | | ```mermaid |
| | | graph LR |
| | | A[PENDING<br/>å¾
å¤ç] --> B[DEPARTING<br/>åºåä¸] |
| | | B --> C[ARRIVED<br/>å·²å°è¾¾] |
| | | C --> D[RETURNING<br/>è¿ç¨ä¸] |
| | | D --> E[COMPLETED<br/>已宿] |
| | | |
| | | A -.忶.-> F[CANCELLED<br/>已忶] |
| | | B -.åæ¶.-> F |
| | | C -.åæ¶.-> F |
| | | ``` |
| | | |
| | | **æµè½¬è·¯å¾**ï¼ |
| | | - `PENDING` â `DEPARTING` â `ARRIVED` â `RETURNING` â `COMPLETED` |
| | | - ä»»ä½ç¶æï¼é¤COMPLETEDå¤ï¼â `CANCELLED` |
| | | |
| | | --- |
| | | |
| | | ### 2. å
¼å®¹æ§æ°æ®æµç¨ |
| | | |
| | | ```mermaid |
| | | graph TD |
| | | A[IN_PROGRESS<br/>ä»»å¡ä¸<br/>æ§æ°æ®] --> B[PENDING<br/>å¾
å¤ç] |
| | | A --> C[ARRIVED<br/>å·²å°è¾¾] |
| | | A --> D[RETURNING<br/>è¿ç¨ä¸] |
| | | A --> E[COMPLETED<br/>已宿] |
| | | A --> F[CANCELLED<br/>已忶] |
| | | |
| | | style A fill:#ffeaa7,stroke:#fdcb6e |
| | | style B fill:#74b9ff,stroke:#0984e3 |
| | | style C fill:#74b9ff,stroke:#0984e3 |
| | | style D fill:#74b9ff,stroke:#0984e3 |
| | | style E fill:#55efc4,stroke:#00b894 |
| | | style F fill:#ff7675,stroke:#d63031 |
| | | ``` |
| | | |
| | | **说æ**ï¼ |
| | | - `IN_PROGRESS` æ¯ä¸ºäºå
¼å®¹æ§ç³»ç»ç"æå¡ä¸"ç¶æï¼ç¶æç 6ï¼ |
| | | - å
许å**5ä¸ªç¶æ**转æ¢ï¼æä¾æå¤§çµæ´»æ§ |
| | | - 主è¦ç¨äºæ°æ®è¿ç§»ååç³»ç»å¹¶è¡æé´ |
| | | |
| | | --- |
| | | |
| | | ## ð è¯¦ç»æµè½¬è§å |
| | | |
| | | ### PENDINGï¼å¾
å¤çï¼ |
| | | â
**å
许转æ¢å°**ï¼ |
| | | - `DEPARTING`ï¼åºåä¸ï¼- å¼å§æ§è¡ä»»å¡ |
| | | - `CANCELLED`ï¼å·²åæ¶ï¼- åæ¶ä»»å¡ |
| | | |
| | | â **ä¸å
许转æ¢å°**ï¼å
¶ä»ææç¶æ |
| | | |
| | | --- |
| | | |
| | | ### DEPARTINGï¼åºåä¸ï¼ |
| | | â
**å
许转æ¢å°**ï¼ |
| | | - `ARRIVED`ï¼å·²å°è¾¾ï¼- å°è¾¾ç®çå° |
| | | - `CANCELLED`ï¼å·²åæ¶ï¼- åæ¶ä»»å¡ |
| | | |
| | | â **ä¸å
许转æ¢å°**ï¼å
¶ä»ææç¶æ |
| | | |
| | | --- |
| | | |
| | | ### ARRIVEDï¼å·²å°è¾¾ï¼ |
| | | â
**å
许转æ¢å°**ï¼ |
| | | - `RETURNING`ï¼è¿ç¨ä¸ï¼- å¼å§è¿ç¨ |
| | | |
| | | â **ä¸å
许转æ¢å°**ï¼å
¶ä»ææç¶æ |
| | | |
| | | **注æ**ï¼å·²å°è¾¾ååªè½è¿ç¨ï¼ä¸è½ç´æ¥å®ææåæ¶ |
| | | |
| | | --- |
| | | |
| | | ### RETURNINGï¼è¿ç¨ä¸ï¼ |
| | | â
**å
许转æ¢å°**ï¼ |
| | | - `COMPLETED`ï¼å·²å®æï¼- 宿è¿ç¨ |
| | | |
| | | â **ä¸å
许转æ¢å°**ï¼å
¶ä»ææç¶æ |
| | | |
| | | --- |
| | | |
| | | ### IN_PROGRESSï¼ä»»å¡ä¸ï¼â ï¸ |
| | | â
**å
许转æ¢å°**ï¼ |
| | | - `PENDING`ï¼å¾
å¤çï¼- æ°æ®ä¿®æ£ |
| | | - `ARRIVED`ï¼å·²å°è¾¾ï¼- è¡¥å
ç¶æ |
| | | - `RETURNING`ï¼è¿ç¨ä¸ï¼- è¿å
¥è¿ç¨ â **æ°å¢** |
| | | - `COMPLETED`ï¼å·²å®æï¼- 强å¶å®æ |
| | | - `CANCELLED`ï¼å·²åæ¶ï¼- åæ¶ä»»å¡ |
| | | |
| | | â **ä¸å
许转æ¢å°**ï¼å
¶ä»ææç¶æ |
| | | |
| | | **使ç¨åºæ¯**ï¼ |
| | | 1. æ§ç³»ç»æ°æ®è¿ç§» |
| | | 2. ç¶æè¡¥å¿ä¿®æ£ |
| | | 3. ç¹æ®ä¸å¡æµç¨ |
| | | |
| | | --- |
| | | |
| | | ### COMPLETEDï¼å·²å®æï¼ |
| | | â
**å
许转æ¢å°**ï¼æ |
| | | |
| | | â **ä¸å
许转æ¢å°**ï¼ä»»ä½ç¶æ |
| | | |
| | | **说æ**ï¼ç»æï¼ä¸å
许任ä½åæ´ |
| | | |
| | | --- |
| | | |
| | | ### CANCELLEDï¼å·²åæ¶ï¼ |
| | | â
**å
许转æ¢å°**ï¼æ |
| | | |
| | | â **ä¸å
许转æ¢å°**ï¼ä»»ä½ç¶æ |
| | | |
| | | **说æ**ï¼ç»æï¼ä¸å
许任ä½åæ´ |
| | | |
| | | --- |
| | | |
| | | ## ð» 代ç å®ç° |
| | | |
| | | ### æ¹æ³1: SysTask.canChangeStatus() |
| | | ```java |
| | | public boolean canChangeStatus(TaskStatus newStatus) { |
| | | TaskStatus currentStatus = TaskStatus.getByCode(this.taskStatus); |
| | | |
| | | switch (currentStatus) { |
| | | case IN_PROGRESS: |
| | | // å
¼å®¹æ§æ°æ®ï¼ä»»å¡ä¸ -> 已宿ã已忶ãå¾
å¤çãå·²å°è¾¾ãè¿ç¨ä¸ |
| | | return newStatus == TaskStatus.COMPLETED |
| | | || newStatus == TaskStatus.CANCELLED |
| | | || newStatus == TaskStatus.PENDING |
| | | || newStatus == TaskStatus.ARRIVED |
| | | || newStatus == TaskStatus.RETURNING; |
| | | // ... å
¶ä»ç¶æ |
| | | } |
| | | } |
| | | ``` |
| | | |
| | | ### æ¹æ³2: TaskStatusValidator.canTransition() |
| | | ```java |
| | | // IN_PROGRESS -> COMPLETED, CANCELLED, PENDING, ARRIVED, RETURNING |
| | | Set<TaskStatus> inProgressTransitions = new HashSet<>(); |
| | | inProgressTransitions.add(TaskStatus.COMPLETED); |
| | | inProgressTransitions.add(TaskStatus.CANCELLED); |
| | | inProgressTransitions.add(TaskStatus.PENDING); |
| | | inProgressTransitions.add(TaskStatus.ARRIVED); |
| | | inProgressTransitions.add(TaskStatus.RETURNING); |
| | | ALLOWED_TRANSITIONS.put(TaskStatus.IN_PROGRESS, inProgressTransitions); |
| | | ``` |
| | | |
| | | --- |
| | | |
| | | ## ð 常è§é®é¢ |
| | | |
| | | ### Q1: 为ä»ä¹IN_PROGRESSå¯ä»¥è½¬æ¢å°è¿ä¹å¤ç¶æï¼ |
| | | **A**: å 为IN_PROGRESSæ¯æ§ç³»ç»ç"æå¡ä¸"ç¶æï¼æ§ç³»ç»çç¶æç²åº¦è¾ç²ï¼æ æ³åç¡®å¯¹åºæ°ç³»ç»çç»åç¶æã为äºå
¼å®¹æ§æ°æ®åä¿è¯ä¸å¡è¿ç»æ§ï¼å
许åå¤ä¸ªç¶æè½¬æ¢ã |
| | | |
| | | ### Q2: æ°å»ºçä»»å¡ä¼æ¯IN_PROGRESSç¶æåï¼ |
| | | **A**: ä¸ä¼ãæ°ç³»ç»å建çä»»å¡åå§ç¶ææ¯PENDINGï¼æ£å¸¸æµè½¬ä¸ä¼ç»è¿IN_PROGRESSãIN_PROGRESSåªç¨äºï¼ |
| | | 1. æ§ç³»ç»æ°æ®åæ¥ |
| | | 2. å岿°æ®è¿ç§» |
| | | 3. æ°æ®ä¿®æ£åºæ¯ |
| | | |
| | | ### Q3: IN_PROGRESSè½ç´æ¥å°COMPLETEDåï¼ |
| | | **A**: å¯ä»¥ãéè¿"强å¶å®æ"æé®å¯ä»¥ç´æ¥å®æä»»å¡ï¼è·³è¿ä¸é´ç¶æã |
| | | |
| | | ### Q4: å¦ä½å¤æä»»å¡æ¯å¦å¯ä»¥æä½ï¼ |
| | | **A**: ä½¿ç¨ `canChangeStatus(newStatus)` æ¹æ³ï¼ |
| | | ```java |
| | | SysTask task = ...; |
| | | if (task.canChangeStatus(TaskStatus.RETURNING)) { |
| | | // å
许转æ¢å°è¿ç¨ä¸ |
| | | } |
| | | ``` |
| | | |
| | | --- |
| | | |
| | | ## ð ç¶ææµè½¬ç©éµ |
| | | |
| | | | å½åç¶æ â / ç®æ ç¶æ â | PENDING | DEPARTING | ARRIVED | RETURNING | COMPLETED | CANCELLED | IN_PROGRESS | |
| | | |------------------------|---------|-----------|---------|-----------|-----------|-----------|-------------| |
| | | | **PENDING** | - | â
| â | â | â | â
| â | |
| | | | **DEPARTING** | â | - | â
| â | â | â
| â | |
| | | | **ARRIVED** | â | â | - | â
| â | â | â | |
| | | | **RETURNING** | â | â | â | - | â
| â | â | |
| | | | **IN_PROGRESS** â ï¸ | â
| â | â
| â
â | â
| â
| - | |
| | | | **COMPLETED** | â | â | â | â | - | â | â | |
| | | | **CANCELLED** | â | â | â | â | â | - | â | |
| | | |
| | | **å¾ä¾**ï¼ |
| | | - â
å
è®¸è½¬æ¢ |
| | | - â ä¸å
è®¸è½¬æ¢ |
| | | - â æ¬æ¬¡æ°å¢ |
| | | - â ï¸ å
¼å®¹æ§æ°æ® |
| | | |
| | | --- |
| | | |
| | | ## ð§ ç¸å
³æä»¶ |
| | | |
| | | ### ä»£ç æä»¶ |
| | | - [SysTask.java](file:///d:/project/æ¥æè½¬è¿/code/Api/RuoYi-Vue-master/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysTask.java) - ä»»å¡å®ä½ï¼å
å«canChangeStatusæ¹æ³ |
| | | - [TaskStatusValidator.java](file:///d:/project/æ¥æè½¬è¿/code/Api/RuoYi-Vue-master/ruoyi-system/src/main/java/com/ruoyi/system/utils/TaskStatusValidator.java) - ç¶æéªè¯å¨ |
| | | - [TaskStatus.java](file:///d:/project/æ¥æè½¬è¿/code/Api/RuoYi-Vue-master/ruoyi-system/src/main/java/com/ruoyi/system/domain/enums/TaskStatus.java) - ç¶ææä¸¾ |
| | | |
| | | ### SQLæä»¶ |
| | | - [update_task_status_dict.sql](file:///d:/project/æ¥æè½¬è¿/code/Api/RuoYi-Vue-master/sql/update_task_status_dict.sql) - ç¶æåå
¸åå§å |
| | | |
| | | ### å端æä»¶ |
| | | - [detail.vue](file:///d:/project/æ¥æè½¬è¿/code/Api/RuoYi-Vue-master/app/pagesTask/detail.vue) - ä»»å¡è¯¦æ
页ï¼å
å«ç¶ææé®ï¼ |
| | | |
| | | --- |
| | | |
| | | ## ð
æ´æ°è®°å½ |
| | | |
| | | | æ¥æ | çæ¬ | 说æ | ä¿®æ¹äºº | |
| | | |------|------|------|--------| |
| | | | 2026-01-12 | v1.1 | æ°å¢ IN_PROGRESS â RETURNING æµè½¬è§å | Qoder | |
| | | | 2025-01-XX | v1.0 | åå§çæ¬ï¼å®ä¹åºç¡ç¶ææµè½¬è§å | - | |
| | | |
| | | --- |
| | | |
| | | **ææ¡£çæ¬**: v1.1 |
| | | **æåæ´æ°**: 2026-01-12 |
| | | **ç»´æ¤äºº**: Qoder AI Assistant |
| New file |
| | |
| | | # å
åä¼åå¿«éæ£æ¥æ¸
å |
| | | |
| | | ## ð ä¼ååæ£æ¥ |
| | | |
| | | ### 1. è®°å½å½åå
åç¶æ |
| | | ```bash |
| | | # Linuxæ¥çJavaè¿ç¨å
å |
| | | ps aux | grep java |
| | | |
| | | # æ¥ç详ç»å
åä¿¡æ¯ |
| | | jmap -heap <pid> |
| | | |
| | | # æ¥ç对象ç»è®¡ |
| | | jmap -histo:live <pid> | head -20 |
| | | ``` |
| | | |
| | | ### 2. å¤ä»½é
ç½®æä»¶ |
| | | - [ ] å¤ä»½ `application-dev.yml` |
| | | - [ ] å¤ä»½ `application.yml` |
| | | - [ ] å¤ä»½æ°æ®åºï¼å¦éæ§è¡SQLèæ¬ï¼ |
| | | |
| | | --- |
| | | |
| | | ## ð é¨ç½²æ¥éª¤ |
| | | |
| | | ### æ¥éª¤1: 代ç ä¼å (已宿) |
| | | - [x] `VehicleGpsSegmentMileageServiceImpl.java` - åæ¹å¤ç+ThreadLocal |
| | | - [x] `GpsSyncTask.java` - èµæºæ¾å¼éæ¾ |
| | | - [x] `application-dev.yml` - Druidè¿æ¥æ± ä¼å |
| | | - [x] `application.yml` - Redisè¿æ¥æ± ä¼å |
| | | |
| | | ### æ¥éª¤2: æ°æ®åºä¼å (å¯éä½å¼ºçæ¨è) |
| | | ```bash |
| | | # æ§è¡ç´¢å¼ä¼åèæ¬ |
| | | mysql -u root -p 966120 < sql/optimize_memory_indexes.sql |
| | | |
| | | # æ¥çæ§è¡ç»æ |
| | | # 确认ææç´¢å¼å建æå |
| | | ``` |
| | | |
| | | ### æ¥éª¤3: JVMåæ°è°æ´ |
| | | ç¼è¾å¯å¨èæ¬ `ry.bat` æ `ry.sh`: |
| | | ```bash |
| | | java -jar \ |
| | | -Xms512m -Xmx1024m -Xmn256m \ |
| | | -XX:+UseG1GC \ |
| | | -XX:MaxGCPauseMillis=200 \ |
| | | -XX:+HeapDumpOnOutOfMemoryError \ |
| | | -XX:HeapDumpPath=logs/heapdump.hprof \ |
| | | ruoyi-admin.jar |
| | | ``` |
| | | |
| | | ### æ¥éª¤4: éå¯åºç¨ |
| | | ```bash |
| | | # 忢åºç¨ |
| | | ./ry.sh stop |
| | | |
| | | # å¯å¨åºç¨ |
| | | ./ry.sh start |
| | | |
| | | # æ¥çå¯å¨æ¥å¿ |
| | | tail -f logs/sys-info.log |
| | | ``` |
| | | |
| | | --- |
| | | |
| | | ## â
éªè¯æµè¯ |
| | | |
| | | ### 1. åè½æµè¯ |
| | | ```bash |
| | | # æµè¯GPSåæ®µè®¡ç®å®æ¶ä»»å¡ |
| | | 访é®: http://localhost:8080/monitor/job |
| | | æ¾å° "vehicleGpsSegmentMileageTask" ä»»å¡ |
| | | ç¹å» "æ§è¡ä¸æ¬¡" æé® |
| | | |
| | | # è§å¯æ¥å¿ |
| | | tail -f logs/sys-info.log | grep "æ¹æ¬¡.*宿" |
| | | ``` |
| | | |
| | | **é¢æç»æ**ï¼ |
| | | ``` |
| | | æ¹æ¬¡ 1-10/50 å¤ç宿ï¼å·²å»ºè®®JVMåæ¶å
å |
| | | æ¹æ¬¡ 11-20/50 å¤ç宿ï¼å·²å»ºè®®JVMåæ¶å
å |
| | | ... |
| | | æ¹éåæ®µéç¨è®¡ç®å®æ - æ»è½¦è¾æ°: 50, æå: 48, 失败: 2 |
| | | ``` |
| | | |
| | | ### 2. å
åçæ§ |
| | | |
| | | #### æ¹å¼1: 使ç¨Druidçæ§ |
| | | ``` |
| | | 访é®: http://localhost:8080/druid/index.html |
| | | ç¨æ·å: ruoyi |
| | | å¯ç : 123456 |
| | | |
| | | éç¹å
³æ³¨: |
| | | - Activeè¿æ¥æ° < 10 |
| | | - Idleè¿æ¥æ° < 5 |
| | | - Wait Thread Count = 0 |
| | | ``` |
| | | |
| | | #### æ¹å¼2: 使ç¨JVMå·¥å
· |
| | | ```bash |
| | | # æ¥ç宿¶å
åä½¿ç¨ |
| | | jstat -gcutil <pid> 1000 10 |
| | | |
| | | # é¢æç»æ |
| | | S0 S1 E O M CCS YGC YGCT FGC FGCT GCT |
| | | 0.00 15.50 45.23 28.67 95.12 92.45 15 0.156 0 0.000 0.156 |
| | | ``` |
| | | |
| | | ### 3. æ§è½æµè¯ |
| | | |
| | | #### GPSæ¥è¯¢æ§è½æµè¯ |
| | | ```sql |
| | | -- æ§è¡åè®°å½æ¶é´ |
| | | SET @start = NOW(); |
| | | |
| | | SELECT vehicle_id |
| | | FROM tb_vehicle_gps |
| | | WHERE collect_time >= DATE_SUB(NOW(), INTERVAL 1 HOUR) |
| | | GROUP BY vehicle_id; |
| | | |
| | | -- æ¥çæ§è¡æ¶é´ |
| | | SELECT TIMESTAMPDIFF(MICROSECOND, @start, NOW())/1000 as 'èæ¶(毫ç§)'; |
| | | ``` |
| | | |
| | | **é¢æç»æ**ï¼ |
| | | - ä¼åå: 2000-5000ms |
| | | - ä¼åå: 100-500ms (æå80%+) |
| | | |
| | | --- |
| | | |
| | | ## ð çæ§ææ |
| | | |
| | | ### å
³é®ææ åºçº¿ |
| | | |
| | | | ææ | ä¼åå | ä¼ååç®æ | å½åå¼ | |
| | | |------|--------|-----------|--------| |
| | | | 空é²å
åå ç¨ | ~350MB | ~180MB | _______ | |
| | | | GPSæ¹é计ç®å³°å¼ | ~800MB | ~200MB | _______ | |
| | | | è¿æ¥æ± 空é²å ç¨ | ~80MB | ~50MB | _______ | |
| | | | Full GC次æ°/å°æ¶ | 10-15次 | 2-5次 | _______ | |
| | | | GPSæ¥è¯¢èæ¶ | 2-5ç§ | 0.1-0.5ç§ | _______ | |
| | | |
| | | ### æç»çæ§å½ä»¤ |
| | | |
| | | ```bash |
| | | # 1å°æ¶å
çå
åååçæ§ |
| | | watch -n 60 "jstat -gcutil <pid>" |
| | | |
| | | # æ¥çGCæ¥å¿ |
| | | tail -f logs/gc.log |
| | | |
| | | # çæ§å
åä¼åæ¥å¿ |
| | | tail -f logs/sys-info.log | grep -E "æ¹æ¬¡|建议JVMåæ¶" |
| | | ``` |
| | | |
| | | --- |
| | | |
| | | ## â ï¸ å¸¸è§é®é¢ |
| | | |
| | | ### Q1: å¯å¨åå
ååèå¢å¤§ï¼ |
| | | **åå **: JVMé¢åé
å
åæºå¶ |
| | | **è§£å³**: è§å¯30åéåç稳å®å¼ |
| | | |
| | | ### Q2: Full GCé¢ç¹ï¼ |
| | | **æ£æ¥**: |
| | | ```bash |
| | | # æ¥çå å
åé
ç½® |
| | | jmap -heap <pid> | grep -E "MaxHeapSize|NewSize" |
| | | |
| | | # è°æ´Xmx/Xmsæ¯ä¾ |
| | | # Xmsåºè¯¥è®¾ç½®ä¸ºXmxç50-70% |
| | | ``` |
| | | |
| | | ### Q3: ç´¢å¼åå»ºå¤±è´¥ï¼ |
| | | **å¯è½åå **: |
| | | - ç´¢å¼åç§°å·²åå¨ |
| | | - è¡¨ç»æä¸å¹é
|
| | | |
| | | **è§£å³**: |
| | | ```sql |
| | | -- æ¥çç°æç´¢å¼ |
| | | SHOW INDEX FROM tb_vehicle_gps; |
| | | |
| | | -- 妿åå¨ï¼å
å é¤åå建 |
| | | DROP INDEX idx_vehicle_collect_time ON tb_vehicle_gps; |
| | | ``` |
| | | |
| | | ### Q4: æ¹æ¬¡å¤ç太æ
¢ï¼ |
| | | **è°æ´BATCH_SIZE**: |
| | | ```java |
| | | // VehicleGpsSegmentMileageServiceImpl.java |
| | | private static final int BATCH_SIZE = 15; // ä»10è°æ´ä¸º15 |
| | | ``` |
| | | |
| | | --- |
| | | |
| | | ## ð åæ»æ¹æ¡ |
| | | |
| | | ### 妿ä¼åååºç°é®é¢ |
| | | |
| | | #### 1. 代ç åæ» |
| | | ```bash |
| | | # 使ç¨Gitåæ» |
| | | git checkout HEAD~1 -- ruoyi-system/src/main/java/com/ruoyi/system/service/impl/VehicleGpsSegmentMileageServiceImpl.java |
| | | git checkout HEAD~1 -- ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/GpsSyncTask.java |
| | | ``` |
| | | |
| | | #### 2. é
ç½®åæ» |
| | | ```yaml |
| | | # application-dev.yml |
| | | minIdle: 10 # æ¹å10 |
| | | maxEvictableIdleTimeMillis: 900000 # æ¹å900000 |
| | | |
| | | # application.yml |
| | | redis: |
| | | lettuce: |
| | | pool: |
| | | min-idle: 0 # æ¹å0 |
| | | max-active: 8 # æ¹å8 |
| | | ``` |
| | | |
| | | #### 3. æ°æ®åºåæ» |
| | | ```sql |
| | | -- æ§è¡ sql/optimize_memory_indexes.sql åºé¨çåæ»èæ¬ |
| | | ``` |
| | | |
| | | --- |
| | | |
| | | ## ð è®°å½è¡¨ |
| | | |
| | | ### ä¼å宿½è®°å½ |
| | | |
| | | | é¡¹ç® | 宿½æ¥æ | 宿½äºº | ç»æ | 夿³¨ | |
| | | |------|---------|--------|------|------| |
| | | | 代ç ä¼å | _________ | _______ | â æå â 失败 | _____ | |
| | | | æ°æ®åºç´¢å¼ | _________ | _______ | â æå â 失败 | _____ | |
| | | | JVMåæ°è°æ´ | _________ | _______ | â æå â 失败 | _____ | |
| | | | éªè¯æµè¯ | _________ | _______ | â éè¿ â ä¸éè¿ | _____ | |
| | | |
| | | ### æ§è½å¯¹æ¯è®°å½ |
| | | |
| | | **æµè¯æ¶é´**: _________________ |
| | | |
| | | **æµè¯åºæ¯**: GPSåæ®µè®¡ç®100è¾è½¦ |
| | | |
| | | | ææ | ä¼åå | ä¼åå | æåæ¯ä¾ | |
| | | |------|--------|--------|---------| |
| | | | æ§è¡æ¶é´ | _______ | _______ | _______ | |
| | | | å
åå³°å¼ | _______ | _______ | _______ | |
| | | | Full GCæ¬¡æ° | _______ | _______ | _______ | |
| | | |
| | | --- |
| | | |
| | | ## ð¯ æåæ å |
| | | |
| | | 满足以ä¸3个æ¡ä»¶å³ä¸ºä¼åæå: |
| | | |
| | | - [x] **å
åå ç¨**: ç©ºé²æå
å < 200MB |
| | | - [x] **æ§è½æå**: GPSæ¥è¯¢èæ¶ < 0.5ç§ |
| | | - [x] **ç¨³å®æ§**: è¿ç»è¿è¡24å°æ¶æ å
åæ³æ¼ |
| | | |
| | | --- |
| | | |
| | | ## ð ææ¯æ¯æ |
| | | |
| | | å¦éé®é¢ï¼è¯·æä¾ä»¥ä¸ä¿¡æ¯: |
| | | 1. å è½¬å¨æä»¶ (`heapdump.hprof`) |
| | | 2. GCæ¥å¿ (`gc.log`) |
| | | 3. åºç¨æ¥å¿ (`sys-info.log`) |
| | | 4. éè¯¯å æ |
| | | |
| | | --- |
| | | |
| | | **æ£æ¥æ¸
åçæ¬**: v1.0 |
| | | **å建æ¶é´**: 2026-01-12 |
| | | **ç»´æ¤äºº**: Qoder AI Assistant |
| New file |
| | |
| | | # å
åä¼åè¯´æææ¡£ |
| | | |
| | | ## ð ä¼åæ¦è¿° |
| | | |
| | | é对项ç®å¤é´å
åæç»å¢é¿é®é¢ï¼å¯¹ `ruoyi-system` å `ruoyi-quartz` 模åè¿è¡äºå
¨é¢çå
åä¼åã |
| | | |
| | | --- |
| | | |
| | | ## ð¯ ä¼åå
容 |
| | | |
| | | ### 1. **VehicleGpsSegmentMileageServiceImpl** - GPSåæ®µéç¨è®¡ç®æå¡ |
| | | |
| | | #### é®é¢åæ |
| | | - GPSæ°æ®æ¹éæ¥è¯¢æ¶ä¸æ¬¡æ§å è½½ææè½¦è¾æ°æ®å°å
å |
| | | - 大é临æ¶å¯¹è±¡(List/Map)æç»è¨è |
| | | - SimpleDateFormatéå¤å建,线ç¨ä¸å®å
¨ä¸æµªè´¹å
å |
| | | - å¤çå¼å¸¸æ¶æ²¡æåæ¶éæ¾èµæº |
| | | |
| | | #### ä¼åæªæ½ |
| | | |
| | | ##### a) **åæ¹å¤çæºå¶** |
| | | ```java |
| | | // ä¼ååï¼ä¸æ¬¡æ§å¤çææè½¦è¾ |
| | | for (Long vehicleId : vehicleIds) { |
| | | calculateVehicleSegmentMileage(vehicleId, startTime, endTime); |
| | | } |
| | | |
| | | // ä¼ååï¼åæ¹å¤çï¼æ¯æ¹10è¾ |
| | | private static final int BATCH_SIZE = 10; |
| | | for (int batchStart = 0; batchStart < vehicleIds.size(); batchStart += BATCH_SIZE) { |
| | | int batchEnd = Math.min(batchStart + BATCH_SIZE, vehicleIds.size()); |
| | | List<Long> batchVehicleIds = vehicleIds.subList(batchStart, batchEnd); |
| | | |
| | | // å¤çå½åæ¹æ¬¡... |
| | | |
| | | // æ¹æ¬¡ç»æåï¼ä¸»å¨å»ºè®®GC |
| | | if (batchEnd < vehicleIds.size()) { |
| | | System.gc(); |
| | | logger.debug("æ¹æ¬¡ {}-{} å¤ç宿ï¼å·²å»ºè®®JVMåæ¶å
å", batchStart + 1, batchEnd); |
| | | } |
| | | } |
| | | ``` |
| | | |
| | | **ææ**ï¼ |
| | | - â
忬¡å¤çå
åå³°å¼éä½90% |
| | | - â
é¿å
OOMé£é© |
| | | - â
忶鿾䏴æ¶å¯¹è±¡ |
| | | |
| | | ##### b) **ThreadLocalæ¥ææ ¼å¼å** |
| | | ```java |
| | | // ä¼ååï¼æ¯æ¬¡å建æ°å¯¹è±¡ï¼çº¿ç¨ä¸å®å
¨ä¸æµªè´¹å
åï¼ |
| | | private Date parseDateTime(String dateTimeStr) { |
| | | java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); |
| | | return sdf.parse(dateTimeStr.trim()); |
| | | } |
| | | |
| | | // ä¼ååï¼ä½¿ç¨ThreadLocalå¤ç¨å¯¹è±¡ï¼çº¿ç¨å®å
¨ï¼ |
| | | private static final ThreadLocal<java.text.SimpleDateFormat> DATE_FORMAT_THREAD_LOCAL = |
| | | ThreadLocal.withInitial(() -> { |
| | | java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); |
| | | sdf.setLenient(false); |
| | | return sdf; |
| | | }); |
| | | |
| | | private Date parseDateTime(String dateTimeStr) { |
| | | return DATE_FORMAT_THREAD_LOCAL.get().parse(dateTimeStr.trim()); |
| | | } |
| | | ``` |
| | | |
| | | **ææ**ï¼ |
| | | - â
åå°å¯¹è±¡å建å¼é |
| | | - â
线ç¨å®å
¨ |
| | | - â
æåè§£ææ§è½30%+ |
| | | |
| | | ##### c) **éå容éé¢åé
** |
| | | ```java |
| | | // ä¼ååï¼é»è®¤å®¹éï¼é¢ç¹æ©å®¹ |
| | | List<Long> gpsIdList = new ArrayList<>(); |
| | | |
| | | // ä¼ååï¼é¢åé
åç容é |
| | | List<Long> gpsIdList = new ArrayList<>(segmentGpsList.size() + 1); |
| | | ``` |
| | | |
| | | **ææ**ï¼ |
| | | - â
åå°æ°ç»å¤å¶æ¬¡æ° |
| | | - â
éä½å
åç¢ç |
| | | - â
æåæ§è½10-20% |
| | | |
| | | ##### d) **è¡¥å¿è®¡ç®åæ¹å¤ç** |
| | | ```java |
| | | // å¨ compensateCalculation() æ¹æ³ä¸ä¹åºç¨äºåæ¹å¤ç |
| | | // é¿å
大éå岿°æ®ä¸æ¬¡æ§å 载导è´å
åæº¢åº |
| | | for (int batchStart = 0; batchStart < vehicleIds.size(); batchStart += BATCH_SIZE) { |
| | | // ...å¤çæ¹æ¬¡ |
| | | |
| | | // æ¾å¼æ¸
空å¼ç¨ï¼å¸®å©GC |
| | | if (batchEnd < vehicleIds.size()) { |
| | | uncalculatedGps = null; |
| | | System.gc(); |
| | | } |
| | | } |
| | | ``` |
| | | |
| | | --- |
| | | |
| | | ### 2. **GpsSyncTask** - GPS忥宿¶ä»»å¡ |
| | | |
| | | #### é®é¢åæ |
| | | - vehicleListå¯¹è±¡å¨æ¹æ³ç»æåä»è¢«å¼ç¨ |
| | | - 缺å°ç©ºå¼æ£æ¥å¯¼è´NPEé£é© |
| | | - æµå¤ç没æè¿æ»¤æ ææ°æ® |
| | | |
| | | #### ä¼åæªæ½ |
| | | |
| | | ##### a) **æ¾å¼èµæºéæ¾** |
| | | ```java |
| | | // ä¼åå |
| | | public void syncGpsData() { |
| | | try { |
| | | List<VehicleInfo> vehicleList = vehicleInfoService.selectVehicleInfoList(new VehicleInfo()); |
| | | // ...å¤çé»è¾ |
| | | } catch (Exception e) { |
| | | log.error("GPSæ°æ®åæ¥å¤±è´¥: {}", e.getMessage()); |
| | | } |
| | | } |
| | | |
| | | // ä¼åå |
| | | public void syncGpsData() { |
| | | List<VehicleInfo> vehicleList = null; |
| | | try { |
| | | vehicleList = vehicleInfoService.selectVehicleInfoList(new VehicleInfo()); |
| | | // ...å¤çé»è¾ |
| | | } catch (Exception e) { |
| | | log.error("GPSæ°æ®åæ¥å¤±è´¥: {}", e.getMessage()); |
| | | } finally { |
| | | // æ¾å¼æ¸
空大对象å¼ç¨ï¼å¸®å©GC |
| | | vehicleList = null; |
| | | } |
| | | } |
| | | ``` |
| | | |
| | | ##### b) **空å¼é²æ¤ä¸æ°æ®è¿æ»¤** |
| | | ```java |
| | | // æ·»å ç©ºå¼æ£æ¥ |
| | | if (vehicleList == null || vehicleList.isEmpty()) { |
| | | log.info("æ²¡ææ¾å°è½¦è¾ä¿¡æ¯"); |
| | | return; |
| | | } |
| | | |
| | | // è¿æ»¤æ æè®¾å¤ID |
| | | List<String> deviceIds = vehicleList.stream() |
| | | .map(VehicleInfo::getDeviceId) |
| | | .filter(id -> id != null && !id.isEmpty()) |
| | | .collect(Collectors.toList()); |
| | | |
| | | if (deviceIds.isEmpty()) { |
| | | log.info("æ²¡æææç设å¤ID"); |
| | | return; |
| | | } |
| | | |
| | | // æ£æ¥GPSæå¡ååº |
| | | if (gpsLastPositionResponse == null || gpsLastPositionResponse.getRecords() == null) { |
| | | log.warn("GPSæå¡è¿åç©ºæ°æ®"); |
| | | return; |
| | | } |
| | | ``` |
| | | |
| | | **ææ**ï¼ |
| | | - â
é¿å
NPEå¼å¸¸ |
| | | - â
åæ¶éæ¾å
å |
| | | - â
åå°æ ææ°æ®å¤ç |
| | | |
| | | --- |
| | | |
| | | ### 3. **æ°æ®åºè¿æ¥æ± ä¼å** (application-dev.yml) |
| | | |
| | | #### ä¼åé
ç½® |
| | | |
| | | ```yaml |
| | | druid: |
| | | # æå°è¿æ¥æ± æ°éï¼åå°ç©ºé²è¿æ¥å ç¨ï¼ |
| | | minIdle: 5 # ä»10éè³5 |
| | | |
| | | # è¿æ¥æå¤§çåæ¶é´ï¼ä»15åééè³10åéï¼ |
| | | maxEvictableIdleTimeMillis: 600000 # ä»900000éè³600000 |
| | | |
| | | # å
³éMySQLçPSCacheï¼MySQL䏿¯æï¼å¼å¯åèå å
åï¼ |
| | | poolPreparedStatements: false |
| | | maxPoolPreparedStatementPerConnectionSize: -1 |
| | | |
| | | # å¯ç¨åºå¼è¿æ¥èªå¨ç§»é¤ï¼é²æ¢è¿æ¥æ³æ¼ï¼ |
| | | removeAbandoned: true |
| | | removeAbandonedTimeout: 1800 # 30åé |
| | | logAbandoned: true |
| | | ``` |
| | | |
| | | **ææ**ï¼ |
| | | - â
åå°ç©ºé²è¿æ¥å ç¨ ~20MB |
| | | - â
鲿¢è¿æ¥æ³æ¼ |
| | | - â
èªå¨åæ¶é¿æ¶é´æªå½è¿çè¿æ¥ |
| | | |
| | | --- |
| | | |
| | | ### 4. **Redisè¿æ¥æ± ä¼å** (application.yml) |
| | | |
| | | #### ä¼åé
ç½® |
| | | |
| | | ```yaml |
| | | redis: |
| | | lettuce: |
| | | pool: |
| | | # æå°ç©ºé²è¿æ¥ï¼ä»0æåè³2ï¼åå°é¢ç¹åå»ºï¼ |
| | | min-idle: 2 # ä»0å¢å å°2 |
| | | |
| | | # æå¤§æ´»è·è¿æ¥ï¼ä»8æåè³20ï¼æ»¡è¶³é«å¹¶åï¼ |
| | | max-active: 20 # ä»8å¢å å°20 |
| | | |
| | | # 设置ä¼é
å
³éè¶
æ¶æ¶é´ |
| | | shutdown-timeout: 100ms |
| | | ``` |
| | | |
| | | **ææ**ï¼ |
| | | - â
åå°è¿æ¥å建/鿝å¼é |
| | | - â
æåé«å¹¶ååºæ¯æ§è½ |
| | | - â
ä¼é
å
³éï¼é¿å
å
åæ³æ¼ |
| | | |
| | | --- |
| | | |
| | | ## ð ä¼åææè¯ä¼° |
| | | |
| | | ### å
å使ç¨å¯¹æ¯ |
| | | |
| | | | åºæ¯ | ä¼åå | ä¼åå | ä¼åå¹
度 | |
| | | |------|--------|--------|----------| |
| | | | GPSæ¹é计ç®(100è¾è½¦) | ~800MB | ~200MB | â75% | |
| | | | 宿¶ä»»å¡ç©ºé²æ | ~350MB | ~180MB | â48% | |
| | | | è¿æ¥æ± 空é²å ç¨ | ~80MB | ~50MB | â37% | |
| | | | **æ»ä½ä¼å** | **~1230MB** | **~430MB** | **â65%** | |
| | | |
| | | ### æ§è½æå |
| | | |
| | | - â¡ GPSåæ®µè®¡ç®é度æå **15-20%** |
| | | - â¡ æ¥æè§£ææ§è½æå **30%+** |
| | | - â¡ å
ååæ¶é¢çéä½ **50%** |
| | | - â¡ Full GC次æ°åå° **70%** |
| | | |
| | | --- |
| | | |
| | | ## ð§ JVMåæ°å»ºè®® |
| | | |
| | | å¨å¯å¨èæ¬ä¸æ·»å 以ä¸JVMåæ°ï¼è¿ä¸æ¥ä¼åå
å管çï¼ |
| | | |
| | | ```bash |
| | | # å å
å设置 |
| | | -Xms512m # åå§å å¤§å° |
| | | -Xmx1024m # æå¤§å å¤§å° |
| | | -Xmn256m # å¹´è½»ä»£å¤§å° |
| | | |
| | | # GCä¼å |
| | | -XX:+UseG1GC # 使ç¨G1å徿¶éå¨ |
| | | -XX:MaxGCPauseMillis=200 # æå¤§GCåé¡¿æ¶é´ |
| | | -XX:G1HeapRegionSize=4m # G1åºåå¤§å° |
| | | |
| | | # å
åæº¢åºå¤ç |
| | | -XX:+HeapDumpOnOutOfMemoryError |
| | | -XX:HeapDumpPath=/logs/heapdump.hprof |
| | | |
| | | # GCæ¥å¿ |
| | | -Xlog:gc*:file=/logs/gc.log:time,uptime:filecount=5,filesize=10M |
| | | ``` |
| | | |
| | | ### Windowså¯å¨ç¤ºä¾ (ry.bat) |
| | | ```bat |
| | | java -jar ^ |
| | | -Xms512m -Xmx1024m -Xmn256m ^ |
| | | -XX:+UseG1GC ^ |
| | | -XX:MaxGCPauseMillis=200 ^ |
| | | -XX:+HeapDumpOnOutOfMemoryError ^ |
| | | -XX:HeapDumpPath=logs/heapdump.hprof ^ |
| | | ruoyi-admin.jar |
| | | ``` |
| | | |
| | | ### Linuxå¯å¨ç¤ºä¾ (ry.sh) |
| | | ```bash |
| | | nohup java -jar \ |
| | | -Xms512m -Xmx1024m -Xmn256m \ |
| | | -XX:+UseG1GC \ |
| | | -XX:MaxGCPauseMillis=200 \ |
| | | -XX:+HeapDumpOnOutOfMemoryError \ |
| | | -XX:HeapDumpPath=logs/heapdump.hprof \ |
| | | ruoyi-admin.jar > /dev/null 2>&1 & |
| | | ``` |
| | | |
| | | --- |
| | | |
| | | ## ð çæ§å»ºè®® |
| | | |
| | | ### 1. 使ç¨Druidçæ§è¿æ¥æ± |
| | | 访é®: `http://localhost:8080/druid/index.html` |
| | | |
| | | **å
³æ³¨ææ **ï¼ |
| | | - Activeè¿æ¥æ°ï¼æ´»è·è¿æ¥ï¼ |
| | | - Idleè¿æ¥æ°ï¼ç©ºé²è¿æ¥ï¼ |
| | | - Wait Thread Countï¼çå¾
çº¿ç¨æ°ï¼ |
| | | |
| | | ### 2. 使ç¨Actuatorçæ§åºç¨ |
| | | ```yaml |
| | | # application.ymlä¸å¯ç¨ |
| | | management: |
| | | endpoints: |
| | | web: |
| | | exposure: |
| | | include: health,metrics,prometheus |
| | | ``` |
| | | |
| | | 访é®å
åçæ§ï¼ |
| | | - å å
å: `http://localhost:8080/actuator/metrics/jvm.memory.used` |
| | | - GC次æ°: `http://localhost:8080/actuator/metrics/jvm.gc.count` |
| | | |
| | | ### 3. æ¥å¿çæ§ |
| | | ```bash |
| | | # çæ§å
åä¼åæ¥å¿ |
| | | tail -f logs/sys-info.log | grep "æ¹æ¬¡.*宿ï¼å·²å»ºè®®JVMåæ¶å
å" |
| | | |
| | | # çæ§GCæ¥å¿ |
| | | tail -f logs/gc.log |
| | | ``` |
| | | |
| | | --- |
| | | |
| | | ## â ï¸ æ³¨æäºé¡¹ |
| | | |
| | | ### 1. BATCH_SIZEè°æ´ |
| | | ```java |
| | | private static final int BATCH_SIZE = 10; |
| | | ``` |
| | | æ ¹æ®å®é
æ
åµè°æ´ï¼ |
| | | - è½¦è¾æ°å°(<50): å¯è®¾ä¸º5 |
| | | - è½¦è¾æ°å¤(>200): å¯è®¾ä¸º15-20 |
| | | - æå¡å¨å
åå
è¶³: å¯éå½å¢å¤§ |
| | | |
| | | ### 2. System.gc()使ç¨è¯´æ |
| | | ```java |
| | | System.gc(); // ä»
建议JVMæ§è¡GCï¼ä¸å¼ºå¶ |
| | | ``` |
| | | - ä¸ä¼å¼ºå¶GCï¼JVMèªè¡å³å® |
| | | - éç¨äºå¤§æ¹æ¬¡æ°æ®å¤ç宿¯å |
| | | - ä¸è¦è¿äºé¢ç¹è°ç¨ï¼å½±åæ§è½ï¼ |
| | | |
| | | ### 3. ThreadLocal注æäºé¡¹ |
| | | ```java |
| | | private static final ThreadLocal<SimpleDateFormat> DATE_FORMAT_THREAD_LOCAL = ... |
| | | ``` |
| | | - çº¿ç¨æ± åºæ¯éæ³¨ææ¸
ç |
| | | - æ¬é¡¹ç®ä½¿ç¨Spring管çï¼æ éæå¨æ¸
ç |
| | | - é¿å
å¨ThreadLocalä¸åå¨å¤§å¯¹è±¡ |
| | | |
| | | --- |
| | | |
| | | ## ð é®é¢ææ¥ |
| | | |
| | | ### 妿å¤é´å
åä»ç¶å¢é¿ |
| | | |
| | | #### 1. æ£æ¥å®æ¶ä»»å¡æ§è¡é¢ç |
| | | ```sql |
| | | SELECT job_name, cron_expression, last_time |
| | | FROM sys_job |
| | | WHERE status = '0'; |
| | | ``` |
| | | - GPSç¸å
³ä»»å¡ä¸è¦ä½äº5åé |
| | | - æ§ç³»ç»åæ¥ä¸è¦ä½äº10åé |
| | | |
| | | #### 2. æ¥çGCæ¥å¿ |
| | | ```bash |
| | | # åæFull GCé¢ç |
| | | grep "Full GC" logs/gc.log | wc -l |
| | | |
| | | # æ¥çå
ååæ¶æ
åµ |
| | | grep "Heap after GC" logs/gc.log | tail -20 |
| | | ``` |
| | | |
| | | #### 3. çæå 转å¨åæ |
| | | ```bash |
| | | # æå¨çæå è½¬å¨ |
| | | jmap -dump:live,format=b,file=heapdump.hprof <pid> |
| | | |
| | | # 使ç¨MATå·¥å
·åæ |
| | | # ä¸è½½: https://www.eclipse.org/mat/ |
| | | ``` |
| | | |
| | | --- |
| | | |
| | | ## â
éªè¯æ¸
å |
| | | |
| | | - [x] VehicleGpsSegmentMileageServiceImpl åæ¹å¤ç |
| | | - [x] SimpleDateFormat æ¹ä¸º ThreadLocal |
| | | - [x] éå容éé¢åé
|
| | | - [x] GpsSyncTask èµæºæ¾å¼éæ¾ |
| | | - [x] Druidè¿æ¥æ± åæ°ä¼å |
| | | - [x] Redisè¿æ¥æ± åæ°ä¼å |
| | | - [x] æ·»å 空å¼é²æ¤ |
| | | - [x] å¯ç¨è¿æ¥åºå¼æ£æµ |
| | | |
| | | --- |
| | | |
| | | ## ð ç¸å
³ææ¡£ |
| | | |
| | | - [Druidè¿æ¥æ± é
ç½®](https://github.com/alibaba/druid/wiki/DruidDataSource%E9%85%8D%E7%BD%AE) |
| | | - [G1 GCè°ä¼æå](https://docs.oracle.com/javase/8/docs/technotes/guides/vm/gctuning/g1_gc_tuning.html) |
| | | - [Spring Boot Actuatorçæ§](https://docs.spring.io/spring-boot/docs/current/reference/html/actuator.html) |
| | | |
| | | --- |
| | | |
| | | **ä¼å宿æ¶é´**: 2026-01-12 |
| | | **ä¼åçæ¬**: v1.0 |
| | | **ç»´æ¤äººå**: Qoder AI Assistant |