Merge branch 'master' into cc_20251010_wxnotice

# Conflicts:
#	coolstore-partner-service/src/main/java/com/cool/store/service/impl/MessageTemplateServiceImpl.java
This commit is contained in:
苏竹红
2025-10-29 19:44:14 +08:00
71 changed files with 1551 additions and 71 deletions

View File

@@ -40,4 +40,16 @@ public class PartnerWebApplication {
return defaultDataSourceProperties().initializeDataSourceBuilder().type(HikariDataSource.class).build();
}
@Bean
@ConfigurationProperties("platform.datasource")
public DataSourceProperties platformDataSourceProperties() {
return new DataSourceProperties();
}
@Bean
@ConfigurationProperties("spring.datasource.hikari")
public DataSource platformDataSource() {
return platformDataSourceProperties().initializeDataSourceBuilder().type(HikariDataSource.class).build();
}
}

View File

@@ -0,0 +1,37 @@
package com.cool.store.aspect;
import com.cool.store.annotation.PlatformDB;
import com.cool.store.datasource.DataSourceContextHolder;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
/**
* <p>
* 数据源切换 切面
* </p>
*
* @author wangff
* @since 2025/9/4
*/
@Aspect
@Component
public class DataSourceAspect {
@Before("@annotation(platformDB)")
public void before(PlatformDB platformDB) {
DataSourceContextHolder.setDataSourceType("platform");
}
@After("@annotation(platformDB)")
public void after(PlatformDB platformDB) {
DataSourceContextHolder.clearDataSourceType();
}
@AfterThrowing("@annotation(platformDB)")
public void afterThrowing(PlatformDB platformDB) {
DataSourceContextHolder.clearDataSourceType();
}
}

View File

@@ -60,7 +60,8 @@ public class SignValidateFilter implements Filter {
"/zxjp/**/api/audit/result",
"/zxjp/**/api/license",
"/zxjp/mini/line/getRegionPayPic",
"/zxjp/mini/miniProgram/getUserInfoByToken"
"/zxjp/mini/miniProgram/getUserInfoByToken",
"/zxjp/ws/**"
);

View File

@@ -52,7 +52,10 @@ public class TokenValidateFilter implements Filter {
"/zxjp/pc/sysRole/**",
"/zxjp/**/api/audit/result",
"/zxjp/pc/video/**",
"/zxjp/**/api/license"
"/zxjp/**/api/license",
"/zxjp/pc/v3/login/accountLogin",
"/zxjp/pc/v3/login/refreshLogin",
"/zxjp/ws/**"
);

View File

@@ -0,0 +1,72 @@
package com.cool.store.config.websocket;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;
/**
* <p>
* WebSocket配置类
* </p>
*
* @author wangff
* @since 2025/9/2
*/
@Configuration
@EnableWebSocketMessageBroker
@Slf4j
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/ws/zxzs")
.setAllowedOrigins("*")
.withSockJS(); // 启用SockJS支持
}
@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
// 配置消息代理
registry.enableSimpleBroker("/topic", "/queue") // 启用简单代理,用于广播和点对点消息
.setHeartbeatValue(new long[]{0, 10000})
.setTaskScheduler(webSocketTaskScheduler());
registry.setApplicationDestinationPrefixes("/app"); // 设置应用程序端点前缀
// registry.setUserDestinationPrefix("/user");
}
@Bean
public TaskScheduler webSocketTaskScheduler() {
ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
taskScheduler.setPoolSize(1);
taskScheduler.setThreadNamePrefix("websocket-heartbeat-");
taskScheduler.initialize();
return taskScheduler;
}
// @Override
// public void configureClientInboundChannel(ChannelRegistration registration) {
// registration.interceptors(new ChannelInterceptor() {
// @Override
// public Message<?> preSend(Message<?> message, MessageChannel channel) {
// StompHeaderAccessor accessor = StompHeaderAccessor.wrap(message);
//
// if (StompCommand.CONNECT.equals(accessor.getCommand())) {
// // 从STOMP头部获取login字段作为用户标识
// String login = accessor.getLogin();
// log.info("用户login:{}", login);
// if (login != null && !login.isEmpty()) {
// // 设置用户身份
// accessor.setUser(() -> login);
// }
// }
// return message;
// }
// });
// }
}

View File

@@ -0,0 +1,47 @@
package com.cool.store.controller.webb;
import com.cool.store.dto.login.UserLoginDTO;
import com.cool.store.dto.login.UserRefreshLoginDTO;
import com.cool.store.response.ResponseResult;
import com.cool.store.service.login.LoginBaseService;
import com.cool.store.service.login.LoginStrategy;
import com.cool.store.utils.SpringContextUtil;
import com.cool.store.vo.login.UserLoginVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
/**
* <p>
* 登录 前端控制器
* </p>
*
* @author wangff
* @since 2025/9/4
*/
@Api(tags = "登录")
@RestController
@RequestMapping("/pc/v3/login")
@RequiredArgsConstructor
public class LoginController {
private final LoginBaseService loginBaseService;
@ApiOperation("账号密码登录")
@PostMapping("/accountLogin")
public ResponseResult<UserLoginVO> accountLogin(@RequestBody UserLoginDTO param) {
return SpringContextUtil.getBean(param.getLoginType().getClazzName(), LoginStrategy.class).login(param);
}
@ApiOperation("refresh登录")
@PostMapping("/refreshLogin")
public ResponseResult<UserLoginVO> refreshLogin(@RequestBody UserRefreshLoginDTO param) {
return loginBaseService.refreshLogin(param);
}
@ApiOperation("登出")
@PostMapping("/logout")
public ResponseResult logout() {
return loginBaseService.logout();
}
}

View File

@@ -1,12 +1,12 @@
package com.cool.store.controller.webb;
import com.cool.store.context.CurrentUserHolder;
import com.cool.store.context.LoginUserInfo;
import com.cool.store.dto.notice.NoticeDTO;
import com.cool.store.request.notice.*;
import com.cool.store.response.ResponseResult;
import com.cool.store.service.MessageTemplateService;
import com.cool.store.vo.notice.MessageTemplateDetailVO;
import com.cool.store.vo.notice.StoreMessageDetailVO;
import com.cool.store.vo.notice.*;
import com.github.pagehelper.PageInfo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
@@ -87,5 +87,34 @@ public class MessageTemplateController {
return ResponseResult.success(messageTemplateService.revokeById(id,CurrentUserHolder.getUser()));
}
@ApiOperation("获取每个门店需要展示的模块")
@GetMapping("/getModuleListByStoreId")
public ResponseResult<List<ModuleAndMatterVO>> getModuleListByStoreId(@RequestParam("id")String storeId) {
return ResponseResult.success(messageTemplateService.getModuleList(storeId, CurrentUserHolder.getUser().getMobile()));
}
@ApiOperation("获取消息详情")
@GetMapping("/getMessageDetail")
public ResponseResult<MessageDetailVO> getMessageDetail(@RequestParam("id")Long id) {
return ResponseResult.success(messageTemplateService.getMessageDetail(id));
}
@ApiOperation("待办列表/模块列表")
@PostMapping("/getStorePendingList")
public ResponseResult<PageInfo<StoreMessageVO>> getStorePendingList(@RequestBody StoreMessagePendingRequest request) {
return ResponseResult.success(messageTemplateService.getStorePendingList(request));
}
@ApiOperation("确认已读")
@GetMapping("/readMessage")
public ResponseResult<Boolean> readMessage(@RequestParam("id")Long id) {
return ResponseResult.success(messageTemplateService.readMessage(id, CurrentUserHolder.getUser().getMobile()));
}
@ApiOperation("确认已处理")
@GetMapping("/handleMessage")
public ResponseResult<Boolean> handleMessage(@RequestParam("id")Long id) {
LoginUserInfo user = CurrentUserHolder.getUser();
return ResponseResult.success(messageTemplateService.handleMessage(id, user.getName(), user.getMobile()));
}
}

View File

@@ -0,0 +1,34 @@
package com.cool.store.controller.webb;
import com.cool.store.common.PageBasicInfo;
import com.cool.store.context.CurrentUserHolder;
import com.cool.store.response.MiniShopsResponse;
import com.cool.store.response.ResponseResult;
import com.cool.store.service.StoreService;
import com.github.pagehelper.PageInfo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
/**
* <p>
* PC门店 前端控制器
* </p>
*
* @author wangff
* @since 2025/9/9
*/
@Api(tags = "PC门店")
@RestController
@RequestMapping("/pc/stores")
@RequiredArgsConstructor
public class PCStoreController {
private final StoreService storeService;
@ApiOperation("当前用户门店列表")
@PostMapping("/userStoreList")
public ResponseResult<PageInfo<MiniShopsResponse>> getCurrentUserStoreList(@RequestBody PageBasicInfo request) {
return ResponseResult.success(storeService.getStoreListByMobile(CurrentUserHolder.getUser().getMobile(), request.getPageNum(), request.getPageSize(), null, null));
}
}

View File

@@ -5,6 +5,7 @@ import com.cool.store.context.PartnerUserHolder;
import com.cool.store.request.notice.StoreMessagePendingRequest;
import com.cool.store.response.ResponseResult;
import com.cool.store.service.MessageTemplateService;
import com.cool.store.vo.PartnerUserInfoVO;
import com.cool.store.vo.notice.MessageDetailVO;
import com.cool.store.vo.notice.ModuleAndMatterVO;
import com.cool.store.vo.notice.StoreMessageVO;
@@ -34,7 +35,7 @@ public class MiniMessageTemplateController {
@ApiOperation("获取每个门店需要展示的模块")
@GetMapping("/getModuleListByStoreId")
public ResponseResult<List<ModuleAndMatterVO>> getModuleListByStoreId(@RequestParam("id")String storeId) {
return ResponseResult.success(messageTemplateService.getModuleList(storeId, PartnerUserHolder.getUser()));
return ResponseResult.success(messageTemplateService.getModuleList(storeId, PartnerUserHolder.getUser().getMobile()));
}
@ApiOperation("获取消息详情")
@@ -52,13 +53,14 @@ public class MiniMessageTemplateController {
@ApiOperation("确认已读")
@GetMapping("/readMessage")
public ResponseResult<Boolean> readMessage(@RequestParam("id")Long id) {
return ResponseResult.success(messageTemplateService.readMessage(id, PartnerUserHolder.getUser()));
return ResponseResult.success(messageTemplateService.readMessage(id, PartnerUserHolder.getUser().getMobile()));
}
@ApiOperation("确认已处理")
@GetMapping("/handleMessage")
public ResponseResult<Boolean> handleMessage(@RequestParam("id")Long id) {
return ResponseResult.success(messageTemplateService.handleMessage(id, PartnerUserHolder.getUser()));
PartnerUserInfoVO user = PartnerUserHolder.getUser();
return ResponseResult.success(messageTemplateService.handleMessage(id, user.getUsername(), user.getMobile()));
}
}

View File

@@ -8,7 +8,6 @@ import com.cool.store.dto.ShopAccount.ShopAccountDTO;
import com.cool.store.request.GetPasswordDTO;
import com.cool.store.response.ResponseResult;
import com.cool.store.service.*;
import com.cool.store.vo.PartnerUserInfoVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.validation.annotation.Validated;
@@ -95,7 +94,7 @@ public class MiniShopAccountController {
@ApiOperation("获取标品登录token")
@GetMapping("/getAccessToken")
public ResponseResult<String> getAccessToken() {
return ResponseResult.success(enterpriseService.getAccessToken(PartnerUserHolder.getUser().getMobile()));
return ResponseResult.success(enterpriseService.getLoginInfo(PartnerUserHolder.getUser().getMobile()).getAccessToken());
}
}

View File

@@ -1,5 +1,6 @@
package com.cool.store.job;
import cn.hutool.core.collection.CollStreamUtil;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSONObject;
import com.cool.store.constants.CommonConstants;
@@ -7,6 +8,7 @@ import com.cool.store.dao.*;
import com.cool.store.dto.*;
import com.cool.store.dto.decoration.ConstructionScheduleDTO;
import com.cool.store.dto.openPreparation.OpenPlanShopInfoDTO;
import com.cool.store.dto.store.StoreOrderTimeDTO;
import com.cool.store.entity.*;
import com.cool.store.enums.*;
import com.cool.store.enums.point.ShopStatusEnum;
@@ -19,11 +21,14 @@ import com.cool.store.mapper.TrainingExperienceMapper;
import com.cool.store.mq.producer.SimpleMessageService;
import com.cool.store.mq.util.HttpRestTemplateService;
import com.cool.store.request.ZxjpApiRequest;
import com.cool.store.request.bigdata.LatestOrderDateRequest;
import com.cool.store.request.xfsgFirstOrderListRequest;
import com.cool.store.response.bigdata.LatestOrderDateResponse;
import com.cool.store.response.xfsgFirstOderListResponse;
import com.cool.store.service.*;
import com.cool.store.service.impl.CommonService;
import com.cool.store.utils.CoolDateUtils;
import com.cool.store.utils.MDCUtils;
import com.cool.store.utils.NumberConverter;
import com.cool.store.utils.poi.DateUtils;
import com.cool.store.utils.poi.StringUtils;
@@ -40,6 +45,7 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.Instant;
@@ -111,6 +117,10 @@ public class XxlJobHandler {
@Resource
PushService pushService;
@Resource
StoreDao storeDao;
@Resource
ThirdBigDataService thirdBigDataService;
/**
@@ -395,4 +405,56 @@ public class XxlJobHandler {
}
}
@XxlJob("latestOrderDate")
public void latestOrderDate() {
log.info("------start latestOrderDate------");
MDCUtils.put(CommonConstants.REQUEST_ID, UUID.randomUUID().toString());
String param = XxlJobHelper.getJobParam();
List<String> storeStatus = null;
if (StringUtils.isNotBlank(param)) {
storeStatus = Arrays.asList(param.split(","));
}
boolean hasNext = true;
int pageNum = 1;
int pageSize = CommonConstants.BATCH_SIZE;
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
while (hasNext) {
PageHelper.startPage(pageNum, pageSize);
List<StoreDO> storeList = storeDao.getAllStoreIdAndNum(storeStatus);
if (CollectionUtils.isEmpty(storeList)) {
break;
}
hasNext = storeList.size() >= pageSize;
List<String> storeNums = CollStreamUtil.toList(storeList, StoreDO::getStoreNum);
Map<String, String> storeIdMap = CollStreamUtil.toMap(storeList, StoreDO::getStoreNum, StoreDO::getStoreId);
LatestOrderDateRequest request = new LatestOrderDateRequest(1, pageSize, String.join(",", storeNums));
List<LatestOrderDateResponse> resList = thirdBigDataService.getLatestOrderDate(request);
log.info("接口请求门店数量:{},返回门店数:{}", storeList.size(), resList.size());
if (CollectionUtils.isNotEmpty(resList)) {
try {
List<StoreOrderTimeDTO> updateList = resList.stream()
.map(v -> {
Date date = parseDate(v, dateFormat);
return Objects.nonNull(date) ? new StoreOrderTimeDTO(storeIdMap.get(v.getStore_code()), date) : null;
})
.filter(Objects::nonNull)
.collect(Collectors.toList());
storeDao.batchInsertOrUpdateOrderTime(updateList);
} catch (Exception e) {
log.error("获取最新订货时间失败", e);
}
}
pageNum++;
}
log.info("------end latestOrderDate------");
}
public Date parseDate(LatestOrderDateResponse v, DateFormat format) {
try {
return format.parse(v.getLatest_buy_date());
} catch (ParseException e) {
log.error("日期转化失败,storeCode:{},latestBuyDate:{}", v.getStore_code(), v.getLatest_buy_date());
}
return null;
}
}

View File

@@ -4,6 +4,10 @@ default.datasource.url=jdbc:mysql://dingpushcoolcollege.mysql.rds.aliyuncs.com:3
default.datasource.username=coolstore
default.datasource.password=CSCErYcXniNYm7bT
platform.datasource.url=jdbc:mysql://dingpushcoolcollege.mysql.rds.aliyuncs.com:3306/coolcollege_intelligent_config?useSSL=false&useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&autoReconnect=true
platform.datasource.username=coolstore
platform.datasource.password=CSCErYcXniNYm7bT
#redis
redis.host.uri=http://userInfo:Cx111111@tstore-coolcollege.redis.rds.aliyuncs.com:6379/0

View File

@@ -1,9 +1,13 @@
#mysql config
default.datasource.url=jdbc:mysql://store10-coolcollege.mysql.rds.aliyuncs.com:3306/coolcollege_intelligent_10027?useUnicode=true&characterEncoding=UTF-8&useSSL=false&autoReconnect=true&failOverReadOnly=false&serverTimezone=Asia/Shanghai&allowMultiQueries=true
default.datasource.url=jdbc:mysql://zx-coolstore.mysql.rds.aliyuncs.com:3306/coolcollege_intelligent_10027?useUnicode=true&characterEncoding=UTF-8&useSSL=false&autoReconnect=true&failOverReadOnly=false&serverTimezone=Asia/Shanghai&allowMultiQueries=true
default.datasource.username=coolstore
default.datasource.password=CSCErYcXniNYm7bT
platform.datasource.url=jdbc:mysql://zx-coolstore.mysql.rds.aliyuncs.com:3306/coolcollege_intelligent_config?useUnicode=true&characterEncoding=UTF-8&useSSL=false&autoReconnect=true&failOverReadOnly=false&serverTimezone=Asia/Shanghai&allowMultiQueries=true
platform.datasource.username=coolstore
platform.datasource.password=CSCErYcXniNYm7bT
#redis
redis.host.uri=http://userInfo:Cx111111@store-coolcollege.redis.rds.aliyuncs.com:6379/0

View File

@@ -4,6 +4,10 @@ default.datasource.url=jdbc:mysql://dingpushcoolcollege.mysql.rds.aliyuncs.com:3
default.datasource.username=coolstore
default.datasource.password=CSCErYcXniNYm7bT
platform.datasource.url=jdbc:mysql://dingpushcoolcollege.mysql.rds.aliyuncs.com:3306/coolcollege_intelligent_config?useSSL=false&useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&autoReconnect=true
platform.datasource.username=coolstore
platform.datasource.password=CSCErYcXniNYm7bT
#redis
redis.host.uri=http://userInfo:Cx111111@tstore-coolcollege-open.redis.rds.aliyuncs.com:6379/0
@@ -133,3 +137,8 @@ special.user.id=wpayJeDAAAhGIFgUJpJN-zg39JuNbYhg_woayJeDAAA0TC8mkCJeXouw94hYA-D3
ask.bot.url=https://test.auth.wx.askbot.cn
hqt.token.url=https://tc.cloud.hecom.cn
hqt.token.username=18161486722
hqt.token.grant_type=client_credentials
hqt.token.client.id=WrPffdGpcWkcPsbN
hqt.token.client.secret=rYe9Cwug5LwQNIBJAiW0a7weF9CAhYCD

View File

@@ -3,6 +3,10 @@ default.datasource.url=jdbc:mysql://zx-coolstore.mysql.rds.aliyuncs.com:3306/coo
default.datasource.username=coolstore
default.datasource.password=CSCErYcXniNYm7bT
platform.datasource.url=jdbc:mysql://zx-coolstore.mysql.rds.aliyuncs.com:3306/coolcollege_intelligent_config?useUnicode=true&characterEncoding=UTF-8&useSSL=false&autoReconnect=true&failOverReadOnly=false&serverTimezone=Asia/Shanghai&allowMultiQueries=true
platform.datasource.username=coolstore
platform.datasource.password=CSCErYcXniNYm7bT
#redis
redis.host.uri=http://userInfo:Cx111111@store-coolcollege.redis.rds.aliyuncs.com:6379/0

View File

@@ -4,6 +4,10 @@ default.datasource.url=jdbc:mysql://dingpushcoolcollege.mysql.rds.aliyuncs.com:3
default.datasource.username=coolstore
default.datasource.password=CSCErYcXniNYm7bT
platform.datasource.url=jdbc:mysql://dingpushcoolcollege.mysql.rds.aliyuncs.com:3306/coolcollege_intelligent_config?useSSL=false&useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&autoReconnect=true
platform.datasource.username=coolstore
platform.datasource.password=CSCErYcXniNYm7bT
#redis
redis.host.uri=http://userInfo:Cx111111@tstore-coolcollege-open.redis.rds.aliyuncs.com:6379/0