Showing
20 changed files
with
447 additions
and
16 deletions
xingyun-sc/src/main/java/com/lframework/xingyun/sc/events/quotation/CommonChangedEvent.java
renamed from
xingyun-sc/src/main/java/com/lframework/xingyun/sc/events/quotation/SalesmanQuotationPeerChangedEvent.java
| ... | ... | @@ -4,15 +4,15 @@ import lombok.Getter; |
| 4 | 4 | import org.springframework.context.ApplicationEvent; |
| 5 | 5 | |
| 6 | 6 | /** |
| 7 | - * 同行报价信息变更事件 | |
| 7 | + * 变更事件 | |
| 8 | 8 | */ |
| 9 | 9 | @Getter |
| 10 | -public class SalesmanQuotationPeerChangedEvent extends ApplicationEvent { | |
| 10 | +public class CommonChangedEvent extends ApplicationEvent { | |
| 11 | 11 | |
| 12 | 12 | private static final long serialVersionUID = 1L; |
| 13 | 13 | |
| 14 | 14 | /** |
| 15 | - * 同行报价信息ID | |
| 15 | + * 业务主键ID | |
| 16 | 16 | */ |
| 17 | 17 | private final String id; |
| 18 | 18 | |
| ... | ... | @@ -21,7 +21,7 @@ public class SalesmanQuotationPeerChangedEvent extends ApplicationEvent { |
| 21 | 21 | */ |
| 22 | 22 | private final String eventType; |
| 23 | 23 | |
| 24 | - public SalesmanQuotationPeerChangedEvent(Object source, String id, String eventType) { | |
| 24 | + public CommonChangedEvent(Object source, String id, String eventType) { | |
| 25 | 25 | super(source); |
| 26 | 26 | this.id = id; |
| 27 | 27 | this.eventType = eventType; | ... | ... |
| 1 | +package com.lframework.xingyun.sc.listeners.app; | |
| 2 | + | |
| 3 | +import com.lframework.xingyun.sc.events.quotation.CommonChangedEvent; | |
| 4 | +import com.lframework.xingyun.sc.procurement.websocket.quotation.line.SalesmanQuotationLineRealtimePushService; | |
| 5 | +import org.springframework.stereotype.Component; | |
| 6 | +import org.springframework.transaction.event.TransactionPhase; | |
| 7 | +import org.springframework.transaction.event.TransactionalEventListener; | |
| 8 | + | |
| 9 | +import javax.annotation.Resource; | |
| 10 | + | |
| 11 | +/** | |
| 12 | + * 业务员报价实时推送监听器 | |
| 13 | + */ | |
| 14 | +@Component | |
| 15 | +public class SalesmanQuotationLineRealtimeListener { | |
| 16 | + | |
| 17 | + @Resource | |
| 18 | + private SalesmanQuotationLineRealtimePushService realtimePushService; | |
| 19 | + | |
| 20 | + /** | |
| 21 | + * 业务员报价信息变更后广播当日完整数据 | |
| 22 | + * | |
| 23 | + * @param event 变更事件 | |
| 24 | + */ | |
| 25 | + @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT) | |
| 26 | + public void handleChanged(CommonChangedEvent event) { | |
| 27 | + realtimePushService.broadcastCurrentDayFullData(event.getEventType()); | |
| 28 | + } | |
| 29 | +} | ... | ... |
| 1 | 1 | package com.lframework.xingyun.sc.listeners.app; |
| 2 | 2 | |
| 3 | -import com.lframework.xingyun.sc.events.quotation.SalesmanQuotationPeerChangedEvent; | |
| 4 | -import com.lframework.xingyun.sc.procurement.websocket.quotation.SalesmanQuotationPeerRealtimePushService; | |
| 3 | +import com.lframework.xingyun.sc.events.quotation.CommonChangedEvent; | |
| 4 | +import com.lframework.xingyun.sc.procurement.websocket.quotation.peer.SalesmanQuotationPeerRealtimePushService; | |
| 5 | 5 | import javax.annotation.Resource; |
| 6 | 6 | import org.springframework.stereotype.Component; |
| 7 | 7 | import org.springframework.transaction.event.TransactionPhase; |
| ... | ... | @@ -22,7 +22,7 @@ public class SalesmanQuotationPeerRealtimeListener { |
| 22 | 22 | * @param event 变更事件 |
| 23 | 23 | */ |
| 24 | 24 | @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT) |
| 25 | - public void handleChanged(SalesmanQuotationPeerChangedEvent event) { | |
| 25 | + public void handleChanged(CommonChangedEvent event) { | |
| 26 | 26 | realtimePushService.broadcastCurrentDayFullData(event.getEventType()); |
| 27 | 27 | } |
| 28 | 28 | } | ... | ... |
| 1 | +package com.lframework.xingyun.sc.procurement.dto.quotation; | |
| 2 | + | |
| 3 | +import com.lframework.xingyun.sc.procurement.entity.SalesmanQuotationLine; | |
| 4 | +import lombok.Data; | |
| 5 | + | |
| 6 | +import java.io.Serializable; | |
| 7 | +import java.time.LocalDate; | |
| 8 | +import java.time.LocalDateTime; | |
| 9 | +import java.util.List; | |
| 10 | + | |
| 11 | +/** | |
| 12 | + * 业务员报价实时推送消息 | |
| 13 | + */ | |
| 14 | +@Data | |
| 15 | +public class QuotationLineRealtimeMessage implements Serializable { | |
| 16 | + | |
| 17 | + private static final long serialVersionUID = 1L; | |
| 18 | + | |
| 19 | + /** | |
| 20 | + * 消息类型 | |
| 21 | + */ | |
| 22 | + private String messageType; | |
| 23 | + | |
| 24 | + /** | |
| 25 | + * 事件类型 | |
| 26 | + */ | |
| 27 | + private String eventType; | |
| 28 | + | |
| 29 | + /** | |
| 30 | + * 业务日期 | |
| 31 | + */ | |
| 32 | + private LocalDate businessDate; | |
| 33 | + | |
| 34 | + /** | |
| 35 | + * 推送时间 | |
| 36 | + */ | |
| 37 | + private LocalDateTime pushTime; | |
| 38 | + | |
| 39 | + /** | |
| 40 | + * 数据列表 | |
| 41 | + */ | |
| 42 | + private List<SalesmanQuotationLine> records; | |
| 43 | +} | ... | ... |
| ... | ... | @@ -90,6 +90,24 @@ public class SalesmanQuotationLine extends BaseEntity implements BaseDto { |
| 90 | 90 | private String itemId; |
| 91 | 91 | |
| 92 | 92 | /** |
| 93 | + * 报价时间 | |
| 94 | + */ | |
| 95 | + @TableField(exist = false) | |
| 96 | + private String quoteTime; | |
| 97 | + | |
| 98 | + /** | |
| 99 | + * 业务员 | |
| 100 | + */ | |
| 101 | + @TableField(exist = false) | |
| 102 | + private String quoterName; | |
| 103 | + | |
| 104 | + /** | |
| 105 | + * 供应商名称 | |
| 106 | + */ | |
| 107 | + @TableField(exist = false) | |
| 108 | + private String supplierName; | |
| 109 | + | |
| 110 | + /** | |
| 93 | 111 | * 创建人ID |
| 94 | 112 | */ |
| 95 | 113 | @TableField(fill = FieldFill.INSERT) | ... | ... |
| ... | ... | @@ -16,6 +16,7 @@ import com.lframework.xingyun.sc.procurement.vo.quotation.CreateSalesmanQuotatio |
| 16 | 16 | import com.lframework.xingyun.sc.procurement.vo.quotation.QuerySalesmanQuotationLineVo; |
| 17 | 17 | import com.lframework.xingyun.sc.procurement.vo.quotation.UpdateSalesmanQuotationLineVo; |
| 18 | 18 | import java.io.Serializable; |
| 19 | +import java.time.LocalDate; | |
| 19 | 20 | import java.util.List; |
| 20 | 21 | import org.apache.commons.lang3.StringUtils; |
| 21 | 22 | import org.springframework.stereotype.Service; |
| ... | ... | @@ -41,6 +42,17 @@ public class SalesmanQuotationLineServiceImpl |
| 41 | 42 | } |
| 42 | 43 | |
| 43 | 44 | /** |
| 45 | + * 查询指定日期创建的业务员报价明细 | |
| 46 | + * | |
| 47 | + * @param day 日期 | |
| 48 | + * @return 业务员报价明细列表 | |
| 49 | + */ | |
| 50 | + @Override | |
| 51 | + public List<SalesmanQuotationLine> queryCurrentDayList(LocalDate day) { | |
| 52 | + return getBaseMapper().queryCurrentDayList(day); | |
| 53 | + } | |
| 54 | + | |
| 55 | + /** | |
| 44 | 56 | * 根据ID查询 |
| 45 | 57 | * |
| 46 | 58 | * @param id 主键ID | ... | ... |
| ... | ... | @@ -16,7 +16,7 @@ import com.lframework.starter.web.core.utils.PageResultUtil; |
| 16 | 16 | import com.lframework.starter.web.inner.components.oplog.OtherOpLogType; |
| 17 | 17 | import com.lframework.xingyun.basedata.entity.BreedRelationship; |
| 18 | 18 | import com.lframework.xingyun.basedata.service.breed.BreedRelationshipService; |
| 19 | -import com.lframework.xingyun.sc.events.quotation.SalesmanQuotationPeerChangedEvent; | |
| 19 | +import com.lframework.xingyun.sc.events.quotation.CommonChangedEvent; | |
| 20 | 20 | import com.lframework.xingyun.sc.procurement.entity.SalesmanQuotationPeer; |
| 21 | 21 | import com.lframework.xingyun.sc.procurement.mappers.quotation.SalesmanQuotationPeerMapper; |
| 22 | 22 | import com.lframework.xingyun.sc.procurement.service.quotation.SalesmanQuotationPeerService; |
| ... | ... | @@ -183,6 +183,6 @@ public class SalesmanQuotationPeerServiceImpl |
| 183 | 183 | * @param eventType 事件类型 |
| 184 | 184 | */ |
| 185 | 185 | private void publishChangedEvent(String id, String eventType) { |
| 186 | - applicationEventPublisher.publishEvent(new SalesmanQuotationPeerChangedEvent(this, id, eventType)); | |
| 186 | + applicationEventPublisher.publishEvent(new CommonChangedEvent(this, id, eventType)); | |
| 187 | 187 | } |
| 188 | 188 | } | ... | ... |
| ... | ... | @@ -29,6 +29,7 @@ import com.lframework.starter.web.inner.service.system.SysUserService; |
| 29 | 29 | import com.lframework.xingyun.basedata.entity.BreedRelationship; |
| 30 | 30 | import com.lframework.xingyun.basedata.service.breed.BreedRelationshipService; |
| 31 | 31 | import com.lframework.xingyun.sc.enums.CustomerDevelopStatus; |
| 32 | +import com.lframework.xingyun.sc.events.quotation.CommonChangedEvent; | |
| 32 | 33 | import com.lframework.xingyun.sc.procurement.entity.ProcurementDomesticCustomerCredit; |
| 33 | 34 | import com.lframework.xingyun.sc.procurement.entity.SalesmanQuotation; |
| 34 | 35 | import com.lframework.xingyun.sc.procurement.entity.SalesmanQuotationLine; |
| ... | ... | @@ -57,6 +58,7 @@ import java.util.Objects; |
| 57 | 58 | import java.util.Set; |
| 58 | 59 | import java.util.stream.Collectors; |
| 59 | 60 | import org.apache.commons.lang3.StringUtils; |
| 61 | +import org.springframework.context.ApplicationEventPublisher; | |
| 60 | 62 | import org.springframework.stereotype.Service; |
| 61 | 63 | import org.springframework.transaction.annotation.Transactional; |
| 62 | 64 | import javax.annotation.Resource; |
| ... | ... | @@ -88,6 +90,8 @@ public class SalesmanQuotationServiceImpl |
| 88 | 90 | private SalesmanQuotationLineService salesmanQuotationLineService; |
| 89 | 91 | @Resource |
| 90 | 92 | private SysRoleService sysRoleService; |
| 93 | + @Resource | |
| 94 | + private ApplicationEventPublisher applicationEventPublisher; | |
| 91 | 95 | |
| 92 | 96 | /** |
| 93 | 97 | * 编号前缀 |
| ... | ... | @@ -304,6 +308,7 @@ public class SalesmanQuotationServiceImpl |
| 304 | 308 | .set(SalesmanQuotation::getStatus, "QUOTED") |
| 305 | 309 | .eq(SalesmanQuotation::getId, id); |
| 306 | 310 | getBaseMapper().update(wrapper); |
| 311 | + publishChangedEvent(id, "CREATE"); | |
| 307 | 312 | } else { |
| 308 | 313 | Wrapper<SalesmanQuotation> wrapper = Wrappers.lambdaUpdate(SalesmanQuotation.class) |
| 309 | 314 | .set(SalesmanQuotation::getApprovalStatus, approvalStatus) |
| ... | ... | @@ -730,6 +735,17 @@ public class SalesmanQuotationServiceImpl |
| 730 | 735 | } |
| 731 | 736 | } |
| 732 | 737 | |
| 738 | + | |
| 739 | + /** | |
| 740 | + * 发布业务员报价信息变更事件 | |
| 741 | + * | |
| 742 | + * @param id 主键ID | |
| 743 | + * @param eventType 事件类型 | |
| 744 | + */ | |
| 745 | + private void publishChangedEvent(String id, String eventType) { | |
| 746 | + applicationEventPublisher.publishEvent(new CommonChangedEvent(this, id, eventType)); | |
| 747 | + } | |
| 748 | + | |
| 733 | 749 | /** |
| 734 | 750 | * 清理缓存 |
| 735 | 751 | * | ... | ... |
| ... | ... | @@ -3,6 +3,7 @@ package com.lframework.xingyun.sc.procurement.mappers.quotation; |
| 3 | 3 | import com.lframework.starter.web.core.mapper.BaseMapper; |
| 4 | 4 | import com.lframework.xingyun.sc.procurement.entity.SalesmanQuotationLine; |
| 5 | 5 | import com.lframework.xingyun.sc.procurement.vo.quotation.QuerySalesmanQuotationLineVo; |
| 6 | +import java.time.LocalDate; | |
| 6 | 7 | import java.util.List; |
| 7 | 8 | import org.apache.ibatis.annotations.Param; |
| 8 | 9 | |
| ... | ... | @@ -18,4 +19,12 @@ public interface SalesmanQuotationLineMapper extends BaseMapper<SalesmanQuotatio |
| 18 | 19 | * @return 明细列表 |
| 19 | 20 | */ |
| 20 | 21 | List<SalesmanQuotationLine> query(@Param("vo") QuerySalesmanQuotationLineVo vo); |
| 22 | + | |
| 23 | + /** | |
| 24 | + * 查询指定日期创建的业务员报价明细 | |
| 25 | + * | |
| 26 | + * @param day 日期 | |
| 27 | + * @return 业务员报价明细表列表 | |
| 28 | + */ | |
| 29 | + List<SalesmanQuotationLine> queryCurrentDayList(@Param("day") LocalDate day); | |
| 21 | 30 | } | ... | ... |
| ... | ... | @@ -5,6 +5,7 @@ import com.lframework.xingyun.sc.procurement.entity.SalesmanQuotationLine; |
| 5 | 5 | import com.lframework.xingyun.sc.procurement.vo.quotation.CreateSalesmanQuotationLineVo; |
| 6 | 6 | import com.lframework.xingyun.sc.procurement.vo.quotation.QuerySalesmanQuotationLineVo; |
| 7 | 7 | import com.lframework.xingyun.sc.procurement.vo.quotation.UpdateSalesmanQuotationLineVo; |
| 8 | +import java.time.LocalDate; | |
| 8 | 9 | import java.util.List; |
| 9 | 10 | |
| 10 | 11 | /** |
| ... | ... | @@ -21,6 +22,14 @@ public interface SalesmanQuotationLineService extends BaseMpService<SalesmanQuot |
| 21 | 22 | List<SalesmanQuotationLine> query(QuerySalesmanQuotationLineVo vo); |
| 22 | 23 | |
| 23 | 24 | /** |
| 25 | + * 查询指定日期创建的业务员报价明细 | |
| 26 | + * | |
| 27 | + * @param day 日期 | |
| 28 | + * @return 业务员报价明细列表 | |
| 29 | + */ | |
| 30 | + List<SalesmanQuotationLine> queryCurrentDayList(LocalDate day); | |
| 31 | + | |
| 32 | + /** | |
| 24 | 33 | * 根据ID查询 |
| 25 | 34 | * |
| 26 | 35 | * @param id 主键ID | ... | ... |
xingyun-sc/src/main/java/com/lframework/xingyun/sc/procurement/websocket/quotation/CommonWebSocketAuthService.java
renamed from
xingyun-sc/src/main/java/com/lframework/xingyun/sc/procurement/websocket/quotation/SalesmanQuotationPeerWebSocketAuthService.java
| ... | ... | @@ -8,10 +8,10 @@ import javax.annotation.Resource; |
| 8 | 8 | import org.springframework.stereotype.Service; |
| 9 | 9 | |
| 10 | 10 | /** |
| 11 | - * 同行报价信息 WebSocket 鉴权服务 | |
| 11 | + * WebSocket 鉴权服务 | |
| 12 | 12 | */ |
| 13 | 13 | @Service |
| 14 | -public class SalesmanQuotationPeerWebSocketAuthService { | |
| 14 | +public class CommonWebSocketAuthService { | |
| 15 | 15 | |
| 16 | 16 | @Resource |
| 17 | 17 | private SysUserService sysUserService; | ... | ... |
| 1 | +package com.lframework.xingyun.sc.procurement.websocket.quotation.line; | |
| 2 | + | |
| 3 | +import com.lframework.starter.web.core.utils.JsonUtil; | |
| 4 | +import com.lframework.xingyun.sc.procurement.dto.quotation.QuotationLineRealtimeMessage; | |
| 5 | +import com.lframework.xingyun.sc.procurement.entity.SalesmanQuotationLine; | |
| 6 | +import com.lframework.xingyun.sc.procurement.service.quotation.SalesmanQuotationLineService; | |
| 7 | +import lombok.extern.slf4j.Slf4j; | |
| 8 | +import org.springframework.stereotype.Service; | |
| 9 | +import org.springframework.web.socket.TextMessage; | |
| 10 | +import org.springframework.web.socket.WebSocketSession; | |
| 11 | +import javax.annotation.Resource; | |
| 12 | +import java.io.IOException; | |
| 13 | +import java.time.LocalDate; | |
| 14 | +import java.time.LocalDateTime; | |
| 15 | +import java.util.List; | |
| 16 | +import java.util.Map; | |
| 17 | +import java.util.concurrent.ConcurrentHashMap; | |
| 18 | + | |
| 19 | +/** | |
| 20 | + * 业务员报价信息实时推送服务 | |
| 21 | + */ | |
| 22 | +@Slf4j | |
| 23 | +@Service | |
| 24 | +public class SalesmanQuotationLineRealtimePushService { | |
| 25 | + | |
| 26 | + /** | |
| 27 | + * 当前在线连接 | |
| 28 | + */ | |
| 29 | + private final Map<String, WebSocketSession> sessionMap = new ConcurrentHashMap<>(); | |
| 30 | + | |
| 31 | + @Resource | |
| 32 | + private SalesmanQuotationLineService salesmanQuotationLineService; | |
| 33 | + | |
| 34 | + /** | |
| 35 | + * 注册连接 | |
| 36 | + * | |
| 37 | + * @param session WebSocket 会话 | |
| 38 | + */ | |
| 39 | + public void register(WebSocketSession session) { | |
| 40 | + sessionMap.put(session.getId(), session); | |
| 41 | + } | |
| 42 | + | |
| 43 | + /** | |
| 44 | + * 注销连接 | |
| 45 | + * | |
| 46 | + * @param session WebSocket 会话 | |
| 47 | + */ | |
| 48 | + public void unregister(WebSocketSession session) { | |
| 49 | + if (session != null) { | |
| 50 | + sessionMap.remove(session.getId()); | |
| 51 | + } | |
| 52 | + } | |
| 53 | + | |
| 54 | + /** | |
| 55 | + * 广播当日完整业务员报价数据 | |
| 56 | + * | |
| 57 | + * @param eventType 事件类型 | |
| 58 | + */ | |
| 59 | + public void broadcastCurrentDayFullData(String eventType) { | |
| 60 | + if (sessionMap.isEmpty()) { | |
| 61 | + return; | |
| 62 | + } | |
| 63 | + | |
| 64 | + QuotationLineRealtimeMessage message = buildCurrentDayMessage(eventType); | |
| 65 | + String payload = JsonUtil.toJsonString(message); | |
| 66 | + for (WebSocketSession session : sessionMap.values()) { | |
| 67 | + sendMessage(session, payload); | |
| 68 | + } | |
| 69 | + } | |
| 70 | + | |
| 71 | + /** | |
| 72 | + * 向单个连接补推当日完整数据 | |
| 73 | + * | |
| 74 | + * @param session WebSocket 会话 | |
| 75 | + * @param eventType 事件类型 | |
| 76 | + */ | |
| 77 | + public void replayCurrentDayFullData(WebSocketSession session, String eventType) { | |
| 78 | + if (session == null) { | |
| 79 | + return; | |
| 80 | + } | |
| 81 | + sendMessage(session, JsonUtil.toJsonString(buildCurrentDayMessage(eventType))); | |
| 82 | + } | |
| 83 | + | |
| 84 | + /** | |
| 85 | + * 构建当日完整数据消息 | |
| 86 | + * | |
| 87 | + * @param eventType 事件类型 | |
| 88 | + * @return 推送消息 | |
| 89 | + */ | |
| 90 | + private QuotationLineRealtimeMessage buildCurrentDayMessage(String eventType) { | |
| 91 | + LocalDate today = LocalDate.now(); | |
| 92 | + List<SalesmanQuotationLine> records = salesmanQuotationLineService.queryCurrentDayList(today); | |
| 93 | + | |
| 94 | + QuotationLineRealtimeMessage message = new QuotationLineRealtimeMessage(); | |
| 95 | + message.setMessageType("FULL_SYNC"); | |
| 96 | + message.setEventType(eventType); | |
| 97 | + message.setBusinessDate(today); | |
| 98 | + message.setPushTime(LocalDateTime.now()); | |
| 99 | + message.setRecords(records); | |
| 100 | + return message; | |
| 101 | + } | |
| 102 | + | |
| 103 | + /** | |
| 104 | + * 发送消息 | |
| 105 | + * | |
| 106 | + * @param session WebSocket 会话 | |
| 107 | + * @param payload 消息体 | |
| 108 | + */ | |
| 109 | + private void sendMessage(WebSocketSession session, String payload) { | |
| 110 | + if (session == null || !session.isOpen()) { | |
| 111 | + unregister(session); | |
| 112 | + return; | |
| 113 | + } | |
| 114 | + | |
| 115 | + try { | |
| 116 | + synchronized (session) { | |
| 117 | + session.sendMessage(new TextMessage(payload)); | |
| 118 | + } | |
| 119 | + } catch (IOException e) { | |
| 120 | + log.warn("业务员报价信息实时推送失败,sessionId={}", session.getId(), e); | |
| 121 | + unregister(session); | |
| 122 | + } | |
| 123 | + } | |
| 124 | +} | ... | ... |
| 1 | +package com.lframework.xingyun.sc.procurement.websocket.quotation.line; | |
| 2 | + | |
| 3 | +import org.springframework.context.annotation.Configuration; | |
| 4 | +import org.springframework.web.socket.config.annotation.EnableWebSocket; | |
| 5 | +import org.springframework.web.socket.config.annotation.WebSocketConfigurer; | |
| 6 | +import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry; | |
| 7 | + | |
| 8 | +import javax.annotation.Resource; | |
| 9 | + | |
| 10 | +/** | |
| 11 | + * 业务员报价 WebSocket 配置 | |
| 12 | + */ | |
| 13 | +@Configuration | |
| 14 | +@EnableWebSocket | |
| 15 | +public class SalesmanQuotationLineWebSocketConfig implements WebSocketConfigurer { | |
| 16 | + | |
| 17 | + // 添加这段代码 | |
| 18 | + static { | |
| 19 | + System.out.println("========== WebSocket配置类正在加载 =========="); | |
| 20 | + } | |
| 21 | + | |
| 22 | + /** | |
| 23 | + * WebSocket 路径 | |
| 24 | + */ | |
| 25 | + public static final String ENDPOINT = "/ws/procurement/salesmanQuotationLine/realtime"; | |
| 26 | + | |
| 27 | + @Resource | |
| 28 | + private SalesmanQuotationLineWebSocketHandler webSocketHandler; | |
| 29 | + @Resource | |
| 30 | + private SalesmanQuotationLineWebSocketHandshakeInterceptor handshakeInterceptor; | |
| 31 | + | |
| 32 | + @Override | |
| 33 | + public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { | |
| 34 | + System.out.println("========== 正在注册 WebSocket 路径 =========="); | |
| 35 | + registry.addHandler(webSocketHandler, ENDPOINT) | |
| 36 | + .addInterceptors(handshakeInterceptor) | |
| 37 | + .setAllowedOrigins("*"); | |
| 38 | + } | |
| 39 | +} | ... | ... |
| 1 | +package com.lframework.xingyun.sc.procurement.websocket.quotation.line; | |
| 2 | + | |
| 3 | +import lombok.extern.slf4j.Slf4j; | |
| 4 | +import org.apache.commons.lang3.StringUtils; | |
| 5 | +import org.springframework.stereotype.Component; | |
| 6 | +import org.springframework.web.socket.CloseStatus; | |
| 7 | +import org.springframework.web.socket.TextMessage; | |
| 8 | +import org.springframework.web.socket.WebSocketSession; | |
| 9 | +import org.springframework.web.socket.handler.TextWebSocketHandler; | |
| 10 | + | |
| 11 | +import javax.annotation.Resource; | |
| 12 | + | |
| 13 | +/** | |
| 14 | + * 业务员报价 WebSocket 处理器 | |
| 15 | + */ | |
| 16 | +@Slf4j | |
| 17 | +@Component | |
| 18 | +public class SalesmanQuotationLineWebSocketHandler extends TextWebSocketHandler { | |
| 19 | + | |
| 20 | + @Resource | |
| 21 | + private SalesmanQuotationLineRealtimePushService realtimePushService; | |
| 22 | + | |
| 23 | + @Override | |
| 24 | + public void afterConnectionEstablished(WebSocketSession session) { | |
| 25 | + realtimePushService.register(session); | |
| 26 | + realtimePushService.replayCurrentDayFullData(session, "INIT"); | |
| 27 | + } | |
| 28 | + | |
| 29 | + @Override | |
| 30 | + protected void handleTextMessage(WebSocketSession session, TextMessage message) { | |
| 31 | + String payload = StringUtils.trimToEmpty(message.getPayload()); | |
| 32 | + if ("SYNC_TODAY".equalsIgnoreCase(payload) || "RESYNC".equalsIgnoreCase(payload)) { | |
| 33 | + realtimePushService.replayCurrentDayFullData(session, "RESYNC"); | |
| 34 | + } | |
| 35 | + } | |
| 36 | + | |
| 37 | + @Override | |
| 38 | + public void afterConnectionClosed(WebSocketSession session, CloseStatus status) { | |
| 39 | + realtimePushService.unregister(session); | |
| 40 | + } | |
| 41 | + | |
| 42 | + @Override | |
| 43 | + public void handleTransportError(WebSocketSession session, Throwable exception) { | |
| 44 | + log.warn("业务员报价 WebSocket 连接异常,sessionId={}", session.getId(), exception); | |
| 45 | + realtimePushService.unregister(session); | |
| 46 | + } | |
| 47 | +} | ... | ... |
| 1 | +package com.lframework.xingyun.sc.procurement.websocket.quotation.line; | |
| 2 | + | |
| 3 | +import com.lframework.starter.web.inner.entity.SysUser; | |
| 4 | +import com.lframework.xingyun.sc.procurement.websocket.quotation.CommonWebSocketAuthService; | |
| 5 | +import org.springframework.http.HttpStatus; | |
| 6 | +import org.springframework.http.server.ServerHttpRequest; | |
| 7 | +import org.springframework.http.server.ServerHttpResponse; | |
| 8 | +import org.springframework.stereotype.Component; | |
| 9 | +import org.springframework.web.socket.WebSocketHandler; | |
| 10 | +import org.springframework.web.socket.server.HandshakeInterceptor; | |
| 11 | + | |
| 12 | +import javax.annotation.Resource; | |
| 13 | +import java.util.Map; | |
| 14 | + | |
| 15 | +/** | |
| 16 | + * 业务员报价 WebSocket 握手鉴权拦截器 | |
| 17 | + */ | |
| 18 | +@Component | |
| 19 | +public class SalesmanQuotationLineWebSocketHandshakeInterceptor implements HandshakeInterceptor { | |
| 20 | + | |
| 21 | + /** | |
| 22 | + * 用户ID属性名 | |
| 23 | + */ | |
| 24 | + public static final String ATTR_USER_ID = "userId"; | |
| 25 | + | |
| 26 | + /** | |
| 27 | + * 用户名称属性名 | |
| 28 | + */ | |
| 29 | + public static final String ATTR_USER_NAME = "userName"; | |
| 30 | + | |
| 31 | + @Resource | |
| 32 | + private CommonWebSocketAuthService authService; | |
| 33 | + | |
| 34 | + @Override | |
| 35 | + public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, | |
| 36 | + WebSocketHandler wsHandler, Map<String, Object> attributes) { | |
| 37 | + try { | |
| 38 | + SysUser user = authService.authenticateCurrentUser(); | |
| 39 | + attributes.put(ATTR_USER_ID, user.getId()); | |
| 40 | + attributes.put(ATTR_USER_NAME, user.getName()); | |
| 41 | + return true; | |
| 42 | + } catch (Exception e) { | |
| 43 | + response.setStatusCode(HttpStatus.FORBIDDEN); | |
| 44 | + return false; | |
| 45 | + } | |
| 46 | + } | |
| 47 | + | |
| 48 | + @Override | |
| 49 | + public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, | |
| 50 | + WebSocketHandler wsHandler, Exception exception) { | |
| 51 | + } | |
| 52 | +} | ... | ... |
xingyun-sc/src/main/java/com/lframework/xingyun/sc/procurement/websocket/quotation/peer/SalesmanQuotationPeerRealtimePushService.java
renamed from
xingyun-sc/src/main/java/com/lframework/xingyun/sc/procurement/websocket/quotation/SalesmanQuotationPeerRealtimePushService.java
| 1 | -package com.lframework.xingyun.sc.procurement.websocket.quotation; | |
| 1 | +package com.lframework.xingyun.sc.procurement.websocket.quotation.peer; | |
| 2 | 2 | |
| 3 | 3 | import com.lframework.starter.web.core.utils.JsonUtil; |
| 4 | 4 | import com.lframework.xingyun.sc.procurement.dto.quotation.PeerQuotationRealtimeMessage; | ... | ... |
xingyun-sc/src/main/java/com/lframework/xingyun/sc/procurement/websocket/quotation/peer/SalesmanQuotationPeerWebSocketConfig.java
renamed from
xingyun-sc/src/main/java/com/lframework/xingyun/sc/procurement/websocket/quotation/SalesmanQuotationPeerWebSocketConfig.java
xingyun-sc/src/main/java/com/lframework/xingyun/sc/procurement/websocket/quotation/peer/SalesmanQuotationPeerWebSocketHandler.java
renamed from
xingyun-sc/src/main/java/com/lframework/xingyun/sc/procurement/websocket/quotation/SalesmanQuotationPeerWebSocketHandler.java
xingyun-sc/src/main/java/com/lframework/xingyun/sc/procurement/websocket/quotation/peer/SalesmanQuotationPeerWebSocketHandshakeInterceptor.java
renamed from
xingyun-sc/src/main/java/com/lframework/xingyun/sc/procurement/websocket/quotation/SalesmanQuotationPeerWebSocketHandshakeInterceptor.java
| 1 | -package com.lframework.xingyun.sc.procurement.websocket.quotation; | |
| 1 | +package com.lframework.xingyun.sc.procurement.websocket.quotation.peer; | |
| 2 | 2 | |
| 3 | 3 | import com.lframework.starter.web.inner.entity.SysUser; |
| 4 | 4 | import java.util.Map; |
| 5 | 5 | import javax.annotation.Resource; |
| 6 | + | |
| 7 | +import com.lframework.xingyun.sc.procurement.websocket.quotation.CommonWebSocketAuthService; | |
| 6 | 8 | import org.springframework.http.HttpStatus; |
| 7 | 9 | import org.springframework.http.server.ServerHttpRequest; |
| 8 | 10 | import org.springframework.http.server.ServerHttpResponse; |
| ... | ... | @@ -27,7 +29,7 @@ public class SalesmanQuotationPeerWebSocketHandshakeInterceptor implements Hands |
| 27 | 29 | public static final String ATTR_USER_NAME = "userName"; |
| 28 | 30 | |
| 29 | 31 | @Resource |
| 30 | - private SalesmanQuotationPeerWebSocketAuthService authService; | |
| 32 | + private CommonWebSocketAuthService authService; | |
| 31 | 33 | |
| 32 | 34 | @Override |
| 33 | 35 | public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, | ... | ... |
| ... | ... | @@ -16,6 +16,9 @@ |
| 16 | 16 | <result column="estimated_loss" property="estimatedLoss"/> |
| 17 | 17 | <result column="application_attrition" property="applicationAttrition"/> |
| 18 | 18 | <result column="item_id" property="itemId"/> |
| 19 | + <result column="quote_time" property="quoteTime"/> | |
| 20 | + <result column="quoter_name" property="quoterName"/> | |
| 21 | + <result column="supplier_name" property="supplierName"/> | |
| 19 | 22 | <result column="create_by_id" property="createById"/> |
| 20 | 23 | <result column="create_by" property="createBy"/> |
| 21 | 24 | <result column="update_by_id" property="updateById"/> |
| ... | ... | @@ -58,4 +61,32 @@ |
| 58 | 61 | </where> |
| 59 | 62 | ORDER BY tb.create_time ASC |
| 60 | 63 | </select> |
| 64 | + | |
| 65 | + <sql id="SalesmanQuotationLineSql1"> | |
| 66 | + SELECT | |
| 67 | + tb.id, | |
| 68 | + tb.quotation_id, | |
| 69 | + sq.quote_time, | |
| 70 | + sq.quoter_name, | |
| 71 | + pdc.unit_name AS supplier_name, | |
| 72 | + br.product_name, | |
| 73 | + tb.quantity, | |
| 74 | + tb.purchase_price, | |
| 75 | + tb.create_by_id, | |
| 76 | + tb.create_by, | |
| 77 | + tb.update_by_id, | |
| 78 | + tb.update_by, | |
| 79 | + tb.create_time, | |
| 80 | + tb.update_time | |
| 81 | + FROM procurement_salesman_quotation_line tb | |
| 82 | + LEFT JOIN base_data_breed_relationship br ON br.id = tb.product_id | |
| 83 | + LEFT JOIN procurement_salesman_quotation sq on sq.id=tb.quotation_id | |
| 84 | + LEFT JOIN procurement_domestic_customer_credit pdc ON pdc.id = sq.supplier_id | |
| 85 | + </sql> | |
| 86 | + | |
| 87 | + <select id="queryCurrentDayList" resultMap="SalesmanQuotationLine"> | |
| 88 | + <include refid="SalesmanQuotationLineSql1"/> | |
| 89 | + WHERE DATE(sq.create_time) = #{day} and sq.status='QUOTED' | |
| 90 | + ORDER BY tb.create_time DESC, tb.quotation_id DESC | |
| 91 | + </select> | |
| 61 | 92 | </mapper> | ... | ... |