From 265cbe3cc187758cd024e91e39dfd488d8486a33 Mon Sep 17 00:00:00 2001 From: liujie <liujie> Date: 星期六, 16 九月 2023 10:55:23 +0800 Subject: [PATCH] app 2.0 --- cloud-server-gateway/src/main/java/cn/mb/cloud/gateway/controller/NettyController.java | 48 cloud-server-gateway/src/main/java/cn/mb/cloud/gateway/util/applets/CacheType.java | 86 + cloud-server-activity/src/main/java/com/dsh/activity/feignclient/model/PointDetailsVo.java | 2 cloud-server-account/src/main/java/com/dsh/account/feignclient/course/model/RecordAppoint.java | 2 cloud-server-gateway/src/main/java/cn/mb/cloud/gateway/util/applets/ClientPingMessage.java | 59 cloud-server-course/src/main/java/com/dsh/course/service/TCoursePackageService.java | 7 cloud-server-gateway/src/main/java/cn/mb/cloud/gateway/util/echo/NettyServerController.java | 399 +++++ cloud-server-management/src/main/webapp/WEB-INF/view/system/tGoods/TGoods_detail_two.html | 4 cloud-server-account/src/main/java/com/dsh/account/service/impl/TStudentServiceImpl.java | 42 cloud-server-competition/src/main/java/com/dsh/competition/model/CompetitionInfo.java | 3 cloud-server-course/src/main/java/com/dsh/course/util/TaskUtil.java | 60 cloud-server-account/mb-cloud-account.iml | 8 cloud-server-course/src/main/java/com/dsh/course/feignclient/model/RecordAppoint.java | 2 cloud-server-gateway/src/main/java/cn/mb/cloud/gateway/util/applets/NettyServer0.java | 77 + cloud-server-gateway/src/main/java/cn/mb/cloud/gateway/util/echo/NettyServer.java | 95 + cloud-server-course/src/main/java/com/dsh/course/service/impl/TCoursePackageServiceImpl.java | 719 ++++++++-- cloud-server-competition/src/main/java/com/dsh/competition/service/CompetitionService.java | 10 cloud-server-gateway/src/main/java/cn/mb/cloud/gateway/util/echo/NettyChannelMap.java | 133 + cloud-server-activity/src/main/java/com/dsh/activity/controller/PointMercharsController.java | 7 cloud-server-course/src/main/java/com/dsh/course/feignclient/activity/UserCouponClient.java | 8 cloud-server-other/src/main/java/com/dsh/other/entity/SiteBooking.java | 8 cloud-server-activity/src/main/java/com/dsh/activity/controller/IntroduceRewardsController.java | 10 cloud-server-auth/mb-cloud-auth.iml | 8 cloud-server-competition/src/main/java/com/dsh/competition/service/impl/CompetitionServiceImpl.java | 55 cloud-server-activity/src/main/java/com/dsh/activity/entity/PointsMerchandise.java | 2 cloud-server-competition/src/main/java/com/dsh/competition/model/PaymentCompetitionVo.java | 2 cloud-server-account/src/main/java/com/dsh/account/model/vo/userBenefitDetail/MallRequest.java | 2 cloud-server-course/src/main/java/com/dsh/course/entity/TCoursePackage.java | 4 cloud-server-other/src/main/java/com/dsh/other/service/impl/SiteServiceImpl.java | 29 cloud-server-course/src/main/java/com/dsh/course/service/impl/TCoursePackagePaymentServiceImpl.java | 186 ++ cloud-server-other/src/main/java/com/dsh/other/model/ReservationSite.java | 6 cloud-server-course/src/main/java/com/dsh/course/controller/CourseController.java | 38 cloud-server-competition/src/main/java/com/dsh/competition/service/impl/PaymentCompetitionServiceImpl.java | 2 cloud-server-gateway/src/main/java/cn/mb/cloud/gateway/util/applets/NettyWebSocketController.java | 205 ++ cloud-server-account/src/main/java/com/dsh/account/feignclient/activity/IntroduceRewardsClient.java | 2 cloud-server-activity/mb-cloud-activity.iml | 8 cloud-server-course/src/main/java/com/dsh/course/entity/CoursePackagePaymentConfig.java | 2 cloud-server-gateway/src/main/java/cn/mb/cloud/gateway/util/echo/NettyMsg.java | 165 ++ cloud-server-competition/mb-cloud-competition.iml | 8 cloud-server-course/src/main/java/com/dsh/course/feignclient/account/AppUserClient.java | 7 cloud-server-gateway/src/main/java/cn/mb/cloud/gateway/util/applets/createSSLContext.java | 31 cloud-server-course/src/main/java/com/dsh/course/controller/CoursePackagePaymentController.java | 200 ++ cloud-server-activity/src/main/java/com/dsh/activity/feignclient/model/ProductDetailsVo.java | 3 cloud-server-other/src/main/java/com/dsh/other/controller/SiteController.java | 9 cloud-server-other/src/main/java/com/dsh/other/controller/StoreController.java | 2 cloud-server-course/src/main/java/com/dsh/course/feignclient/activity/CouponClient.java | 6 cloud-server-gateway/src/main/java/cn/mb/cloud/gateway/util/applets/Global.java | 9 cloud-server-activity/src/main/java/com/dsh/activity/controller/BenefitVideoController.java | 18 cloud-server-gateway/src/main/java/cn/mb/cloud/gateway/util/SinataUtil.java | 405 +++++ cloud-server-gateway/src/main/java/cn/mb/cloud/gateway/util/applets/WebSocketHandler.java | 180 ++ cloud-server-other/src/main/java/com/dsh/other/entity/Site.java | 10 cloud-server-account/src/main/java/com/dsh/account/model/vo/classDetails/CourseVenue.java | 6 cloud-server-gateway/src/main/java/cn/mb/cloud/gateway/util/SpringUtil.java | 34 cloud-server-course/src/main/java/com/dsh/course/model/vo/RegisterCourseVo.java | 3 cloud-server-course/src/main/java/com/dsh/course/service/TCoursePackagePaymentService.java | 20 cloud-server-account/src/main/java/com/dsh/account/controller/AppUserController.java | 13 cloud-server-competition/src/main/java/com/dsh/competition/entity/Competition.java | 2 cloud-server-activity/src/main/java/com/dsh/activity/service/impl/BenefitsVideosServiceImpl.java | 36 cloud-server-competition/src/main/java/com/dsh/competition/feignclient/course/model/PaymentDeductionClassHour.java | 4 cloud-server-gateway/src/main/java/cn/mb/cloud/gateway/util/StringUtil.java | 121 + cloud-server-account/src/main/java/com/dsh/account/model/vo/userBenefitDetail/ProductDetailsVo.java | 3 cloud-server-account/src/main/java/com/dsh/account/model/AddAppUserVo.java | 4 cloud-server-gateway/pom.xml | 8 cloud-server-course/mb-cloud-course.iml | 12 cloud-server-account/src/main/java/com/dsh/account/controller/ClassDetailsController.java | 64 cloud-server-activity/src/main/java/com/dsh/activity/service/BenefitsVideosService.java | 1 cloud-server-course/src/main/java/com/dsh/course/feignclient/model/CourseOfStoreVo.java | 8 cloud-server-gateway/src/main/java/cn/mb/cloud/gateway/util/applets/ChildChannelHandler.java | 36 cloud-server-account/src/main/java/com/dsh/account/model/vo/userBenefitDetail/Goods.java | 4 cloud-server-account/src/main/java/com/dsh/account/model/vo/userBenefitDetail/PointDetailsVo.java | 4 cloud-server-course/src/main/java/com/dsh/course/model/CoursePackageListVo.java | 6 cloud-server-course/src/main/java/com/dsh/course/feignclient/model/PaymentDeductionClassHour.java | 4 cloud-server-account/src/main/java/com/dsh/account/feignclient/course/CoursePaymentClient.java | 7 cloud-server-account/src/main/java/com/dsh/account/feignclient/course/model/CourseOfStoreVo.java | 6 cloud-server-course/src/main/java/com/dsh/course/model/CoursePackageInfo.java | 4 /dev/null | 8 cloud-server-activity/src/main/java/com/dsh/activity/controller/UserCouponController.java | 29 cloud-server-account/src/main/java/com/dsh/account/service/impl/TAppUserServiceImpl.java | 53 cloud-server-competition/src/main/java/com/dsh/competition/feignclient/course/CoursePackagePaymentClient.java | 13 cloud-server-gateway/src/main/java/cn/mb/cloud/gateway/util/echo/DiscardServerHandler.java | 153 ++ cloud-server-other/src/main/java/com/dsh/other/model/QuerySiteInfoVo.java | 13 cloud-server-gateway/src/main/java/cn/mb/cloud/gateway/util/echo/Method.java | 26 cloud-server-gateway/src/main/java/cn/mb/cloud/gateway/util/echo/ServerInit.java | 25 cloud-server-competition/src/main/java/com/dsh/competition/controller/CompetitionController.java | 20 84 files changed, 3,890 insertions(+), 253 deletions(-) diff --git a/cloud-server-account/mb-cloud-account.iml b/cloud-server-account/mb-cloud-account.iml index 1daccae..13e8572 100644 --- a/cloud-server-account/mb-cloud-account.iml +++ b/cloud-server-account/mb-cloud-account.iml @@ -1,8 +1,2 @@ <?xml version="1.0" encoding="UTF-8"?> -<module version="4"> - <component name="FacetManager"> - <facet type="Spring" name="Spring"> - <configuration /> - </facet> - </component> -</module> \ No newline at end of file +<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" version="4" /> \ No newline at end of file diff --git a/cloud-server-account/src/main/java/com/dsh/account/controller/AppUserController.java b/cloud-server-account/src/main/java/com/dsh/account/controller/AppUserController.java index fccd65a..3625888 100644 --- a/cloud-server-account/src/main/java/com/dsh/account/controller/AppUserController.java +++ b/cloud-server-account/src/main/java/com/dsh/account/controller/AppUserController.java @@ -3,9 +3,11 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.dsh.account.entity.TAppUser; +import com.dsh.account.entity.TCourseInfoRecord; import com.dsh.account.model.*; import com.dsh.account.service.IVipPaymentService; import com.dsh.account.service.TAppUserService; +import com.dsh.account.service.TCourseInfoRecordService; import com.dsh.account.util.PayMoneyUtil; import com.dsh.account.util.ResultUtil; import com.dsh.account.util.TokenUtil; @@ -43,6 +45,9 @@ @Autowired private TokenUtil tokenUtil; + + @Autowired + private TCourseInfoRecordService courseInfoRecordService; @@ -391,4 +396,12 @@ public List<TAppUser> queryAppUserListByName(@RequestBody String name){ return appUserService.list(new QueryWrapper<TAppUser>().eq("state", 1).like("name", name)); } + + + + @PostMapping("/appUser/addCourseInfoRecord") + public Boolean addCourseInfoRecord(@RequestBody TCourseInfoRecord tCourseInfoRecord){ + boolean save = courseInfoRecordService.save(tCourseInfoRecord); + return save; + } } diff --git a/cloud-server-account/src/main/java/com/dsh/account/controller/ClassDetailsController.java b/cloud-server-account/src/main/java/com/dsh/account/controller/ClassDetailsController.java index 210bd96..c7f2a49 100644 --- a/cloud-server-account/src/main/java/com/dsh/account/controller/ClassDetailsController.java +++ b/cloud-server-account/src/main/java/com/dsh/account/controller/ClassDetailsController.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.dsh.account.entity.TAppGift; import com.dsh.account.entity.TStudent; import com.dsh.account.feignclient.competition.model.PurchaseRecordVo; import com.dsh.account.feignclient.course.model.RecordAppoint; @@ -14,10 +15,7 @@ import com.dsh.account.model.vo.sourceDetail.CouponStuAvailableVo; import com.dsh.account.model.vo.sourceDetail.CourseDetailsOfContinuationResp; import com.dsh.account.model.vo.sourceDetail.RecordTimeRequest; -import com.dsh.account.service.EvaluateStudentService; -import com.dsh.account.service.StudentHonorService; -import com.dsh.account.service.TAppUserService; -import com.dsh.account.service.TStudentService; +import com.dsh.account.service.*; import com.dsh.account.util.*; import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiImplicitParams; @@ -25,6 +23,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; @@ -59,6 +58,9 @@ @Autowired private TokenUtil tokenUtil; + + @Autowired + private TAppGiftService appGiftService; @@ -106,6 +108,60 @@ } + @ResponseBody + @PostMapping("/api/startCource/weeksOfGetHours") + @ApiOperation(value = "上课首页获取未分配课时-课程列表", tags = {"APP-开始上课"}) + @ApiImplicitParams({ + @ApiImplicitParam(name = "Authorization", value = "Bearer +token", required = true, dataType = "String", paramType = "header", defaultValue = "Bearer eyJhbGciOiJIUzUxMiJ9....."), + }) + public ResultUtil<Integer> weeksOfGetHours(){ + try { + Integer appUserId = tokenUtil.getUserIdFormRedis(); + if(null == appUserId){ + return ResultUtil.tokenErr(); + } + TAppGift one = appGiftService.getOne(new LambdaQueryWrapper<TAppGift>().eq(TAppGift::getUserId, appUserId)); + + return ResultUtil.success(one==null?0:one.getNum()); + }catch (Exception e){ + e.printStackTrace(); + return ResultUtil.runErr(); + } + } + + + @ResponseBody + @PostMapping("/api/startCource/weeksOfAddHours") + @ApiOperation(value = "上课首页分配课时-课程列表", tags = {"APP-开始上课"}) + @ApiImplicitParams({ + @ApiImplicitParam(name = "Authorization", value = "Bearer +token", required = true, dataType = "String", paramType = "header", defaultValue = "Bearer eyJhbGciOiJIUzUxMiJ9....."), + @ApiImplicitParam(value = "分配给课包id", name = "packetId", required = true, dataType = "string"), + }) + public ResultUtil<Integer> weeksOfAddHours(Integer packetId){ + try { + Integer appUserId = tokenUtil.getUserIdFormRedis(); + if(null == appUserId){ + return ResultUtil.tokenErr(); + } + TAppGift one = appGiftService.getOne(new LambdaQueryWrapper<TAppGift>().eq(TAppGift::getUserId, appUserId)); + Boolean b= false; + if(one!=null && one.getNum()>0){ + b =appGiftService.weeksOfAddHours(packetId,appUserId,one.getNum()); + } + if(b){ + // 送完清0 + one.setNum(0); + appGiftService.updateById(one); + return ResultUtil.success(); + }else { + return ResultUtil.runErr(); + } + }catch (Exception e){ + e.printStackTrace(); + return ResultUtil.runErr(); + } + } + @ResponseBody @PostMapping("/api/startCource/queryPhysical") diff --git a/cloud-server-account/src/main/java/com/dsh/account/feignclient/activity/IntroduceRewardsClient.java b/cloud-server-account/src/main/java/com/dsh/account/feignclient/activity/IntroduceRewardsClient.java index f3b9d0d..1998736 100644 --- a/cloud-server-account/src/main/java/com/dsh/account/feignclient/activity/IntroduceRewardsClient.java +++ b/cloud-server-account/src/main/java/com/dsh/account/feignclient/activity/IntroduceRewardsClient.java @@ -16,6 +16,8 @@ @PostMapping("/base/introduce/useOfRewards") public List<PurchaseRecordVo> queryAppUsersofIntroduce(@RequestBody IntrduceOfUserRequest request); + @PostMapping("/base/introduce/getGiftList") + Integer getGiftList(@RequestBody String cityCode); } diff --git a/cloud-server-account/src/main/java/com/dsh/account/feignclient/course/CoursePaymentClient.java b/cloud-server-account/src/main/java/com/dsh/account/feignclient/course/CoursePaymentClient.java index 61a8c62..b8c26af 100644 --- a/cloud-server-account/src/main/java/com/dsh/account/feignclient/course/CoursePaymentClient.java +++ b/cloud-server-account/src/main/java/com/dsh/account/feignclient/course/CoursePaymentClient.java @@ -62,4 +62,11 @@ @PostMapping("/base/coursePack/getCoursePackagePaymentOfCode") List<TCoursePackagePayment> getCoursePackagePaymentOfCode(@RequestBody String code); + @PostMapping("/base/coursePack/sendHours") + Boolean sendHours(String s); + + @PostMapping("/base/coursePack/getClassHour") + Integer getClassHour(Integer courseConfigId); + + } diff --git a/cloud-server-account/src/main/java/com/dsh/account/feignclient/course/model/CourseOfStoreVo.java b/cloud-server-account/src/main/java/com/dsh/account/feignclient/course/model/CourseOfStoreVo.java index 8e1fff5..2c67928 100644 --- a/cloud-server-account/src/main/java/com/dsh/account/feignclient/course/model/CourseOfStoreVo.java +++ b/cloud-server-account/src/main/java/com/dsh/account/feignclient/course/model/CourseOfStoreVo.java @@ -36,4 +36,10 @@ @ApiModelProperty(value = "预约状态") private Integer status; + @ApiModelProperty(value = "总学时数") + Integer allNum; + @ApiModelProperty(value = "已扣学时数") + Integer useNum; + @ApiModelProperty(value = "剩余学时数") + Integer lastNum; } diff --git a/cloud-server-account/src/main/java/com/dsh/account/feignclient/course/model/RecordAppoint.java b/cloud-server-account/src/main/java/com/dsh/account/feignclient/course/model/RecordAppoint.java index e4c0131..40394d3 100644 --- a/cloud-server-account/src/main/java/com/dsh/account/feignclient/course/model/RecordAppoint.java +++ b/cloud-server-account/src/main/java/com/dsh/account/feignclient/course/model/RecordAppoint.java @@ -24,7 +24,7 @@ @ApiModelProperty(value = "门店名称+地址") private String storeNameAddr; - @ApiModelProperty(value = "课状态(1待上课 2已开始 3已完成 4已取消)") + @ApiModelProperty(value = "课状态(1待上课 2已开始 3已完成 4已取消 5已请假 6旷课)") private Integer status; } diff --git a/cloud-server-account/src/main/java/com/dsh/account/model/AddAppUserVo.java b/cloud-server-account/src/main/java/com/dsh/account/model/AddAppUserVo.java index d1cca9b..3062fb3 100644 --- a/cloud-server-account/src/main/java/com/dsh/account/model/AddAppUserVo.java +++ b/cloud-server-account/src/main/java/com/dsh/account/model/AddAppUserVo.java @@ -15,4 +15,8 @@ private String password; @ApiModelProperty(value = "邀请人id", dataType = "int", required = false) private Integer referralUserId; + + private String lon; + private String lat; + } \ No newline at end of file diff --git a/cloud-server-account/src/main/java/com/dsh/account/model/vo/classDetails/CourseVenue.java b/cloud-server-account/src/main/java/com/dsh/account/model/vo/classDetails/CourseVenue.java index 87498f2..4c00225 100644 --- a/cloud-server-account/src/main/java/com/dsh/account/model/vo/classDetails/CourseVenue.java +++ b/cloud-server-account/src/main/java/com/dsh/account/model/vo/classDetails/CourseVenue.java @@ -37,6 +37,12 @@ @ApiModelProperty(value = "预约状态:1=未预约,2=已预约") Integer status; + @ApiModelProperty(value = "总学时数") + Integer allNum; + @ApiModelProperty(value = "已扣学时数") + Integer useNum; + @ApiModelProperty(value = "剩余学时数") + Integer lastNum; } diff --git a/cloud-server-account/src/main/java/com/dsh/account/model/vo/userBenefitDetail/Goods.java b/cloud-server-account/src/main/java/com/dsh/account/model/vo/userBenefitDetail/Goods.java index 7df80ad..b651466 100644 --- a/cloud-server-account/src/main/java/com/dsh/account/model/vo/userBenefitDetail/Goods.java +++ b/cloud-server-account/src/main/java/com/dsh/account/model/vo/userBenefitDetail/Goods.java @@ -5,6 +5,8 @@ import lombok.Data; import java.math.BigDecimal; +import java.util.List; + @Data public class Goods { @@ -35,5 +37,7 @@ @ApiModelProperty(value = "已兑换数量") private Integer nums; + @ApiModelProperty(value = "门店id") + private List<Integer> shopIds; } diff --git a/cloud-server-account/src/main/java/com/dsh/account/model/vo/userBenefitDetail/MallRequest.java b/cloud-server-account/src/main/java/com/dsh/account/model/vo/userBenefitDetail/MallRequest.java index c52cbf0..e640c0b 100644 --- a/cloud-server-account/src/main/java/com/dsh/account/model/vo/userBenefitDetail/MallRequest.java +++ b/cloud-server-account/src/main/java/com/dsh/account/model/vo/userBenefitDetail/MallRequest.java @@ -18,6 +18,8 @@ @ApiModelProperty(value = "商品类型: 1实物 2课包 3门票 4优惠券") private Integer goodsType; + @ApiModelProperty(value = "门店id") + private Integer shopId; @ApiModelProperty(value = "搜索内容") private String search; diff --git a/cloud-server-account/src/main/java/com/dsh/account/model/vo/userBenefitDetail/PointDetailsVo.java b/cloud-server-account/src/main/java/com/dsh/account/model/vo/userBenefitDetail/PointDetailsVo.java index d644a90..eca7bd0 100644 --- a/cloud-server-account/src/main/java/com/dsh/account/model/vo/userBenefitDetail/PointDetailsVo.java +++ b/cloud-server-account/src/main/java/com/dsh/account/model/vo/userBenefitDetail/PointDetailsVo.java @@ -8,7 +8,7 @@ import java.util.List; @Data -public class PointDetailsVo { +public class PointDetailsVo { @ApiModelProperty(value = "记录id") private Integer detailsId; @@ -58,4 +58,6 @@ @ApiModelProperty(value = "兑换方式(1=积分,2=积分+现金)") private Integer exchangeType; + @ApiModelProperty(value = "1日卡 2月卡 3季卡 4年卡") + private Integer cardType; } diff --git a/cloud-server-account/src/main/java/com/dsh/account/model/vo/userBenefitDetail/ProductDetailsVo.java b/cloud-server-account/src/main/java/com/dsh/account/model/vo/userBenefitDetail/ProductDetailsVo.java index 0c66d75..cce4217 100644 --- a/cloud-server-account/src/main/java/com/dsh/account/model/vo/userBenefitDetail/ProductDetailsVo.java +++ b/cloud-server-account/src/main/java/com/dsh/account/model/vo/userBenefitDetail/ProductDetailsVo.java @@ -64,4 +64,7 @@ @ApiModelProperty(value = "商品类型 1实物 2课包 3门票 4优惠券") private Integer goodType; + @ApiModelProperty(value = "1日卡 2月卡 3季卡 4年卡") + private Integer cardType; + } diff --git a/cloud-server-account/src/main/java/com/dsh/account/service/impl/TAppUserServiceImpl.java b/cloud-server-account/src/main/java/com/dsh/account/service/impl/TAppUserServiceImpl.java index a76a64c..c6dc20e 100644 --- a/cloud-server-account/src/main/java/com/dsh/account/service/impl/TAppUserServiceImpl.java +++ b/cloud-server-account/src/main/java/com/dsh/account/service/impl/TAppUserServiceImpl.java @@ -1,10 +1,12 @@ package com.dsh.account.service.impl; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.dsh.account.entity.*; import com.dsh.account.enums.RechargeRecordEnum; +import com.dsh.account.feignclient.activity.IntroduceRewardsClient; import com.dsh.account.feignclient.activity.MerChandiseClient; import com.dsh.account.feignclient.activity.MerChandiseStoreClient; import com.dsh.account.feignclient.activity.UserConponClient; @@ -12,6 +14,7 @@ import com.dsh.account.feignclient.competition.DeductionCompetitionsClient; import com.dsh.account.feignclient.competition.model.BillingDataRequestVo; import com.dsh.account.feignclient.competition.model.PaymentCompetition; +import com.dsh.account.feignclient.competition.model.PurchaseRecordVo; import com.dsh.account.feignclient.course.CoursePackageClient; import com.dsh.account.feignclient.course.CoursePackageConfigClient; import com.dsh.account.feignclient.course.CoursePaymentClient; @@ -33,6 +36,7 @@ import com.dsh.account.model.vo.classDetails.RegisteredCourse; import com.dsh.account.model.vo.classDetails.classInsVo.ClassInfoVo; import com.dsh.account.model.vo.userBenefitDetail.*; +import com.dsh.account.service.TAppGiftService; import com.dsh.account.service.TAppUserService; import com.dsh.account.util.*; import com.dsh.account.util.akeylogin.Md5Util; @@ -134,6 +138,11 @@ @Resource private SiteClient stClient; + @Autowired + private TAppGiftService appGiftService; + + @Autowired + private IntroduceRewardsClient introduceRewardsClient; @Override public ClassInfoVo queryUserOfStus(Integer id) { TAppUser tAppUser = this.baseMapper.selectById(id); @@ -217,6 +226,10 @@ couList.setTimeStr(courseOfStoreVo.getClassStartTime() + "-" + courseOfStoreVo.getClassEndTime()); couList.setDetail("¥" + courseOfStoreVo.getCoursePrice() + "/会员扣2学时"); couList.setStatus(courseOfStoreVo.getStatus()); + + couList.setAllNum(courseOfStoreVo.getAllNum()); + couList.setUseNum(courseOfStoreVo.getUseNum()); + couList.setLastNum(courseOfStoreVo.getLastNum()); courses.add(couList); } courseVenue.setCourses(courses); @@ -279,6 +292,32 @@ tAppUser.setState(1); tAppUser.setInsertTime(new Date()); this.baseMapper.insert(tAppUser); + + + // 介绍有礼 + if(addAppUserVo.getReferralUserId()!=null){ + Map<String, String> geocode = gdMapGeocodingUtil.geocode(addAppUserVo.getLon(), addAppUserVo.getLat()); + Integer num=0; + if(null != geocode){ + String province = geocode.get("province"); + String provinceCode = geocode.get("provinceCode"); + String city = geocode.get("city"); + String cityCode = geocode.get("cityCode"); + num = introduceRewardsClient.getGiftList(cityCode); + } + TAppGift one = appGiftService.getOne(new LambdaQueryWrapper<TAppGift>().eq(TAppGift::getUserId, addAppUserVo.getReferralUserId())); + if(one!=null){ + one.setNum(one.getNum()+num); + appGiftService.updateById(one); + }else { + TAppGift tAppGift = new TAppGift(); + tAppGift.setUserId(addAppUserVo.getReferralUserId()); + tAppGift.setNum(num); + appGiftService.save(tAppGift); + } + + } + return ResultUtil.success(); } @@ -691,6 +730,8 @@ commodity.setBelongsType(vicinityGood.getUserPopulation()); commodity.setGoodsType(1); commodity.setNums(mcClient.getRedeemedQuantity(vicinityGood.getId())); + List<Integer> integers = mcsClient.queryPointMerStoreIds(vicinityGood.getId()); + commodity.setShopIds(integers); break; case 2: commodity.setGoodId(vicinityGood.getCoursePackageId()); @@ -707,6 +748,7 @@ commodity.setBelongsType(vicinityGood.getUserPopulation()); commodity.setGoodsType(2); commodity.setNums(mcClient.getRedeemedQuantity(vicinityGood.getId())); + commodity.setShopIds(mcsClient.queryPointMerStoreIds(vicinityGood.getId())); break; case 3: commodity.setGoodId(vicinityGood.getId()); @@ -722,6 +764,7 @@ commodity.setBelongsType(vicinityGood.getUserPopulation()); commodity.setGoodsType(3); commodity.setNums(mcClient.getRedeemedQuantity(vicinityGood.getId())); + commodity.setShopIds(mcsClient.queryPointMerStoreIds(vicinityGood.getId())); break; default: break; @@ -749,6 +792,7 @@ goods.add(commodity); } } + if (StringUtils.hasText(request.getSearch())){ if (goods.size() > 0 ){ goods = goods.stream() @@ -756,6 +800,15 @@ .collect(Collectors.toList()); } } + // 2.0 门店筛选 + if (request.getShopId()!=null){ + if (goods.size() > 0 ){ + goods = goods.stream() + .filter(merchandise -> merchandise.getShopIds().contains(request.getShopId())) + .collect(Collectors.toList()); + } + } + if (null != request.getRank()){ switch (request.getRank()){ case 1: diff --git a/cloud-server-account/src/main/java/com/dsh/account/service/impl/TStudentServiceImpl.java b/cloud-server-account/src/main/java/com/dsh/account/service/impl/TStudentServiceImpl.java index 71ee8ba..25ade80 100644 --- a/cloud-server-account/src/main/java/com/dsh/account/service/impl/TStudentServiceImpl.java +++ b/cloud-server-account/src/main/java/com/dsh/account/service/impl/TStudentServiceImpl.java @@ -7,6 +7,7 @@ import com.dsh.account.dto.TStudentDto; import com.dsh.account.entity.Coach; import com.dsh.account.entity.TAppUser; +import com.dsh.account.entity.TCourseInfoRecord; import com.dsh.account.entity.TStudent; import com.dsh.account.feignclient.activity.IntroduceRewardsClient; import com.dsh.account.feignclient.activity.UserConponClient; @@ -40,6 +41,7 @@ import com.dsh.account.model.vo.sourceDetail.CourseDetailsOfContinuationResp; import com.dsh.account.model.vo.sourceDetail.RecordTimeRequest; import com.dsh.account.model.vo.userBenefitDetail.Goods; +import com.dsh.account.service.TCourseInfoRecordService; import com.dsh.account.service.TStudentService; import com.dsh.account.util.*; import org.springframework.beans.factory.annotation.Autowired; @@ -113,6 +115,9 @@ @Resource private CourseListClient culisClient; + + @Autowired + private TCourseInfoRecordService courseInfoRecordService; @@ -243,6 +248,7 @@ getStuSourseList.setStartTime(startTime); getStuSourseList.setEndTime(endTime); getStuSourseList.setAppUserId(appUserId); + // 报名赛事 List<PurchaseRecordVo> stuSourseList = dcttClient.getStuSourseList(getStuSourseList); purchaseRecordVoList.addAll(stuSourseList); @@ -259,6 +265,7 @@ getStuSessionList.setEndTime(endTime); getStuSessionList.setStuId(timeRequest.getStuId()); getStuSessionList.setAppUserId(appUserId); + // 购买课包 List<PurchaseRecordVo> purchaseRecordVos = sessionNameClient.queryCourseDetails(getStuSessionList); purchaseRecordVoList.addAll(purchaseRecordVos); List<TAppUser> tAppUsers = tauMapper.selectList(new QueryWrapper<TAppUser>() @@ -270,9 +277,30 @@ request.setStartTime(startTime); request.setEndTime(endTime); request.setUserIds(userIds); + // 介绍有礼 List<PurchaseRecordVo> purchaseRecordVos1 = idrClient.queryAppUsersofIntroduce(request); purchaseRecordVoList.addAll(purchaseRecordVos1); } + + LambdaQueryWrapper<TCourseInfoRecord> eq = new LambdaQueryWrapper<TCourseInfoRecord>().eq(TCourseInfoRecord::getUserId, appUserId); + if(timeRequest.getType()!=null){ + eq.eq(TCourseInfoRecord::getType,timeRequest.getType()); + } + // 2.0其他记录 + List<TCourseInfoRecord> list = courseInfoRecordService.list(eq); + List<PurchaseRecordVo> list1=new ArrayList<>(); + for (TCourseInfoRecord tCourseInfoRecord : list) { + PurchaseRecordVo purchaseRecordVo = new PurchaseRecordVo(); + purchaseRecordVo.setPurchaseTime(new SimpleDateFormat("MM-dd HH:mm").format(tCourseInfoRecord.getTime())); + purchaseRecordVo.setPurchaseType(tCourseInfoRecord.getName()); + if(tCourseInfoRecord.getType()==1){ + purchaseRecordVo.setPurchaseAmount("+"+tCourseInfoRecord.getNum()); + }else { + purchaseRecordVo.setPurchaseAmount("-"+tCourseInfoRecord.getNum()); + } + list1.add(purchaseRecordVo); + } + purchaseRecordVoList.addAll(list1); if (purchaseRecordVoList.size() > 0 ){ purchaseRecordVoList = purchaseRecordVoList.stream() @@ -441,12 +469,14 @@ packagePayment.setInsertTime(new Date()); couPayClient.savePaymentCoursePackage(packagePayment); + Integer hour = couPayClient.getClassHour(request.getCourseConfigId()); + try { switch (request.getPayType()) { case 1: - return WeChatPayment(code,request.getPayAmount()); + return WeChatPayment(code,request.getPayAmount(),hour); case 2: - return AlipayPayment(code,request.getPayAmount()); + return AlipayPayment(code,request.getPayAmount(),hour); case 3: int i = PlaypaiGoldPayment(code,request); switch (i){ @@ -469,7 +499,7 @@ } - public ResultUtil WeChatPayment(String code,BigDecimal amount) throws Exception { + public ResultUtil WeChatPayment(String code,BigDecimal amount,Integer hour) throws Exception { ResultUtil weixinpay = payMoneyUtil.weixinpay("课包续费", "", code, amount.toString(), "/base/coursePackage/wechatPaymentCallback", "APP", ""); if(weixinpay.getCode() == 200){ @@ -508,6 +538,8 @@ } if("SUCCESS".equals(s)){ coursePackagePayment.setPayStatus(2); + coursePackagePayment.setTotalClassHours(hour); + coursePackagePayment.setLaveClassHours(hour); coursePackagePayment.setOrderNumber(transaction_id); couPayClient.updatePaymentCoursePackage(coursePackagePayment); break; @@ -526,7 +558,7 @@ return weixinpay; } - public ResultUtil AlipayPayment(String code,BigDecimal amount){ + public ResultUtil AlipayPayment(String code,BigDecimal amount,Integer hour){ ResultUtil alipay = payMoneyUtil.alipay("课包续费", "课包续费", "", code, amount.toString(), "/base/coursePackage/alipayPaymentCallback"); if(alipay.getCode() == 200){ @@ -562,6 +594,8 @@ } if("TRADE_SUCCESS".equals(s)){ coursePackagePayment.setPayStatus(2); + coursePackagePayment.setTotalClassHours(hour); + coursePackagePayment.setLaveClassHours(hour); coursePackagePayment.setOrderNumber(tradeNo); couPayClient.updatePaymentCoursePackage(coursePackagePayment); break; diff --git a/cloud-server-activity/mb-cloud-activity.iml b/cloud-server-activity/mb-cloud-activity.iml index 1daccae..13e8572 100644 --- a/cloud-server-activity/mb-cloud-activity.iml +++ b/cloud-server-activity/mb-cloud-activity.iml @@ -1,8 +1,2 @@ <?xml version="1.0" encoding="UTF-8"?> -<module version="4"> - <component name="FacetManager"> - <facet type="Spring" name="Spring"> - <configuration /> - </facet> - </component> -</module> \ No newline at end of file +<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" version="4" /> \ No newline at end of file diff --git a/cloud-server-activity/src/main/java/com/dsh/activity/controller/BenefitVideoController.java b/cloud-server-activity/src/main/java/com/dsh/activity/controller/BenefitVideoController.java index 1ad5527..78a9cad 100644 --- a/cloud-server-activity/src/main/java/com/dsh/activity/controller/BenefitVideoController.java +++ b/cloud-server-activity/src/main/java/com/dsh/activity/controller/BenefitVideoController.java @@ -143,6 +143,24 @@ return ResultUtil.runErr(); } } + @ResponseBody + @PostMapping("/base/benefitsVideo/queryClassificationBenefitsVideosListOne") + @ApiOperation(value = "获取视频列表", tags = {"APP-线上课得积分", "APP-看视频得奖励"}) + @ApiImplicitParams({ + @ApiImplicitParam(value = "位置(1=线上课得积分,2=看视频得奖励)", name = "position", dataType = "int", required = true), + @ApiImplicitParam(value = "搜索内容", name = "search", dataType = "string", required = false), + @ApiImplicitParam(name = "Authorization", value = "用户token(Bearer +token)", required = true, dataType = "String", paramType = "header", defaultValue = "Bearer eyJhbGciOiJIUzUxMiJ9.....") + }) + public ResultUtil<List<BenefitsVideoClassificationListVo>> queryClassificationBenefitsVideosListOne(Integer position, String search){ + try { + Integer uid = -1; + List<BenefitsVideoClassificationListVo> listVos = bfvService.queryClassificationBenefitsVideosListOne(uid, position, search); + return ResultUtil.success(listVos); + }catch (Exception e){ + e.printStackTrace(); + return ResultUtil.runErr(); + } + } @ResponseBody diff --git a/cloud-server-activity/src/main/java/com/dsh/activity/controller/IntroduceRewardsController.java b/cloud-server-activity/src/main/java/com/dsh/activity/controller/IntroduceRewardsController.java index 1c36d9b..1f2dbd0 100644 --- a/cloud-server-activity/src/main/java/com/dsh/activity/controller/IntroduceRewardsController.java +++ b/cloud-server-activity/src/main/java/com/dsh/activity/controller/IntroduceRewardsController.java @@ -1,6 +1,7 @@ package com.dsh.activity.controller; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.dsh.activity.entity.IntroduceRewards; import com.dsh.activity.feignclient.model.IntrduceOfUserRequest; @@ -12,7 +13,9 @@ import java.text.SimpleDateFormat; import java.util.ArrayList; +import java.util.Date; import java.util.List; +import java.util.stream.Collectors; @Api @CrossOrigin @@ -45,4 +48,11 @@ return recordVos; } + @PostMapping("/base/introduce/getGiftList") + public Integer getGiftList(@RequestBody String cityCode){ + List<IntroduceRewards> list = idrService.list(new LambdaQueryWrapper<IntroduceRewards>().eq(IntroduceRewards::getCityCode,cityCode).ge(IntroduceRewards::getStartTime,new Date()).le(IntroduceRewards::getEndTime,new Date())); + int sum = list.stream().mapToInt(IntroduceRewards::getGiveClass).sum(); + return sum; + } + } diff --git a/cloud-server-activity/src/main/java/com/dsh/activity/controller/PointMercharsController.java b/cloud-server-activity/src/main/java/com/dsh/activity/controller/PointMercharsController.java index b9699bb..bcd90d1 100644 --- a/cloud-server-activity/src/main/java/com/dsh/activity/controller/PointMercharsController.java +++ b/cloud-server-activity/src/main/java/com/dsh/activity/controller/PointMercharsController.java @@ -148,6 +148,7 @@ SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd"); ProductDetailsVo detailsVo = new ProductDetailsVo(); PointsMerchandise merchandise = pmdsService.getById(detailRequest.getGoodId()); + detailsVo.setCardType(merchandise.getCardTye()); switch (detailRequest.getGoodsType()){ case 2: // 课包 @@ -370,8 +371,11 @@ SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd"); PointDetailsVo detailsVo = new PointDetailsVo(); UserPointsMerchandise byId = upmseService.getById(speMercharsId); + if (ToolUtil.isNotEmpty(byId)){ PointsMerchandise pmdsServiceById = pmdsService.getById(byId.getPointsMerchandiseId()); + // 2.0 + detailsVo.setCardType(pmdsServiceById.getCardTye()); detailsVo.setExchangeType(pmdsServiceById.getRedemptionMethod()); detailsVo.setGoodType(pmdsServiceById.getType()); if (pmdsServiceById.getRedemptionMethod() == 1){ @@ -434,7 +438,8 @@ } detailsVo.setGoodName(pmdsServiceById.getName()); - detailsVo.setStartTime(simpleDateFormat.format(pmdsServiceById.getStartTime())); + // 2.0 + detailsVo.setStartTime(simpleDateFormat.format(byId.getInsertTime())); detailsVo.setEndTime(simpleDateFormat.format(pmdsServiceById.getEndTime())); detailsVo.setOrderTime(simpleDateFormat.format(byId.getInsertTime())); if (byId.getStatus() == 1){ diff --git a/cloud-server-activity/src/main/java/com/dsh/activity/controller/UserCouponController.java b/cloud-server-activity/src/main/java/com/dsh/activity/controller/UserCouponController.java index b1d407f..ad681fb 100644 --- a/cloud-server-activity/src/main/java/com/dsh/activity/controller/UserCouponController.java +++ b/cloud-server-activity/src/main/java/com/dsh/activity/controller/UserCouponController.java @@ -8,6 +8,7 @@ import com.dsh.activity.feignclient.model.CouponStuAvailableVo; import com.dsh.activity.feignclient.model.QueryUserCouponByIdAndUserId; import com.dsh.activity.model.CouponListVo; +import com.dsh.activity.model.SendCouponReq; import com.dsh.activity.service.CouponStoreService; import com.dsh.activity.service.ICouponService; import com.dsh.activity.service.UserCouponService; @@ -22,6 +23,7 @@ import java.text.SimpleDateFormat; import java.util.ArrayList; +import java.util.Date; import java.util.List; import java.util.Map; import java.util.stream.Collectors; @@ -94,6 +96,16 @@ return cService.queryConponRuleOfJson(couponId); } + @ResponseBody + @PostMapping("/base/userConpon/getCoupons") + public List<Coupon> getCoupons(@RequestBody String couponIds){ + ArrayList<Integer> integers = new ArrayList<>(); + for (String s : couponIds.split(",")) { + Integer integer = Integer.valueOf(s); + integers.add(integer); + } + return cService.list(new LambdaQueryWrapper<Coupon>().in(Coupon::getId,integers)); + } @ResponseBody @@ -167,6 +179,23 @@ } } + @PostMapping("/userCoupon/sendUserCoupon") + public void sendUserCoupon(@RequestBody SendCouponReq sendCouponReq){ + try { + String couponIds = sendCouponReq.getCouponIds(); + for (String s : couponIds.split(",")) { + UserCoupon userCoupon = new UserCoupon(); + userCoupon.setCouponId(Integer.valueOf(s)); + userCoupon.setUserId(sendCouponReq.getUserId()); + userCoupon.setStatus(1); + userCoupon.setInsertTime(new Date()); + userCouponService.save(userCoupon); + } + }catch (Exception e){ + e.printStackTrace(); + } + } + /** * 修改优惠券数据 diff --git a/cloud-server-activity/src/main/java/com/dsh/activity/entity/PointsMerchandise.java b/cloud-server-activity/src/main/java/com/dsh/activity/entity/PointsMerchandise.java index 017a237..a636b6d 100644 --- a/cloud-server-activity/src/main/java/com/dsh/activity/entity/PointsMerchandise.java +++ b/cloud-server-activity/src/main/java/com/dsh/activity/entity/PointsMerchandise.java @@ -163,6 +163,8 @@ */ @TableField("shelves") private Integer shelves; + @TableField("cardTye") + private Integer cardTye; @Override protected Serializable pkVal() { diff --git a/cloud-server-activity/src/main/java/com/dsh/activity/feignclient/model/PointDetailsVo.java b/cloud-server-activity/src/main/java/com/dsh/activity/feignclient/model/PointDetailsVo.java index 9949082..621dfbc 100644 --- a/cloud-server-activity/src/main/java/com/dsh/activity/feignclient/model/PointDetailsVo.java +++ b/cloud-server-activity/src/main/java/com/dsh/activity/feignclient/model/PointDetailsVo.java @@ -59,4 +59,6 @@ @ApiModelProperty(value = "兑换方式(1=积分,2=积分+现金)") private Integer exchangeType; + private Integer cardType; + } diff --git a/cloud-server-activity/src/main/java/com/dsh/activity/feignclient/model/ProductDetailsVo.java b/cloud-server-activity/src/main/java/com/dsh/activity/feignclient/model/ProductDetailsVo.java index 5fe6f2e..d53a2b3 100644 --- a/cloud-server-activity/src/main/java/com/dsh/activity/feignclient/model/ProductDetailsVo.java +++ b/cloud-server-activity/src/main/java/com/dsh/activity/feignclient/model/ProductDetailsVo.java @@ -65,4 +65,7 @@ @ApiModelProperty(value = "商品类型 1实物 2课包 3门票 4优惠券") private Integer goodType; + @ApiModelProperty(value = "1日卡 2月卡 3季卡 4年卡") + private Integer cardType; + } diff --git a/cloud-server-activity/src/main/java/com/dsh/activity/service/BenefitsVideosService.java b/cloud-server-activity/src/main/java/com/dsh/activity/service/BenefitsVideosService.java index 49cf43f..a4602ad 100644 --- a/cloud-server-activity/src/main/java/com/dsh/activity/service/BenefitsVideosService.java +++ b/cloud-server-activity/src/main/java/com/dsh/activity/service/BenefitsVideosService.java @@ -25,6 +25,7 @@ * @throws Exception */ List<BenefitsVideoClassificationListVo> queryClassificationBenefitsVideosList(Integer uid, Integer position, String search) throws Exception; + List<BenefitsVideoClassificationListVo> queryClassificationBenefitsVideosListOne(Integer uid, Integer position, String search) throws Exception; /** diff --git a/cloud-server-activity/src/main/java/com/dsh/activity/service/impl/BenefitsVideosServiceImpl.java b/cloud-server-activity/src/main/java/com/dsh/activity/service/impl/BenefitsVideosServiceImpl.java index 54e5111..f80ffc2 100644 --- a/cloud-server-activity/src/main/java/com/dsh/activity/service/impl/BenefitsVideosServiceImpl.java +++ b/cloud-server-activity/src/main/java/com/dsh/activity/service/impl/BenefitsVideosServiceImpl.java @@ -103,6 +103,42 @@ } return listVos; } + @Override + public List<BenefitsVideoClassificationListVo> queryClassificationBenefitsVideosListOne(Integer uid, Integer position, String search) throws Exception { + QueryWrapper<BenefitsVideoClassification> wrapper = new QueryWrapper<BenefitsVideoClassification>().eq("position", position); + if(ToolUtil.isNotEmpty(search)){ + wrapper.like("name", search); + } + List<BenefitsVideoClassification> list = benefitsVideoClassificationService.list(wrapper.orderByAsc("sort")); + List<UserBenefitsVideos> userBenefitsVideos = userBenefitsVideosService.list(new QueryWrapper<UserBenefitsVideos>().eq("appUserId", -1)); + List<Integer> collect = userBenefitsVideos.stream().map(UserBenefitsVideos::getBenefitsVideosId).collect(Collectors.toList()); + + List<BenefitsVideoClassificationListVo> listVos = new ArrayList<>(); + for (BenefitsVideoClassification benefitsVideoClassification : list) { + BenefitsVideoClassificationListVo benefitsVideoClassificationListVo = new BenefitsVideoClassificationListVo(); + benefitsVideoClassificationListVo.setId(benefitsVideoClassification.getId()); + benefitsVideoClassificationListVo.setName(benefitsVideoClassification.getName()); + QueryWrapper<BenefitsVideos> benefitsVideosQueryWrapper = new QueryWrapper<BenefitsVideos>().eq("state", 1); + if(collect.size() > 0){ + benefitsVideosQueryWrapper.notIn("id", collect); + } + List<BenefitsVideos> list1 = this.list(benefitsVideosQueryWrapper.orderByDesc("insertTime").last(" limit 0, 4")); + List<BenefitsVideosListVo> lists = new ArrayList<>(); + for (BenefitsVideos benefitsVideos : list1) { + Integer courseId = benefitsVideos.getCourseId(); + Course course = courseClient.queryCourseById(courseId); + BenefitsVideosListVo benefitsVideosListVo = new BenefitsVideosListVo(); + benefitsVideosListVo.setId(benefitsVideos.getId()); + benefitsVideosListVo.setName(course.getName()); + benefitsVideosListVo.setCover(course.getCoverDrawing()); + benefitsVideosListVo.setIntroduce(course.getIntroduce()); + lists.add(benefitsVideosListVo); + } + benefitsVideoClassificationListVo.setList(lists); + listVos.add(benefitsVideoClassificationListVo); + } + return listVos; + } @Override diff --git a/cloud-server-auth/mb-cloud-auth.iml b/cloud-server-auth/mb-cloud-auth.iml index 1daccae..13e8572 100644 --- a/cloud-server-auth/mb-cloud-auth.iml +++ b/cloud-server-auth/mb-cloud-auth.iml @@ -1,8 +1,2 @@ <?xml version="1.0" encoding="UTF-8"?> -<module version="4"> - <component name="FacetManager"> - <facet type="Spring" name="Spring"> - <configuration /> - </facet> - </component> -</module> \ No newline at end of file +<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" version="4" /> \ No newline at end of file diff --git a/cloud-server-competition/mb-cloud-competition.iml b/cloud-server-competition/mb-cloud-competition.iml index 1daccae..13e8572 100644 --- a/cloud-server-competition/mb-cloud-competition.iml +++ b/cloud-server-competition/mb-cloud-competition.iml @@ -1,8 +1,2 @@ <?xml version="1.0" encoding="UTF-8"?> -<module version="4"> - <component name="FacetManager"> - <facet type="Spring" name="Spring"> - <configuration /> - </facet> - </component> -</module> \ No newline at end of file +<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" version="4" /> \ No newline at end of file diff --git a/cloud-server-competition/src/main/java/com/dsh/competition/controller/CompetitionController.java b/cloud-server-competition/src/main/java/com/dsh/competition/controller/CompetitionController.java index e82c819..f613014 100644 --- a/cloud-server-competition/src/main/java/com/dsh/competition/controller/CompetitionController.java +++ b/cloud-server-competition/src/main/java/com/dsh/competition/controller/CompetitionController.java @@ -204,6 +204,7 @@ @ApiOperation(value = "赛事报名", tags = {"APP-赛事活动列表"}) @ApiImplicitParams({ @ApiImplicitParam(name = "Authorization", value = "用户token(Bearer +token)", required = true, dataType = "String", paramType = "header", defaultValue = "Bearer eyJhbGciOiJIUzUxMiJ9.....") + }) public ResultUtil paymentCompetition(PaymentCompetitionVo paymentCompetitionVo){ try { @@ -217,6 +218,25 @@ return ResultUtil.runErr(); } } + @ResponseBody + @PostMapping("/api/competition/paymentCompetitionCourseList") + @ApiOperation(value = "赛事报名--支付可用课时列表", tags = {"APP-赛事活动列表"}) + @ApiImplicitParams({ + @ApiImplicitParam(name = "Authorization", value = "用户token(Bearer +token)", required = true, dataType = "String", paramType = "header", defaultValue = "Bearer eyJhbGciOiJIUzUxMiJ9....."), + @ApiImplicitParam(value = "赛事id", name = "id", dataType = "int", required = true), + }) + public ResultUtil paymentCompetitionCourseList(Integer id){ + try { + Integer uid = tokenUtil.getUserIdFormRedis(); + if(null == uid){ + return ResultUtil.tokenErr(); + } + return cttService.paymentCompetitionCourseList(uid, id); + }catch (Exception e){ + e.printStackTrace(); + return ResultUtil.runErr(); + } + } /** diff --git a/cloud-server-competition/src/main/java/com/dsh/competition/entity/Competition.java b/cloud-server-competition/src/main/java/com/dsh/competition/entity/Competition.java index 100aa2e..8ff9be6 100644 --- a/cloud-server-competition/src/main/java/com/dsh/competition/entity/Competition.java +++ b/cloud-server-competition/src/main/java/com/dsh/competition/entity/Competition.java @@ -59,7 +59,7 @@ * 门店id */ @TableField("storeId") - private Integer storeId; + private String storeId; /** * 赛事名称 */ diff --git a/cloud-server-competition/src/main/java/com/dsh/competition/feignclient/course/CoursePackagePaymentClient.java b/cloud-server-competition/src/main/java/com/dsh/competition/feignclient/course/CoursePackagePaymentClient.java index 6bad81e..184cd77 100644 --- a/cloud-server-competition/src/main/java/com/dsh/competition/feignclient/course/CoursePackagePaymentClient.java +++ b/cloud-server-competition/src/main/java/com/dsh/competition/feignclient/course/CoursePackagePaymentClient.java @@ -1,8 +1,12 @@ package com.dsh.competition.feignclient.course; import com.dsh.competition.feignclient.course.model.PaymentDeductionClassHour; +import com.dsh.competition.model.PayCourseRes; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; + +import java.util.List; /** * @author zhibing.pu @@ -21,6 +25,10 @@ Integer queryResidueClassHour(Integer id); + @PostMapping("/coursePackagePayment/queryResidueClassHourById") + Integer queryResidueClassHourById(Long id); + + /** * 支付扣减学员课时 */ @@ -34,4 +42,9 @@ */ @PostMapping("/coursePackagePayment/rollbackPaymentDeductionClassHour") void rollbackPaymentDeductionClassHour(PaymentDeductionClassHour paymentDeductionClassHour); + + @PostMapping("/coursePackagePayment/paymentCompetitionCourseList") + List<PayCourseRes> paymentCompetitionCourseList(String s); + + } diff --git a/cloud-server-competition/src/main/java/com/dsh/competition/feignclient/course/model/PaymentDeductionClassHour.java b/cloud-server-competition/src/main/java/com/dsh/competition/feignclient/course/model/PaymentDeductionClassHour.java index eb83edf..e8dc41d 100644 --- a/cloud-server-competition/src/main/java/com/dsh/competition/feignclient/course/model/PaymentDeductionClassHour.java +++ b/cloud-server-competition/src/main/java/com/dsh/competition/feignclient/course/model/PaymentDeductionClassHour.java @@ -20,4 +20,8 @@ * 支付编号 */ private String code; + /** + * 用于支付的课程 + */ + private Long courseId; } diff --git a/cloud-server-competition/src/main/java/com/dsh/competition/model/CompetitionInfo.java b/cloud-server-competition/src/main/java/com/dsh/competition/model/CompetitionInfo.java index bbc3cc6..bd251ec 100644 --- a/cloud-server-competition/src/main/java/com/dsh/competition/model/CompetitionInfo.java +++ b/cloud-server-competition/src/main/java/com/dsh/competition/model/CompetitionInfo.java @@ -5,6 +5,7 @@ import lombok.Data; import java.util.List; +import java.util.Map; /** * @author zhibing.pu @@ -67,4 +68,6 @@ private Double payMoney; @ApiModelProperty("支付方式(1=微信,2=支付宝,3=玩湃币,4=课时)") private Integer payType; + @ApiModelProperty("门店信息") + private List<Map<String,Object>> storeInfos; } diff --git a/cloud-server-competition/src/main/java/com/dsh/competition/model/PaymentCompetitionVo.java b/cloud-server-competition/src/main/java/com/dsh/competition/model/PaymentCompetitionVo.java index 0d0a6d5..e03bd06 100644 --- a/cloud-server-competition/src/main/java/com/dsh/competition/model/PaymentCompetitionVo.java +++ b/cloud-server-competition/src/main/java/com/dsh/competition/model/PaymentCompetitionVo.java @@ -17,4 +17,6 @@ private String ids; @ApiModelProperty(value = "支付方式(1=微信,2=支付宝,3=余额,4=课时)", dataType = "int", required = true) private Integer payType; + @ApiModelProperty(value = "我的购买课包id") + private Long coursePaymentId; } diff --git a/cloud-server-competition/src/main/java/com/dsh/competition/service/CompetitionService.java b/cloud-server-competition/src/main/java/com/dsh/competition/service/CompetitionService.java index 85cdbdd..61efa07 100644 --- a/cloud-server-competition/src/main/java/com/dsh/competition/service/CompetitionService.java +++ b/cloud-server-competition/src/main/java/com/dsh/competition/service/CompetitionService.java @@ -53,4 +53,14 @@ * 定时任务修改赛事状态 */ void taskSetStatus(); + + /** + * 赛事可用课包 + * @param uid + * @param id + * @return + */ + ResultUtil paymentCompetitionCourseList(Integer uid, Integer id); + + } diff --git a/cloud-server-competition/src/main/java/com/dsh/competition/service/impl/CompetitionServiceImpl.java b/cloud-server-competition/src/main/java/com/dsh/competition/service/impl/CompetitionServiceImpl.java index 74c35c7..77267b3 100644 --- a/cloud-server-competition/src/main/java/com/dsh/competition/service/impl/CompetitionServiceImpl.java +++ b/cloud-server-competition/src/main/java/com/dsh/competition/service/impl/CompetitionServiceImpl.java @@ -16,10 +16,7 @@ import com.dsh.competition.feignclient.other.StoreClient; import com.dsh.competition.feignclient.other.model.Store; import com.dsh.competition.mapper.CompetitionMapper; -import com.dsh.competition.model.CompetitionInfo; -import com.dsh.competition.model.CompetitionListVo; -import com.dsh.competition.model.ParticipantVo; -import com.dsh.competition.model.PaymentCompetitionVo; +import com.dsh.competition.model.*; import com.dsh.competition.service.CompetitionService; import com.dsh.competition.service.IParticipantService; import com.dsh.competition.service.IPaymentCompetitionService; @@ -32,10 +29,7 @@ import java.math.BigDecimal; import java.math.RoundingMode; import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.stream.Collectors; /** @@ -104,19 +98,30 @@ competitionInfo.setImgs(competition.getImgs()); competitionInfo.setName(competition.getName()); competitionInfo.setRegisterCondition(competition.getRegisterCondition()); + + // 2.0 + ArrayList<Map<String,Object>> objects = new ArrayList<>(); if(null != competition.getStoreId()){ - Store store = storeClient.queryStoreById(competition.getStoreId()); - competitionInfo.setStoreName(store.getName()); - competitionInfo.setStoreAddress(store.getAddress()); - competitionInfo.setStoreLon(store.getLon()); - competitionInfo.setStoreLat(store.getLat()); - competitionInfo.setStoreCoverDrawing(store.getCoverDrawing()); - if(ToolUtil.isNotEmpty(lon) && ToolUtil.isNotEmpty(lat)){ - Map<String, Double> distance = GeodesyUtil.getDistance(lon + "," + lat, store.getLon() + "," + store.getLat()); - double wgs84 = new BigDecimal(distance.get("WGS84")).divide(new BigDecimal(1000)).setScale(2, RoundingMode.HALF_EVEN).doubleValue(); - competitionInfo.setDistance(wgs84); + HashMap<String, Object> map = new HashMap<>(); + String storeId = competition.getStoreId(); + for (String s : storeId.split(",")) { + Store store = storeClient.queryStoreById(Integer.valueOf(s)); + map.put("name",store.getName()); + map.put("address",store.getAddress()); + map.put("storeLon",store.getLon()); + map.put("storeLat",store.getLat()); + map.put("storeCoverDrawing",store.getCoverDrawing()); + if(ToolUtil.isNotEmpty(lon) && ToolUtil.isNotEmpty(lat)){ + Map<String, Double> distance = GeodesyUtil.getDistance(lon + "," + lat, store.getLon() + "," + store.getLat()); + double wgs84 = new BigDecimal(distance.get("WGS84")).divide(new BigDecimal(1000)).setScale(2, RoundingMode.HALF_EVEN).doubleValue(); + map.put("distance",wgs84); + } } + objects.add(map); } + competitionInfo.setStoreInfos(objects); + + competitionInfo.setRegisterEndTime(sdf.format(competition.getRegisterEndTime())); competitionInfo.setStartTime(sdf.format(competition.getStartTime())); competitionInfo.setEndTime(sdf.format(competition.getEndTime())); @@ -187,7 +192,8 @@ if(null == student){ return ResultUtil.error(participant.getName() + "不是学员,无法使用课时支付。"); } - Integer integer = coursePackagePaymentClient.queryResidueClassHour(student.getId()); + // 2.0 + Integer integer = coursePackagePaymentClient.queryResidueClassHourById(paymentCompetitionVo.getCoursePaymentId()); if(new BigDecimal(integer).compareTo(new BigDecimal(competition.getClassPrice())) < 0){ return ResultUtil.error(participant.getName() + "剩余课时不足,无法完成支付。"); } @@ -245,6 +251,7 @@ paymentDeductionClassHour.setId(student.getId()); paymentDeductionClassHour.setClassHour(competition.getClassPrice()); paymentDeductionClassHour.setCode(code); + paymentDeductionClassHour.setCourseId(paymentCompetitionVo.getCoursePaymentId()); coursePackagePaymentClient.paymentDeductionClassHour(paymentDeductionClassHour); } paymentCompetition = paymentCompetitionService.getById(paymentCompetition.getId()); @@ -400,4 +407,14 @@ this.baseMapper.taskSetStatusStart(); this.baseMapper.taskSetStatusEnd(); } + + @Override + public ResultUtil paymentCompetitionCourseList(Integer uid, Integer id) { + Competition competition = this.baseMapper.selectById(id); + // 获取门店id 找出符合这些门店的课包 + String storeId = competition.getStoreId(); + + List<PayCourseRes> list = coursePackagePaymentClient.paymentCompetitionCourseList(uid+"_"+storeId); + return ResultUtil.success(list); + } } diff --git a/cloud-server-competition/src/main/java/com/dsh/competition/service/impl/PaymentCompetitionServiceImpl.java b/cloud-server-competition/src/main/java/com/dsh/competition/service/impl/PaymentCompetitionServiceImpl.java index fbde07c..3f62769 100644 --- a/cloud-server-competition/src/main/java/com/dsh/competition/service/impl/PaymentCompetitionServiceImpl.java +++ b/cloud-server-competition/src/main/java/com/dsh/competition/service/impl/PaymentCompetitionServiceImpl.java @@ -106,7 +106,7 @@ competitionInfo.setImgs(competition.getImgs()); competitionInfo.setName(competition.getName()); competitionInfo.setRegisterCondition(competition.getRegisterCondition()); - Store store = storeClient.queryStoreById(competition.getStoreId()); + Store store = storeClient.queryStoreById(Integer.valueOf(competition.getStoreId().split(",")[0])); competitionInfo.setStoreName(store.getName()); competitionInfo.setStoreAddress(store.getAddress()); competitionInfo.setStoreLon(store.getLon()); diff --git a/cloud-server-course/mb-cloud-course.iml b/cloud-server-course/mb-cloud-course.iml index 1daccae..5890c76 100644 --- a/cloud-server-course/mb-cloud-course.iml +++ b/cloud-server-course/mb-cloud-course.iml @@ -1,8 +1,18 @@ <?xml version="1.0" encoding="UTF-8"?> -<module version="4"> +<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" version="4"> <component name="FacetManager"> <facet type="Spring" name="Spring"> <configuration /> </facet> + <facet type="jpa" name="JPA"> + <configuration> + <setting name="validation-enabled" value="true" /> + <setting name="provider-name" value="Hibernate" /> + <datasource-mapping> + <factory-entry name="entityManagerFactory" /> + </datasource-mapping> + <naming-strategy-map /> + </configuration> + </facet> </component> </module> \ No newline at end of file diff --git a/cloud-server-course/src/main/java/com/dsh/course/controller/CourseController.java b/cloud-server-course/src/main/java/com/dsh/course/controller/CourseController.java index f885da2..d23a26e 100644 --- a/cloud-server-course/src/main/java/com/dsh/course/controller/CourseController.java +++ b/cloud-server-course/src/main/java/com/dsh/course/controller/CourseController.java @@ -134,7 +134,6 @@ - @ResponseBody @PostMapping("/api/course/queryCourseList") @ApiOperation(value = "获取课程列表", tags = {"APP-课程列表"}) @@ -148,6 +147,23 @@ return ResultUtil.tokenErr(); } List<CoursePackageListVo> coursePackageListVos = coursePackageService.queryCourseList(uid, coursePackageList); + return ResultUtil.success(coursePackageListVos); + }catch (Exception e){ + e.printStackTrace(); + return ResultUtil.runErr(); + } + } + + + @ResponseBody + @PostMapping("/base/course/queryCourseListOne") + @ApiOperation(value = "获取课程列表", tags = {"APP-课程列表"}) + @ApiImplicitParams({ + @ApiImplicitParam(name = "Authorization", value = "用户token(Bearer +token)", required = true, dataType = "String", paramType = "header", defaultValue = "Bearer eyJhbGciOiJIUzUxMiJ9.....") + }) + public ResultUtil<List<CoursePackageListVo>> queryCourseListOne(CoursePackageList coursePackageList){ + try { + List<CoursePackageListVo> coursePackageListVos = coursePackageService.queryCourseListOne( coursePackageList); return ResultUtil.success(coursePackageListVos); }catch (Exception e){ e.printStackTrace(); @@ -203,6 +219,26 @@ } } + // 2.0 + @ResponseBody + @PostMapping("/api/course/paymentCourseCouponList") + @ApiOperation(value = "支付课程--完成后优惠券列表", tags = {"APP-课程列表"}) + @ApiImplicitParams({ + @ApiImplicitParam(name = "Authorization", value = "用户token(Bearer +token)", required = true, dataType = "String", paramType = "header", defaultValue = "Bearer eyJhbGciOiJIUzUxMiJ9.....") + }) + public ResultUtil paymentCourseCouponList(Integer coursePackagePaymentConfigId){ + try { + Integer uid = tokenUtil.getUserIdFormRedis(); + if(null == uid){ + return ResultUtil.tokenErr(); + } + return coursePackageService.paymentCourseCouponList(uid, coursePackagePaymentConfigId); + }catch (Exception e){ + e.printStackTrace(); + return ResultUtil.runErr(); + } + } + /** * 购买课程微信支付回调 diff --git a/cloud-server-course/src/main/java/com/dsh/course/controller/CoursePackagePaymentController.java b/cloud-server-course/src/main/java/com/dsh/course/controller/CoursePackagePaymentController.java index a5bbd2e..c350bf2 100644 --- a/cloud-server-course/src/main/java/com/dsh/course/controller/CoursePackagePaymentController.java +++ b/cloud-server-course/src/main/java/com/dsh/course/controller/CoursePackagePaymentController.java @@ -1,6 +1,8 @@ package com.dsh.course.controller; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; @@ -9,6 +11,7 @@ import com.dsh.course.feignclient.account.StudentClient; import com.dsh.course.feignclient.account.model.AppUser; import com.dsh.course.feignclient.account.model.Student; +import com.dsh.course.feignclient.account.model.TCourseInfoRecord; import com.dsh.course.feignclient.model.*; import com.dsh.course.feignclient.other.StoreClient; import com.dsh.course.feignclient.other.model.Store; @@ -21,9 +24,7 @@ import com.dsh.course.model.vo.CourseDetailRequest; import com.dsh.course.model.vo.RegisterCourseVo; import com.dsh.course.model.vo.request.*; -import com.dsh.course.model.vo.response.AppUserVideoResponse; -import com.dsh.course.model.vo.response.CourseDetailsResponse; -import com.dsh.course.model.vo.response.CourseOfVideoResponse; +import com.dsh.course.model.vo.response.*; import com.dsh.course.service.*; import com.dsh.course.util.*; import com.fasterxml.jackson.core.JsonProcessingException; @@ -36,7 +37,10 @@ import org.slf4j.LoggerFactory; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.*; +import org.springframework.web.client.RestTemplate; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; @@ -102,6 +106,13 @@ @Resource private StoreClient sreClient; + + @Autowired + private AppUserClient appUserClient; + + @Autowired + private RestTemplate internalRestTemplate; + private final SimpleDateFormat format = new SimpleDateFormat("MM-dd HH:mm"); @@ -185,6 +196,11 @@ storeVo.setLon(store.getLon()); storeVo.setCoursePrice(ToolUtil.isEmpty(paymentConfig.getCashPayment()) ? (double) paymentConfig.getPlayPaiCoin():paymentConfig.getCashPayment()); storeVo.setStatus(1); + // 2.0 + storeVo.setAllNum(tCoursePackagePayment.getTotalClassHours()); + storeVo.setLastNum(tCoursePackagePayment.getLaveClassHours()); + storeVo.setUseNum(tCoursePackagePayment.getTotalClassHours()-tCoursePackagePayment.getLaveClassHours()); + course.add(storeVo); } } @@ -484,6 +500,59 @@ } + @ResponseBody + @PostMapping("/api/startCource/payCourseInfo") + @ApiOperation(value = "课后练习-购课详情(用于购课)", tags = {"APP-开始上课"}) + @ApiImplicitParams({ + @ApiImplicitParam(name = "Authorization", value = "Bearer +token", required = true, dataType = "String", paramType = "header", defaultValue = "Bearer eyJhbGciOiJIUzUxMiJ9....."), + }) + public ResultUtil<PayCourseInfoReq> payCourseInfo(Integer courseId){ + try { + return ResultUtil.success(packagePaymentService.payCourseInfo(courseId)); + }catch (Exception e){ + return ResultUtil.runErr(); + } + } + + + @ResponseBody + @PostMapping("/api/startCource/getMyCourseList") + @ApiOperation(value = "课后练习-可支付课程列表(用于购课)", tags = {"APP-开始上课"}) + @ApiImplicitParams({ + @ApiImplicitParam(name = "Authorization", value = "Bearer +token", required = true, dataType = "String", paramType = "header", defaultValue = "Bearer eyJhbGciOiJIUzUxMiJ9....."), + }) + public ResultUtil<List<PayCourseRes>> getMyCourseList(Integer storeId){ + try { + Integer appUserId = tokenUtil.getUserIdFormRedis(); + if(null == appUserId){ + return ResultUtil.tokenErr(); + } + return ResultUtil.success(packagePaymentService.getMyCourseList(storeId,appUserId)); + }catch (Exception e){ + return ResultUtil.runErr(); + } + } + + // 2.0 + @ResponseBody + @PostMapping("/api/startCource/payCourse") + @ApiOperation(value = "课后练习-确认购课", tags = {"APP-开始上课"}) + @ApiImplicitParams({ + @ApiImplicitParam(name = "Authorization", value = "Bearer +token", required = true, dataType = "String", paramType = "header", defaultValue = "Bearer eyJhbGciOiJIUzUxMiJ9....."), + }) + public ResultUtil<?> payCourse(@RequestBody PayCourseReq req){ + try { + Integer appUserId = tokenUtil.getUserIdFormRedis(); + if(null == appUserId){ + return ResultUtil.tokenErr(); + } + return packagePaymentService.payCourse(req,appUserId); + }catch (Exception e){ + return ResultUtil.runErr(); + } + } + + /** * 更新课后视频学习状态 */ @@ -671,6 +740,22 @@ return 0; } } + /** + * 获取学员剩余课时 + * @param id + * @return + */ + @ResponseBody + @PostMapping("/coursePackagePayment/queryResidueClassHourById") + public Integer queryResidueClassHourById(@RequestBody Long id){ + try { + TCoursePackagePayment list = packagePaymentService.getById(id); + return list.getLaveClassHours(); + }catch (Exception e){ + e.printStackTrace(); + return 0; + } + } /** @@ -681,13 +766,31 @@ @PostMapping("/coursePackagePayment/paymentDeductionClassHour") public void paymentDeductionClassHour(@RequestBody PaymentDeductionClassHour paymentDeductionClassHour){ try { - List<TCoursePackagePayment> list = packagePaymentService.list(new QueryWrapper<TCoursePackagePayment>().eq("studentId", paymentDeductionClassHour.getId()).eq("payStatus", 2) + // 2.0 用id进行查询 + List<TCoursePackagePayment> list = packagePaymentService.list(new QueryWrapper<TCoursePackagePayment>().eq("id", paymentDeductionClassHour.getCourseId()).eq("payStatus", 2) .eq("status", 1).eq("state", 1).gt("laveClassHours", 0)); Integer classHour = paymentDeductionClassHour.getClassHour(); for (TCoursePackagePayment coursePackagePayment : list) { if(coursePackagePayment.getLaveClassHours().compareTo(classHour) >= 0){ coursePackagePayment.setLaveClassHours(coursePackagePayment.getLaveClassHours() - classHour); packagePaymentService.updateById(coursePackagePayment); + + // 2.0 少于3课时 推送 + if(coursePackagePayment.getLaveClassHours()<=3){ + Integer appUserId = coursePackagePayment.getAppUserId(); + + //调用推送 + HttpHeaders headers = new HttpHeaders(); + // 以表单的方式提交 + headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); + String s1 = appUserId + "_" + "Three"; + //定时修改排课状态 + String s = internalRestTemplate.getForObject("http://mb-cloud-gateway/netty/sendMsgToClient?id="+s1, String.class); + JSONObject jsonObject1 = JSON.parseObject(s, JSONObject.class); + if(jsonObject1.getIntValue("code") != 200){ + System.err.println(jsonObject1.getString("msg")); + } + } CancelledClasses cancelledClasses = new CancelledClasses(); cancelledClasses.setType(2); @@ -743,6 +846,42 @@ /** + * 找出符合门店的课包 + * @param s + * @return + */ + @ResponseBody + @PostMapping("/coursePackagePayment/paymentCompetitionCourseList") + public List<PayCourseRes> paymentCompetitionCourseList(@RequestBody String s){ + ArrayList<PayCourseRes> objects = new ArrayList<>(); + + String[] split = s.split("_"); + // 用户id + Integer integer = Integer.valueOf(split[0]); + String s1 = split[1]; + // 门店id + String[] split1 = s1.split(","); + ArrayList<Integer> storeIds = new ArrayList<>(); + for (String s2 : split1) { + storeIds.add(Integer.valueOf(s2)); + } + List<TCoursePackagePayment> list = packagePaymentService.list(new LambdaQueryWrapper<TCoursePackagePayment>().eq(TCoursePackagePayment::getAppUserId, integer).ge(TCoursePackagePayment::getLaveClassHours, 0).eq(TCoursePackagePayment::getStatus, 1).eq(TCoursePackagePayment::getState, 1)); + for (TCoursePackagePayment tCoursePackagePayment : list) { + Integer coursePackageId = tCoursePackagePayment.getCoursePackageId(); + TCoursePackage byId = tcpService.getById(coursePackageId); + if(storeIds.contains(byId.getStoreId())){ + PayCourseRes payCourseRes = new PayCourseRes(); + payCourseRes.setCourseNum(tCoursePackagePayment.getLaveClassHours()); + payCourseRes.setId(tCoursePackagePayment.getId()); + payCourseRes.setName(byId.getName()); + objects.add(payCourseRes); + } + } + return objects; + } + + + /** * 课包续费玩湃币支付 * @param */ @@ -770,6 +909,16 @@ appUser.setPlayPaiCoins(appUser.getPlayPaiCoins()-paymentConfig.getPlayPaiCoin()); auClitn.updateAppUser(appUser); + + // 2.0 + TCourseInfoRecord tCourseInfoRecord = new TCourseInfoRecord(); + tCourseInfoRecord.setUserId(userIdFormRedis); + tCourseInfoRecord.setCourseId(coursePackage.getCoursePackageId()); + tCourseInfoRecord.setName("续课"); + tCourseInfoRecord.setTime(new Date()); + tCourseInfoRecord.setType(1); + tCourseInfoRecord.setNum(paymentConfig.getClassHours()); + auClitn.addCourseInfoRecord(tCourseInfoRecord); } catch (Exception e) { return 4; } @@ -788,8 +937,20 @@ } @PostMapping("/base/coursePack/updatePaymentCoursePackage") public boolean updatePaymentCoursePackage(@RequestBody TCoursePackagePayment packagePayment){ - return packagePaymentService.update(packagePayment,new QueryWrapper<TCoursePackagePayment>() - .eq("id",packagePayment.getId())); + boolean id = packagePaymentService.update(packagePayment, new QueryWrapper<TCoursePackagePayment>() + .eq("id", packagePayment.getId())); + if(id){ + // 2.0 + TCourseInfoRecord tCourseInfoRecord = new TCourseInfoRecord(); + tCourseInfoRecord.setNum(packagePayment.getTotalClassHours()); + tCourseInfoRecord.setName("续课"); + tCourseInfoRecord.setCourseId(packagePayment.getCoursePackageId()); + tCourseInfoRecord.setUserId(packagePayment.getAppUserId()); + tCourseInfoRecord.setType(1); + tCourseInfoRecord.setTime(new Date()); + id = appUserClient.addCourseInfoRecord(tCourseInfoRecord); + } + return id; } @PostMapping("/base/coursePack/savePaymentCoursePackage") @@ -824,6 +985,27 @@ .eq("code",code)); } + + // 2.0 送课时 + @PostMapping("/base/coursePack/sendHours") + public Boolean sendHours(@RequestBody String s){ + String[] split = s.split("_"); + TCoursePackagePayment byId = packagePaymentService.getById(Integer.valueOf(split[0])); + byId.setTotalClassHours(byId.getTotalClassHours()+Integer.valueOf(split[2])); + return packagePaymentService.updateById(byId); + } + + + /** + * 查询课时 + * @param courseConfigId + * @return + */ + @PostMapping("/base/coursePack/getClassHour") + public Integer getClassHour(@RequestBody Integer courseConfigId){ + CoursePackagePaymentConfig byId = icppcService.getById(courseConfigId); + return byId.getClassHours(); + } /** * 获取课包报名信息列表 @@ -881,7 +1063,7 @@ */ @ResponseBody @PostMapping("/api/startCource/reverse") - @ApiOperation(value = "上课主页-预约操作", tags = {"APP-开始上课"}) + @ApiOperation(value = "上课主页-预约操作--2.0改请假操作", tags = {"APP-开始上课"}) @ApiImplicitParams({ @ApiImplicitParam(name = "Authorization", value = "Bearer +token", required = true, dataType = "String", paramType = "header", defaultValue = "Bearer eyJhbGciOiJIUzUxMiJ9....."), @ApiImplicitParam(value = "课包id", name = "courseID", required = true, dataType = "String"), @@ -912,7 +1094,7 @@ ); if (ToolUtil.isNotEmpty(coursePackageStudent) && coursePackageStudent.getReservationStatus() == 0){ - coursePackageStudent.setReservationStatus(1); + coursePackageStudent.setSignInOrNot(2); coursePackageStudent.setInsertTime(simpleDateFormat.parse(time)); cspsService.updateById(coursePackageStudent); }else { @@ -921,7 +1103,7 @@ coursePackageStudent.setStudentId(stuId); coursePackageStudent.setCoursePackageId(packagePayment.getCoursePackageId()); coursePackageStudent.setCoursePackagePaymentId(Long.parseLong(courseID)); - coursePackageStudent.setReservationStatus(1); + coursePackageStudent.setSignInOrNot(2); coursePackageStudent.setInsertTime(simpleDateFormat.parse(time)); cspsService.save(coursePackageStudent); } diff --git a/cloud-server-course/src/main/java/com/dsh/course/entity/CoursePackagePaymentConfig.java b/cloud-server-course/src/main/java/com/dsh/course/entity/CoursePackagePaymentConfig.java index 1b9c125..41ad552 100644 --- a/cloud-server-course/src/main/java/com/dsh/course/entity/CoursePackagePaymentConfig.java +++ b/cloud-server-course/src/main/java/com/dsh/course/entity/CoursePackagePaymentConfig.java @@ -38,4 +38,6 @@ */ @TableField("playPaiCoin") private Integer playPaiCoin; + @TableField("couponIds") + private String couponIds; } diff --git a/cloud-server-course/src/main/java/com/dsh/course/entity/TCoursePackage.java b/cloud-server-course/src/main/java/com/dsh/course/entity/TCoursePackage.java index 5eddca4..96faab9 100644 --- a/cloud-server-course/src/main/java/com/dsh/course/entity/TCoursePackage.java +++ b/cloud-server-course/src/main/java/com/dsh/course/entity/TCoursePackage.java @@ -159,5 +159,9 @@ @TableField("insertTime") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") private Date insertTime; + @TableField("type") + private Integer type; + @TableField("needNum") + private Integer needNum; } diff --git a/cloud-server-course/src/main/java/com/dsh/course/feignclient/account/AppUserClient.java b/cloud-server-course/src/main/java/com/dsh/course/feignclient/account/AppUserClient.java index ccfb109..7f68da6 100644 --- a/cloud-server-course/src/main/java/com/dsh/course/feignclient/account/AppUserClient.java +++ b/cloud-server-course/src/main/java/com/dsh/course/feignclient/account/AppUserClient.java @@ -1,6 +1,7 @@ package com.dsh.course.feignclient.account; import com.dsh.course.feignclient.account.model.AppUser; +import com.dsh.course.feignclient.account.model.TCourseInfoRecord; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.PostMapping; @@ -37,4 +38,10 @@ */ @PostMapping("/appUser/queryAppUserListByName") List<AppUser> queryAppUserListByName(String name); + + + @PostMapping("/appUser/addCourseInfoRecord") + Boolean addCourseInfoRecord(TCourseInfoRecord tCourseInfoRecord); + + } diff --git a/cloud-server-course/src/main/java/com/dsh/course/feignclient/activity/CouponClient.java b/cloud-server-course/src/main/java/com/dsh/course/feignclient/activity/CouponClient.java index 14d78a6..133f103 100644 --- a/cloud-server-course/src/main/java/com/dsh/course/feignclient/activity/CouponClient.java +++ b/cloud-server-course/src/main/java/com/dsh/course/feignclient/activity/CouponClient.java @@ -5,6 +5,7 @@ import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; +import java.util.List; import java.util.Map; /** @@ -25,4 +26,9 @@ @PostMapping("/base/userConpon/queryCouponRules") Map<String,Object> getCouponRules(@RequestBody Integer couponId); + + @PostMapping("/base/userConpon/getCoupons") + List<Coupon> getCoupons(String couponIds); + + } diff --git a/cloud-server-course/src/main/java/com/dsh/course/feignclient/activity/UserCouponClient.java b/cloud-server-course/src/main/java/com/dsh/course/feignclient/activity/UserCouponClient.java index 4e4b546..704dc64 100644 --- a/cloud-server-course/src/main/java/com/dsh/course/feignclient/activity/UserCouponClient.java +++ b/cloud-server-course/src/main/java/com/dsh/course/feignclient/activity/UserCouponClient.java @@ -1,5 +1,6 @@ package com.dsh.course.feignclient.activity; +import com.dsh.course.feignclient.activity.model.SendCouponReq; import com.dsh.course.feignclient.activity.model.UserCoupon; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.PostMapping; @@ -19,4 +20,11 @@ */ @PostMapping("/userCoupon/queryUserCouponById") UserCoupon queryUserCouponById(Long id); + + /** + * 送优惠券 + * @param sendCouponReq + */ + @PostMapping("/userCoupon/sendUserCoupon") + void sendUserCoupon(SendCouponReq sendCouponReq); } diff --git a/cloud-server-course/src/main/java/com/dsh/course/feignclient/model/CourseOfStoreVo.java b/cloud-server-course/src/main/java/com/dsh/course/feignclient/model/CourseOfStoreVo.java index b2ca79c..9fe5fe3 100644 --- a/cloud-server-course/src/main/java/com/dsh/course/feignclient/model/CourseOfStoreVo.java +++ b/cloud-server-course/src/main/java/com/dsh/course/feignclient/model/CourseOfStoreVo.java @@ -36,4 +36,12 @@ @ApiModelProperty(value = "预约状态") private Integer status; + + @ApiModelProperty(value = "总学时数") + Integer allNum; + @ApiModelProperty(value = "已扣学时数") + Integer useNum; + @ApiModelProperty(value = "剩余学时数") + Integer lastNum; + } diff --git a/cloud-server-course/src/main/java/com/dsh/course/feignclient/model/PaymentDeductionClassHour.java b/cloud-server-course/src/main/java/com/dsh/course/feignclient/model/PaymentDeductionClassHour.java index e472cf5..0953dd1 100644 --- a/cloud-server-course/src/main/java/com/dsh/course/feignclient/model/PaymentDeductionClassHour.java +++ b/cloud-server-course/src/main/java/com/dsh/course/feignclient/model/PaymentDeductionClassHour.java @@ -20,4 +20,8 @@ * 支付编号 */ private String code; + /** + * 用于支付的课程 + */ + private Long courseId; } diff --git a/cloud-server-course/src/main/java/com/dsh/course/feignclient/model/RecordAppoint.java b/cloud-server-course/src/main/java/com/dsh/course/feignclient/model/RecordAppoint.java index ca6a2cf..49d1ffc 100644 --- a/cloud-server-course/src/main/java/com/dsh/course/feignclient/model/RecordAppoint.java +++ b/cloud-server-course/src/main/java/com/dsh/course/feignclient/model/RecordAppoint.java @@ -24,7 +24,7 @@ @ApiModelProperty(value = "门店名称+地址") private String storeNameAddr; - @ApiModelProperty(value = "课状态(1待上课 2已开始 3已完成 4已取消)") + @ApiModelProperty(value = "课状态(1待上课 2已开始 3已完成 4已取消 5已请假 6旷课)") private Integer status; } diff --git a/cloud-server-course/src/main/java/com/dsh/course/model/CoursePackageInfo.java b/cloud-server-course/src/main/java/com/dsh/course/model/CoursePackageInfo.java index 82469df..18538e3 100644 --- a/cloud-server-course/src/main/java/com/dsh/course/model/CoursePackageInfo.java +++ b/cloud-server-course/src/main/java/com/dsh/course/model/CoursePackageInfo.java @@ -34,7 +34,7 @@ @ApiModelProperty("上课周") private List<String> weeks; @ApiModelProperty("上课时间") - private String times; + private List<String> times; @ApiModelProperty("详情图片") private String detailDrawing; @ApiModelProperty("介绍图") @@ -43,4 +43,6 @@ private List<CoursePackagePaymentConfigVo> list; @ApiModelProperty("学员") private StudentVo student; + @ApiModelProperty("1常规 2假期 3体验") + private Integer type; } diff --git a/cloud-server-course/src/main/java/com/dsh/course/model/CoursePackageListVo.java b/cloud-server-course/src/main/java/com/dsh/course/model/CoursePackageListVo.java index e9da1da..315b45c 100644 --- a/cloud-server-course/src/main/java/com/dsh/course/model/CoursePackageListVo.java +++ b/cloud-server-course/src/main/java/com/dsh/course/model/CoursePackageListVo.java @@ -4,6 +4,8 @@ import io.swagger.annotations.ApiModelProperty; import lombok.Data; +import java.util.List; + /** * @author zhibing.pu * @date 2023/6/24 17:34 @@ -20,7 +22,7 @@ @ApiModelProperty("封面图") private String coverDrawing; @ApiModelProperty("上课时间") - private String classStartTime; + private List<String> classStartTime; @ApiModelProperty("已报名人数") private Integer applicantsNumber; @ApiModelProperty("支付方式(1=现金,2=玩湃币)") @@ -35,4 +37,6 @@ private Integer playPaiCoin; @ApiModelProperty("距离") private Double distance; + @ApiModelProperty("1常规 2假期 3体验") + private Integer type; } diff --git a/cloud-server-course/src/main/java/com/dsh/course/model/vo/RegisterCourseVo.java b/cloud-server-course/src/main/java/com/dsh/course/model/vo/RegisterCourseVo.java index ba888d3..877a839 100644 --- a/cloud-server-course/src/main/java/com/dsh/course/model/vo/RegisterCourseVo.java +++ b/cloud-server-course/src/main/java/com/dsh/course/model/vo/RegisterCourseVo.java @@ -34,4 +34,7 @@ @ApiModelProperty(value = "课包类型id") private Integer coursePackTypeId; + @ApiModelProperty(value = "1常规 2假期 3体验") + private Integer type; + } diff --git a/cloud-server-course/src/main/java/com/dsh/course/service/TCoursePackagePaymentService.java b/cloud-server-course/src/main/java/com/dsh/course/service/TCoursePackagePaymentService.java index cd0703d..17f21f8 100644 --- a/cloud-server-course/src/main/java/com/dsh/course/service/TCoursePackagePaymentService.java +++ b/cloud-server-course/src/main/java/com/dsh/course/service/TCoursePackagePaymentService.java @@ -1,5 +1,6 @@ package com.dsh.course.service; +import com.baomidou.mybatisplus.extension.api.R; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.IService; import com.dsh.course.entity.TCoursePackagePayment; @@ -8,13 +9,8 @@ import com.dsh.course.model.QueryWalkInStudentList; import com.dsh.course.model.BillingRequest; import com.dsh.course.model.vo.RegisterCourseVo; -import com.dsh.course.model.vo.request.ClasspaymentRequest; -import com.dsh.course.model.vo.request.CourseOfAfterRequest; -import com.dsh.course.model.vo.request.CourseWithDetailsRequest; -import com.dsh.course.model.vo.request.UpdateCourseVideoStatusRequest; -import com.dsh.course.model.vo.response.AppUserVideoResponse; -import com.dsh.course.model.vo.response.CourseDetailsResponse; -import com.dsh.course.model.vo.response.CourseOfVideoResponse; +import com.dsh.course.model.vo.request.*; +import com.dsh.course.model.vo.response.*; import com.dsh.course.util.ResultUtil; import java.util.List; @@ -112,4 +108,14 @@ * @return */ List<Map<String, Object>> queryWalkInStudentList(Page<Map<String, Object>> page, QueryWalkInStudentList queryWalkInStudentList); + + List<PayCourseRes> getMyCourseList(Integer storeId, Integer appUserId); + + + PayCourseInfoReq payCourseInfo(Integer courseId); + + + ResultUtil payCourse(PayCourseReq req, Integer userId); + + } diff --git a/cloud-server-course/src/main/java/com/dsh/course/service/TCoursePackageService.java b/cloud-server-course/src/main/java/com/dsh/course/service/TCoursePackageService.java index 4708c1c..672f810 100644 --- a/cloud-server-course/src/main/java/com/dsh/course/service/TCoursePackageService.java +++ b/cloud-server-course/src/main/java/com/dsh/course/service/TCoursePackageService.java @@ -89,4 +89,11 @@ String getHours(Integer coursePackageId); + ResultUtil paymentCourseCouponList(Integer uid, Integer coursePackagePaymentConfigId); + + + List<CoursePackageListVo> queryCourseListOne(CoursePackageList coursePackageList) throws Exception; + + + } diff --git a/cloud-server-course/src/main/java/com/dsh/course/service/impl/TCoursePackagePaymentServiceImpl.java b/cloud-server-course/src/main/java/com/dsh/course/service/impl/TCoursePackagePaymentServiceImpl.java index 8d2bccb..4e7fbbd 100644 --- a/cloud-server-course/src/main/java/com/dsh/course/service/impl/TCoursePackagePaymentServiceImpl.java +++ b/cloud-server-course/src/main/java/com/dsh/course/service/impl/TCoursePackagePaymentServiceImpl.java @@ -14,6 +14,7 @@ import com.dsh.course.feignclient.account.model.AppUser; import com.dsh.course.feignclient.account.model.Coach; import com.dsh.course.feignclient.account.model.Student; +import com.dsh.course.feignclient.account.model.TCourseInfoRecord; import com.dsh.course.feignclient.activity.BenefitVideoClient; import com.dsh.course.feignclient.activity.CouponClient; import com.dsh.course.feignclient.activity.model.BenefitsVideos; @@ -27,20 +28,20 @@ import com.dsh.course.model.QueryWalkInStudentList; import com.dsh.course.model.dto.DiscountJsonDto; import com.dsh.course.model.vo.RegisterCourseVo; -import com.dsh.course.model.vo.request.ClasspaymentRequest; -import com.dsh.course.model.vo.request.CourseOfAfterRequest; -import com.dsh.course.model.vo.request.CourseWithDetailsRequest; -import com.dsh.course.model.vo.request.UpdateCourseVideoStatusRequest; -import com.dsh.course.model.vo.response.AppUserVideoResponse; -import com.dsh.course.model.vo.response.CourseDetailsResponse; -import com.dsh.course.model.vo.response.CourseOfVideoResponse; +import com.dsh.course.model.vo.request.*; +import com.dsh.course.model.vo.response.*; import com.dsh.course.service.ICoursePackageSchedulingService; import com.dsh.course.service.TCoursePackagePaymentService; import com.dsh.course.util.*; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Propagation; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.client.RestTemplate; import javax.annotation.Resource; import java.math.BigDecimal; @@ -107,6 +108,10 @@ @Autowired private ICoursePackageSchedulingService coursePackageSchedulingService; + + + @Autowired + private RestTemplate internalRestTemplate; @@ -221,13 +226,18 @@ TCoursePackage coursePackage = tcpmapper.selectById(tCoursePackagePayment.getCoursePackageId()); Store store = stoClient.queryStoreById(coursePackage.getStoreId()); RegisterCourseVo registerCourseVo = new RegisterCourseVo(); + // 2.0 + registerCourseVo.setType(coursePackage.getType()); + registerCourseVo.setCoursePayId(tCoursePackagePayment.getId()); registerCourseVo.setCoursePackageId(tCoursePackagePayment.getCoursePackageId()); registerCourseVo.setCoursePackTypeId(coursePackage.getCoursePackageTypeId()); registerCourseVo.setPackageImg(coursePackage.getCoverDrawing()); String storeAndCourse = coursePackage.getName()+"("+ store.getName() +")"; registerCourseVo.setCourseNameStore(storeAndCourse); - registerCourseVo.setCourseTime(coursePackage.getClassStartTime()+"-"+coursePackage.getClassEndTime()); +// registerCourseVo.setCourseTime(coursePackage.getClassStartTime()+"-"+coursePackage.getClassEndTime()); + // 2.0 + registerCourseVo.setCourseTime(new SimpleDateFormat("yyyy-MM-dd").format(tCoursePackagePayment.getInsertTime())); Coach coach = coachClient.queryCoachById(coursePackage.getCoachId()); registerCourseVo.setCourseTeacher(ToolUtil.isEmpty(coach) ? "" : coach.getName()); List<CoursePackageStudent> coursePackageStudents = cpsMapper.selectList(new QueryWrapper<CoursePackageStudent>() @@ -602,7 +612,6 @@ String[] split = classWeeks.split(";"); List<String> integerList = Arrays.asList(split); String weekOfDate = DateTimeHelper.getWeekOfDate(new Date()); - if (integerList.contains(weekOfDate)){ String dat = simpleDateFormat.format(date) +" "+ classStartTime; @@ -614,11 +623,18 @@ } if (start.after(new Date())){ recordVo.setStatus(1); + }else if(coursePackageStudent.getSignInOrNot()==2){ + recordVo.setStatus(5); }else { CancelledClasses cancelledClasses = cacMapper.selectOne(new QueryWrapper<CancelledClasses>() .eq("coursePackageId",tCoursePackagePayment.getCoursePackageId() )); if (ToolUtil.isNotEmpty(cancelledClasses)){ recordVo.setStatus(3); + // 消课 到课状态0 旷课 + if(coursePackageStudent.getSignInOrNot()==0){ + recordVo.setStatus(6); + } + }else { recordVo.setStatus(2); } @@ -626,10 +642,10 @@ }else { recordVo.setStatus(1); } + }else { recordVo.setStatus(4); } - recordVoList.add(recordVo); } } @@ -745,4 +761,154 @@ } return list; } + + @Override + public List<PayCourseRes> getMyCourseList(Integer storeId, Integer appUserId) { + // 找到购买的课包 + List<TCoursePackagePayment> tCoursePackagePayments = this.baseMapper.selectList(new LambdaQueryWrapper<TCoursePackagePayment>().eq(TCoursePackagePayment::getAppUserId, appUserId)); + ArrayList<PayCourseRes> payCourseRes = new ArrayList<>(); + for (TCoursePackagePayment tCoursePackagePayment : tCoursePackagePayments) { + TCoursePackage tCoursePackage = tcpmapper.selectById(tCoursePackagePayment.getCoursePackageId()); + if(tCoursePackage.getStoreId().equals(storeId)){ + PayCourseRes payCourseRes1 = new PayCourseRes(); + payCourseRes1.setId(tCoursePackagePayment.getId()); + payCourseRes1.setName(tCoursePackage.getName()); + payCourseRes1.setCourseNum(tCoursePackagePayment.getLaveClassHours()); + payCourseRes.add(payCourseRes1); + + } + } + return payCourseRes; + } + + @Override + public PayCourseInfoReq payCourseInfo(Integer courseId){ + PayCourseInfoReq payCourseInfoReq = new PayCourseInfoReq(); + TCoursePackage tCoursePackage = tcpmapper.selectById(courseId); + payCourseInfoReq.setId(courseId); + payCourseInfoReq.setName(tCoursePackage.getName()); + payCourseInfoReq.setNum(tCoursePackage.getNeedNum()); + payCourseInfoReq.setWeek(tCoursePackage.getClassWeeks()); + String classStartTime = tCoursePackage.getClassStartTime(); + String classEndTime = tCoursePackage.getClassEndTime(); + String[] split = classStartTime.split(","); + String[] split1 = classEndTime.split(","); + ArrayList<String> strings = new ArrayList<>(); + for (int i = 0; i < classStartTime.split(",").length; i++) { + String s = split[i] + "-" + split1[i]; + strings.add(s); + } + payCourseInfoReq.setTime(strings); + return payCourseInfoReq; + } + + @Override + @Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRES_NEW) + public ResultUtil payCourse(PayCourseReq req,Integer userId){ + // 扣除 原来的课时数 + // 添加购买课时 paytyoe为7 + // 排课可期 判断课程时间段 添加排课表 添加上课记录表 + // 找到原来的课包 扣课时 + TCoursePackagePayment tCoursePackagePayment = this.baseMapper.selectById(req.getOldCourseId()); + if(req.getNum()>tCoursePackagePayment.getLaveClassHours()){ + return ResultUtil.error("当前课包课时数不足"); + } + tCoursePackagePayment.setLaveClassHours(tCoursePackagePayment.getLaveClassHours()-req.getNum()); + this.baseMapper.updateById(tCoursePackagePayment); + + + TCoursePackage tCoursePackage = tcpmapper.selectById(req.getCourseId()); + // 添加课包 + TCoursePackagePayment tCoursePackagePayment1 = new TCoursePackagePayment(); + tCoursePackagePayment1.setAppUserId(userId); + Student student = studentClient.queryDefaultStudent(userId); + // student ID + Integer sId=null; + if(student!=null){ + tCoursePackagePayment1.setStudentId(student.getId()); + sId=student.getId(); + } + tCoursePackagePayment1.setCoursePackageId(tCoursePackage.getId()); + tCoursePackagePayment1.setPayType(7); + tCoursePackagePayment1.setClassHours(req.getNum()); + tCoursePackagePayment1.setOriginalPrice(0.0); + tCoursePackagePayment1.setTotalClassHours(req.getNum()); + tCoursePackagePayment1.setLaveClassHours(req.getNum()); + tCoursePackagePayment1.setAbsencesNumber(0); + tCoursePackagePayment1.setPayUserType(1); + tCoursePackagePayment1.setPayStatus(2); + tCoursePackagePayment1.setPayUserId(userId); + tCoursePackagePayment1.setStatus(1); + tCoursePackagePayment1.setState(1); + tCoursePackagePayment1.setInsertTime(new Date()); + this.baseMapper.insert(tCoursePackagePayment1); + // 找出课包时间段 + SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm"); + String classStartTime = tCoursePackage.getClassStartTime(); + String classEndTime = tCoursePackage.getClassEndTime(); + String[] split = classStartTime.split(","); + String[] split1 = classEndTime.split(","); + List<String> time = req.getTime(); + for (String s : time) { + for (int i = 0; i < split.length; i++) { + CoursePackageScheduling coursePackageScheduling = new CoursePackageScheduling(); + coursePackageScheduling.setCourseId(tCoursePackage.getId()); + try { + Date parse = format.parse(s + " " + split[i]); + Date parse1 = format.parse(s + " " + split1[i]); + coursePackageScheduling.setClassDate(parse); + coursePackageScheduling.setEndDate(parse1); + coursePackageScheduling.setStatus(1); + coursePackageSchedulingService.save(coursePackageScheduling); + + CoursePackageStudent student1 = new CoursePackageStudent(); + student1.setAppUserId(userId); + student1.setStudentId(sId); + student1.setCoursePackageId(tCoursePackage.getId()); + student1.setCoursePackagePaymentId(tCoursePackagePayment1.getId()); + student1.setCoursePackageSchedulingId(coursePackageScheduling.getId()); + student1.setSignInOrNot(0); + student1.setReservationStatus(1); + student1.setInsertTime(new Date()); + cpsMapper.insert(student1); + } catch (ParseException e) { + e.printStackTrace(); + } + + } + } + + + // 2.0 + TCourseInfoRecord tCourseInfoRecord = new TCourseInfoRecord(); + tCourseInfoRecord.setUserId(userId); + tCourseInfoRecord.setCourseId(req.getOldCourseId()); + tCourseInfoRecord.setName("体验购课"); + tCourseInfoRecord.setNum(req.getNum()); + tCourseInfoRecord.setTime(new Date()); + tCourseInfoRecord.setType(2); + appuClient.addCourseInfoRecord(tCourseInfoRecord); + + + if(tCoursePackagePayment.getLaveClassHours()<=3){ + Integer appUserId = userId; + + //调用推送 + HttpHeaders headers = new HttpHeaders(); + // 以表单的方式提交 + headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); + String s1 = appUserId + "_" + "Three"; + //定时修改排课状态 + String s = internalRestTemplate.getForObject("http://mb-cloud-gateway/netty/sendMsgToClient?id="+s1, String.class); + JSONObject jsonObject1 = JSON.parseObject(s, JSONObject.class); + if(jsonObject1.getIntValue("code") != 200){ + System.err.println(jsonObject1.getString("msg")); + } + } + + return ResultUtil.success(); + + } + + } diff --git a/cloud-server-course/src/main/java/com/dsh/course/service/impl/TCoursePackageServiceImpl.java b/cloud-server-course/src/main/java/com/dsh/course/service/impl/TCoursePackageServiceImpl.java index 8111282..717e7c5 100644 --- a/cloud-server-course/src/main/java/com/dsh/course/service/impl/TCoursePackageServiceImpl.java +++ b/cloud-server-course/src/main/java/com/dsh/course/service/impl/TCoursePackageServiceImpl.java @@ -1,5 +1,6 @@ package com.dsh.course.service.impl; +import cn.hutool.core.date.DateUtil; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; @@ -12,24 +13,29 @@ import com.dsh.course.feignclient.account.StudentClient; import com.dsh.course.feignclient.account.model.AppUser; import com.dsh.course.feignclient.account.model.Student; +import com.dsh.course.feignclient.account.model.TCourseInfoRecord; import com.dsh.course.feignclient.activity.CouponClient; import com.dsh.course.feignclient.activity.UserCouponClient; import com.dsh.course.feignclient.activity.model.Coupon; +import com.dsh.course.feignclient.activity.model.SendCouponReq; import com.dsh.course.feignclient.activity.model.UserCoupon; import com.dsh.course.feignclient.other.StoreClient; import com.dsh.course.feignclient.other.model.Store; +import com.dsh.course.mapper.CoursePackageStudentMapper; import com.dsh.course.mapper.TCoursePackageMapper; import com.dsh.course.feignclient.model.CourseOfStoreVo; import com.dsh.course.model.*; import com.dsh.course.service.*; import com.dsh.course.util.*; import com.dsh.course.util.httpClinet.HttpResult; +import org.omg.CORBA.INTERNAL; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import javax.annotation.Resource; import java.math.BigDecimal; import java.math.RoundingMode; +import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.*; import java.util.stream.Collectors; @@ -80,7 +86,8 @@ @Autowired private CoursePackageStudentService coursePackageStudentService; - + @Resource + private CoursePackageStudentMapper cpsMapper; @@ -133,13 +140,214 @@ coursePackageListVo.setName(coursePackage.getName()); coursePackageListVo.setStoreName(null != store ? store.getName() : ""); coursePackageListVo.setCoverDrawing(coursePackage.getCoverDrawing()); - coursePackageListVo.setClassStartTime(coursePackage.getClassStartTime() + "-" + coursePackage.getClassEndTime()); + + // 2.0修改 + String classStartTime = coursePackage.getClassStartTime(); + String classEndTime = coursePackage.getClassEndTime(); + ArrayList<String> classTime = new ArrayList<>(); + String[] split = classStartTime.split(","); + String[] split3 = classEndTime.split(","); + for (int i = 0; i < split.length; i++) { + String s = split[i] + "-" + split3[i]; + classTime.add(s); + } + coursePackageListVo.setClassStartTime(classTime); + coursePackageListVo.setType(coursePackage.getType()); + + + coursePackageListVo.setApplicantsNumber(integer); coursePackageListVo.setPayType(coursePackage.getPayType()); coursePackageListVo.setPlayPaiCoin(coursePackagePaymentConfig.getPlayPaiCoin()); //会员显示原价和会员价(最低)。非会员显示会员价和支付价(最低) if(appUser.getIsVip() == 0){//非会员 + List<TCoursePackageDiscount> list2 = coursePackageDiscountService.list(new QueryWrapper<TCoursePackageDiscount>().eq("coursePackagePaymentConfigId", coursePackagePaymentConfig.getId()) + .eq("type", 1).eq("auditStatus", 2)); + Double vipPrice = coursePackagePaymentConfig.getCashPayment(); + for (TCoursePackageDiscount coursePackageDiscount : list2) { + Double num1 = JSON.parseObject(coursePackageDiscount.getContent()).getDouble("discountMember"); + if(vipPrice.compareTo(num1) > 0){ + vipPrice = num1; + } + } + coursePackageListVo.setVipPrice(vipPrice); + + Double paymentPrice = coursePackagePaymentConfig.getCashPayment(); + List<TCoursePackageDiscount> list3 = coursePackageDiscountService.list(new QueryWrapper<TCoursePackageDiscount>().eq("coursePackagePaymentConfigId", coursePackagePaymentConfig.getId()) + .eq("type", 3).eq("auditStatus", 2)); + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + for (TCoursePackageDiscount coursePackageDiscount : list3) { + /** + * [{ + * "startDate": "2023-01-01 00:00:00", + * "endDate": "2023-12-31 23:59:59", + * "startTime": "02:00:00", + * "endTime": "23:00:00", + * "weeks": [1, 2, 7], + * "cashPayment": 100 + * }] + */ + JSONArray jsonArray = JSON.parseArray(coursePackageDiscount.getContent()); + for (int i = 0; i < jsonArray.size(); i++) { + try { + JSONObject jsonObject = jsonArray.getJSONObject(i); + String startDate = jsonObject.getString("startDate"); + String endDate = jsonObject.getString("endDate"); + String startTime = jsonObject.getString("startTime"); + String endTime = jsonObject.getString("endTime"); + List<Integer> weeks = jsonObject.getJSONArray("weeks").toJavaList(Integer.class); + Double cashPayment = jsonObject.getDouble("cashPayment"); + Date startDate_date = sdf.parse(startDate); + Date endDate_date = sdf.parse(endDate); + long timeMillis = System.currentTimeMillis(); + if(timeMillis >= startDate_date.getTime() && timeMillis < endDate_date.getTime()){ + Date date = new Date(); + Calendar calendar = Calendar.getInstance(); + calendar.setTime(date); + int week = calendar.get(Calendar.DAY_OF_WEEK); + boolean isFirstSunday = (calendar.getFirstDayOfWeek() == Calendar.SUNDAY); + if(isFirstSunday){ + week = week - 1; + if(week == 0){ + week = 7; + } + } + if(!weeks.contains(week)){ + continue; + } + + String[] split1 = startTime.split(":"); + Integer hour1 = Integer.valueOf(split1[0]); + Calendar s = Calendar.getInstance(); + s.setTime(date); + s.set(Calendar.HOUR_OF_DAY, hour1); + s.set(Calendar.MINUTE, Integer.valueOf(split1[1])); + s.set(Calendar.SECOND, Integer.valueOf(split1[2])); + + String[] split2 = endTime.split(":"); + Integer hour2 = Integer.valueOf(split2[0]); + Calendar e = Calendar.getInstance(); + e.setTime(date); + e.set(Calendar.HOUR_OF_DAY, hour2); + e.set(Calendar.MINUTE, Integer.valueOf(split2[1])); + e.set(Calendar.SECOND, Integer.valueOf(split2[2])); + + if(hour1 > hour2){ + if(s.getTimeInMillis() > date.getTime()){ + s.set(Calendar.DAY_OF_YEAR, s.get(Calendar.DAY_OF_YEAR) - 1); + }else{ + e.set(Calendar.DAY_OF_YEAR, e.get(Calendar.DAY_OF_YEAR) + 1); + } + } + if(timeMillis >= s.getTimeInMillis() && timeMillis < e.getTimeInMillis() && paymentPrice.compareTo(cashPayment) > 0){ + paymentPrice = cashPayment; + } + } + }catch (Exception e){ + e.printStackTrace(); + } + } + } + coursePackageListVo.setPaymentPrice(paymentPrice); + }else{ + List<TCoursePackageDiscount> list2 = coursePackageDiscountService.list(new QueryWrapper<TCoursePackageDiscount>().eq("coursePackagePaymentConfigId", coursePackagePaymentConfig.getId()) + .eq("type", 1).eq("auditStatus", 2)); + Double vipPrice = coursePackagePaymentConfig.getCashPayment(); + for (TCoursePackageDiscount coursePackageDiscount : list2) { + Double num1 = JSON.parseObject(coursePackageDiscount.getContent()).getDouble("discountMember"); + if(vipPrice.compareTo(num1) > 0){ + vipPrice = num1; + } + } + coursePackageListVo.setPaymentPrice(vipPrice); + coursePackageListVo.setOriginalPrice(coursePackagePaymentConfig.getCashPayment()); + } + + Map<String, Double> distance = GeodesyUtil.getDistance(coursePackageList.getLon() + "," + coursePackageList.getLat(), store.getLon() + "," + store.getLat()); + coursePackageListVo.setDistance(distance.get("WGS84") / 1000); + listVos.add(coursePackageListVo); + } + + //销量排行 + if(ToolUtil.isNotEmpty(coursePackageList.getSalesRanking())){ + Collections.sort(listVos, new Comparator<CoursePackageListVo>() { + public int compare(CoursePackageListVo s1, CoursePackageListVo s2) { + return Integer.compare(s1.getApplicantsNumber(), s2.getApplicantsNumber()); + } + }); + } + //距离排行 + if(ToolUtil.isNotEmpty(coursePackageList.getDistanceSort())){ + Collections.sort(listVos, new Comparator<CoursePackageListVo>() { + public int compare(CoursePackageListVo s1, CoursePackageListVo s2) { + return Double.compare(s1.getDistance(), s2.getDistance()); + } + }); + } + return listVos; + } + + + @Override + public List<CoursePackageListVo> queryCourseListOne(CoursePackageList coursePackageList) throws Exception { +// AppUser appUser = appUserClient.queryAppUser(uid); + Map<String, String> geocode = gdMapGeocodingUtil.geocode(coursePackageList.getLon(), coursePackageList.getLat()); + String provinceCode = geocode.get("provinceCode"); + String cityCode = geocode.get("cityCode"); + QueryWrapper<TCoursePackage> wrapper = new QueryWrapper<TCoursePackage>().in("status", Arrays.asList(1, 2)) + .eq("auditStatus", 2).eq("state", 1).eq("provinceCode", provinceCode).eq("cityCode", cityCode); + if(null != coursePackageList.getCoursePackageTypeId()){ + wrapper.eq("coursePackageTypeId", coursePackageList.getCoursePackageTypeId()); + } + if(null != coursePackageList.getStoreId()){ + wrapper.eq("storeId", coursePackageList.getStoreId()); + } + if(null != coursePackageList.getStoreId()){ + wrapper.eq("storeId", coursePackageList.getStoreId()); + } + if(ToolUtil.isNotEmpty(coursePackageList.getSearch())){ + wrapper.like("name", coursePackageList.getSearch()); + List<Store> stores = storeClient.queryStoreListByName(coursePackageList.getSearch()); + List<Integer> collect = stores.stream().map(Store::getId).collect(Collectors.toList()); + if(collect.size() > 0){ + wrapper.or().in("storeId", collect); + } + } + List<TCoursePackage> list = this.list(wrapper.last(" order by sort, insertTime desc")); + List<CoursePackageListVo> listVos = new ArrayList<>(); + for (TCoursePackage coursePackage : list) { + Store store = storeClient.queryStoreById(coursePackage.getStoreId()); + Integer integer = coursePackagePaymentService.queryCountNumber(coursePackage.getId()); + CoursePackagePaymentConfig coursePackagePaymentConfig = coursePackagePaymentConfigService.getOne(new QueryWrapper<CoursePackagePaymentConfig>() + .eq("coursePackageId", coursePackage.getId()).orderByAsc("classHours").last(" limit 0, 1")); + CoursePackageListVo coursePackageListVo = new CoursePackageListVo(); + coursePackageListVo.setId(coursePackage.getId()); + coursePackageListVo.setName(coursePackage.getName()); + coursePackageListVo.setStoreName(null != store ? store.getName() : ""); + coursePackageListVo.setCoverDrawing(coursePackage.getCoverDrawing()); + + // 2.0修改 + String classStartTime = coursePackage.getClassStartTime(); + String classEndTime = coursePackage.getClassEndTime(); + ArrayList<String> classTime = new ArrayList<>(); + String[] split = classStartTime.split(","); + String[] split3 = classEndTime.split(","); + for (int i = 0; i < split.length; i++) { + String s = split[i] + "-" + split3[i]; + classTime.add(s); + } + coursePackageListVo.setClassStartTime(classTime); + coursePackageListVo.setType(coursePackage.getType()); + + + + coursePackageListVo.setApplicantsNumber(integer); + coursePackageListVo.setPayType(coursePackage.getPayType()); + coursePackageListVo.setPlayPaiCoin(coursePackagePaymentConfig.getPlayPaiCoin()); + + //会员显示原价和会员价(最低)。非会员显示会员价和支付价(最低) + if(false){//非会员 List<TCoursePackageDiscount> list2 = coursePackageDiscountService.list(new QueryWrapper<TCoursePackageDiscount>().eq("coursePackagePaymentConfigId", coursePackagePaymentConfig.getId()) .eq("type", 1).eq("auditStatus", 2)); Double vipPrice = coursePackagePaymentConfig.getCashPayment(); @@ -276,155 +484,168 @@ */ @Override public CoursePackageInfo queryCourseInfo(Integer uid, Integer id, String lon, String lat) throws Exception { - AppUser appUser = appUserClient.queryAppUser(uid); - TCoursePackage coursePackage = this.getById(id); - CoursePackageInfo coursePackageInfo = new CoursePackageInfo(); - coursePackageInfo.setId(id); - coursePackageInfo.setCoverDrawing(coursePackage.getCoverDrawing()); - coursePackageInfo.setName(coursePackage.getName()); - Store store = storeClient.queryStoreById(coursePackage.getStoreId()); - coursePackageInfo.setStoreName(store.getName()); - coursePackageInfo.setStoreCoverDrawing(store.getCoverDrawing()); - coursePackageInfo.setStoreAddress(store.getAddress()); - coursePackageInfo.setLon(store.getLon()); - coursePackageInfo.setLat(store.getLat()); - if(ToolUtil.isNotEmpty(lon) && ToolUtil.isNotEmpty(lat)){ - Map<String, Double> distance = GeodesyUtil.getDistance(lon + "," + lat, store.getLon() + "," + store.getLat()); - double wgs84 = new BigDecimal(distance.get("WGS84")).divide(new BigDecimal(1000)).setScale(2, RoundingMode.HALF_EVEN).doubleValue(); - coursePackageInfo.setDistance(wgs84); - } + AppUser appUser = appUserClient.queryAppUser(uid); + TCoursePackage coursePackage = this.getById(id); + CoursePackageInfo coursePackageInfo = new CoursePackageInfo(); + coursePackageInfo.setId(id); + coursePackageInfo.setCoverDrawing(coursePackage.getCoverDrawing()); + coursePackageInfo.setName(coursePackage.getName()); + Store store = storeClient.queryStoreById(coursePackage.getStoreId()); + coursePackageInfo.setStoreName(store.getName()); + coursePackageInfo.setStoreCoverDrawing(store.getCoverDrawing()); + coursePackageInfo.setStoreAddress(store.getAddress()); + coursePackageInfo.setLon(store.getLon()); + coursePackageInfo.setLat(store.getLat()); + if(ToolUtil.isNotEmpty(lon) && ToolUtil.isNotEmpty(lat)){ + Map<String, Double> distance = GeodesyUtil.getDistance(lon + "," + lat, store.getLon() + "," + store.getLat()); + double wgs84 = new BigDecimal(distance.get("WGS84")).divide(new BigDecimal(1000)).setScale(2, RoundingMode.HALF_EVEN).doubleValue(); + coursePackageInfo.setDistance(wgs84); + } - String[] split = coursePackage.getClassWeeks().split(";"); - coursePackageInfo.setWeeks(Arrays.asList(split)); - coursePackageInfo.setTimes(coursePackage.getClassStartTime() + "-" + coursePackage.getClassEndTime()); - coursePackageInfo.setDetailDrawing(coursePackage.getDetailDrawing()); - coursePackageInfo.setIntroduceDrawing(coursePackage.getIntroduceDrawing()); - List<CoursePackagePaymentConfigVo> list = new ArrayList<>(); - List<CoursePackagePaymentConfig> list1 = coursePackagePaymentConfigService.list(new QueryWrapper<CoursePackagePaymentConfig>().eq("coursePackageId", id).orderByAsc("classHours")); - list1.forEach(coursePackagePaymentConfig -> { - CoursePackagePaymentConfigVo coursePackagePaymentConfigVo = new CoursePackagePaymentConfigVo(); - coursePackagePaymentConfigVo.setId(coursePackagePaymentConfig.getId()); - coursePackagePaymentConfigVo.setClassHours(coursePackagePaymentConfig.getClassHours()); - coursePackagePaymentConfigVo.setPayType(coursePackage.getPayType()); - coursePackagePaymentConfigVo.setPlayPaiCoin(coursePackagePaymentConfig.getPlayPaiCoin()); - //会员显示原价和支付价(会员价)。非会员显示会员价和支付价(最低) - if(appUser.getIsVip() == 0){//非会员 - List<TCoursePackageDiscount> list2 = coursePackageDiscountService.list(new QueryWrapper<TCoursePackageDiscount>().eq("coursePackagePaymentConfigId", coursePackagePaymentConfig.getId()) - .eq("type", 1).eq("auditStatus", 2)); - Double vipPrice = coursePackagePaymentConfig.getCashPayment(); - for (TCoursePackageDiscount coursePackageDiscount : list2) { - Double num1 = JSON.parseObject(coursePackageDiscount.getContent()).getDouble("discountMember"); - if(vipPrice.compareTo(num1) > 0){ - vipPrice = num1; - } - } - coursePackagePaymentConfigVo.setVipPrice(vipPrice); + String[] split = coursePackage.getClassWeeks().split(";"); + coursePackageInfo.setWeeks(Arrays.asList(split)); - Double paymentPrice = coursePackagePaymentConfig.getCashPayment(); - List<TCoursePackageDiscount> list3 = coursePackageDiscountService.list(new QueryWrapper<TCoursePackageDiscount>().eq("coursePackagePaymentConfigId", coursePackagePaymentConfig.getId()) - .eq("type", 3).eq("auditStatus", 2)); - SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); - for (TCoursePackageDiscount coursePackageDiscount : list3) { - /** - * [{ - * "startDate": "2023-01-01 00:00:00", - * "endDate": "2023-12-31 23:59:59", - * "startTime": "02:00:00", - * "endTime": "23:00:00", - * "weeks": [1, 2, 7], - * "cashPayment": 100 - * }] - */ - JSONArray jsonArray = JSON.parseArray(coursePackageDiscount.getContent()); - for (int i = 0; i < jsonArray.size(); i++) { - try { - JSONObject jsonObject = jsonArray.getJSONObject(i); - String startDate = jsonObject.getString("startDate"); - String endDate = jsonObject.getString("endDate"); - String startTime = jsonObject.getString("startTime"); - String endTime = jsonObject.getString("endTime"); - List<Integer> weeks = jsonObject.getJSONArray("weeks").toJavaList(Integer.class); - Double cashPayment = jsonObject.getDouble("cashPayment"); - Date startDate_date = sdf.parse(startDate); - Date endDate_date = sdf.parse(endDate); - long timeMillis = System.currentTimeMillis(); - if(timeMillis >= startDate_date.getTime() && timeMillis < endDate_date.getTime()){ - Date date = new Date(); - Calendar calendar = Calendar.getInstance(); - calendar.setTime(date); - int week = calendar.get(Calendar.DAY_OF_WEEK); - boolean isFirstSunday = (calendar.getFirstDayOfWeek() == Calendar.SUNDAY); - if(isFirstSunday){ - week = week - 1; - if(week == 0){ - week = 7; - } - } - if(!weeks.contains(week)){ - continue; - } + // 2.0 + String classStartTime = coursePackage.getClassStartTime(); + String classEndTime = coursePackage.getClassEndTime(); + ArrayList<String> classTime = new ArrayList<>(); + String[] split4 = classStartTime.split(","); + String[] split3 = classEndTime.split(","); + for (int i = 0; i < split4.length; i++) { + String s = split4[i] + "-" + split3[i]; + classTime.add(s); + } + coursePackageInfo.setTimes(classTime); + coursePackageInfo.setType(coursePackage.getType()); - String[] split1 = startTime.split(":"); - Integer hour1 = Integer.valueOf(split1[0]); - Calendar s = Calendar.getInstance(); - s.setTime(date); - s.set(Calendar.HOUR_OF_DAY, hour1); - s.set(Calendar.MINUTE, Integer.valueOf(split1[1])); - s.set(Calendar.SECOND, Integer.valueOf(split1[2])); - - String[] split2 = endTime.split(":"); - Integer hour2 = Integer.valueOf(split2[0]); - Calendar e = Calendar.getInstance(); - e.setTime(date); - e.set(Calendar.HOUR_OF_DAY, hour2); - e.set(Calendar.MINUTE, Integer.valueOf(split2[1])); - e.set(Calendar.SECOND, Integer.valueOf(split2[2])); - - if(hour1 > hour2){ - if(s.getTimeInMillis() > date.getTime()){ - s.set(Calendar.DAY_OF_YEAR, s.get(Calendar.DAY_OF_YEAR) - 1); - }else{ - e.set(Calendar.DAY_OF_YEAR, e.get(Calendar.DAY_OF_YEAR) + 1); - } - } - if(timeMillis >= s.getTimeInMillis() && timeMillis < e.getTimeInMillis() && paymentPrice.compareTo(cashPayment) > 0){ - paymentPrice = cashPayment; - } - } - }catch (Exception e){ - e.printStackTrace(); + coursePackageInfo.setDetailDrawing(coursePackage.getDetailDrawing()); + coursePackageInfo.setIntroduceDrawing(coursePackage.getIntroduceDrawing()); + List<CoursePackagePaymentConfigVo> list = new ArrayList<>(); + List<CoursePackagePaymentConfig> list1 = coursePackagePaymentConfigService.list(new QueryWrapper<CoursePackagePaymentConfig>().eq("coursePackageId", id).orderByAsc("classHours")); + list1.forEach(coursePackagePaymentConfig -> { + CoursePackagePaymentConfigVo coursePackagePaymentConfigVo = new CoursePackagePaymentConfigVo(); + coursePackagePaymentConfigVo.setId(coursePackagePaymentConfig.getId()); + coursePackagePaymentConfigVo.setClassHours(coursePackagePaymentConfig.getClassHours()); + coursePackagePaymentConfigVo.setPayType(coursePackage.getPayType()); + coursePackagePaymentConfigVo.setPlayPaiCoin(coursePackagePaymentConfig.getPlayPaiCoin()); + //会员显示原价和支付价(会员价)。非会员显示会员价和支付价(最低) + if(appUser.getIsVip() == 0){//非会员 + List<TCoursePackageDiscount> list2 = coursePackageDiscountService.list(new QueryWrapper<TCoursePackageDiscount>().eq("coursePackagePaymentConfigId", coursePackagePaymentConfig.getId()) + .eq("type", 1).eq("auditStatus", 2)); + Double vipPrice = coursePackagePaymentConfig.getCashPayment(); + for (TCoursePackageDiscount coursePackageDiscount : list2) { + Double num1 = JSON.parseObject(coursePackageDiscount.getContent()).getDouble("discountMember"); + if(vipPrice.compareTo(num1) > 0){ + vipPrice = num1; } } - } - coursePackagePaymentConfigVo.setPaymentPrice(paymentPrice); - }else{ - List<TCoursePackageDiscount> list2 = coursePackageDiscountService.list(new QueryWrapper<TCoursePackageDiscount>().eq("coursePackagePaymentConfigId", coursePackagePaymentConfig.getId()) - .eq("type", 1).eq("auditStatus", 2)); - Double vipPrice = coursePackagePaymentConfig.getCashPayment(); - for (TCoursePackageDiscount coursePackageDiscount : list2) { - Double num1 = JSON.parseObject(coursePackageDiscount.getContent()).getDouble("discountMember"); - if(vipPrice.compareTo(num1) > 0){ - vipPrice = num1; - } - } - coursePackagePaymentConfigVo.setPaymentPrice(vipPrice); - coursePackagePaymentConfigVo.setOriginalPrice(coursePackagePaymentConfig.getCashPayment()); - } - list.add(coursePackagePaymentConfigVo); - }); - coursePackageInfo.setList(list); + coursePackagePaymentConfigVo.setVipPrice(vipPrice); - Student student = studentClient.queryDefaultStudent(uid); - StudentVo studentVo = new StudentVo(); - if(null != student){ - studentVo.setId(student.getId()); - studentVo.setPhone(student.getPhone()); - studentVo.setName(student.getName()); - SimpleDateFormat sdf = new SimpleDateFormat("yyyy"); - studentVo.setAge(Integer.valueOf(sdf.format(new Date())) - Integer.valueOf(sdf.format(student.getBirthday()))); - } - coursePackageInfo.setStudent(studentVo); - return coursePackageInfo; + Double paymentPrice = coursePackagePaymentConfig.getCashPayment(); + List<TCoursePackageDiscount> list3 = coursePackageDiscountService.list(new QueryWrapper<TCoursePackageDiscount>().eq("coursePackagePaymentConfigId", coursePackagePaymentConfig.getId()) + .eq("type", 3).eq("auditStatus", 2)); + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + for (TCoursePackageDiscount coursePackageDiscount : list3) { + /** + * [{ + * "startDate": "2023-01-01 00:00:00", + * "endDate": "2023-12-31 23:59:59", + * "startTime": "02:00:00", + * "endTime": "23:00:00", + * "weeks": [1, 2, 7], + * "cashPayment": 100 + * }] + */ + JSONArray jsonArray = JSON.parseArray(coursePackageDiscount.getContent()); + for (int i = 0; i < jsonArray.size(); i++) { + try { + JSONObject jsonObject = jsonArray.getJSONObject(i); + String startDate = jsonObject.getString("startDate"); + String endDate = jsonObject.getString("endDate"); + String startTime = jsonObject.getString("startTime"); + String endTime = jsonObject.getString("endTime"); + List<Integer> weeks = jsonObject.getJSONArray("weeks").toJavaList(Integer.class); + Double cashPayment = jsonObject.getDouble("cashPayment"); + Date startDate_date = sdf.parse(startDate); + Date endDate_date = sdf.parse(endDate); + long timeMillis = System.currentTimeMillis(); + if(timeMillis >= startDate_date.getTime() && timeMillis < endDate_date.getTime()){ + Date date = new Date(); + Calendar calendar = Calendar.getInstance(); + calendar.setTime(date); + int week = calendar.get(Calendar.DAY_OF_WEEK); + boolean isFirstSunday = (calendar.getFirstDayOfWeek() == Calendar.SUNDAY); + if(isFirstSunday){ + week = week - 1; + if(week == 0){ + week = 7; + } + } + if(!weeks.contains(week)){ + continue; + } + + String[] split1 = startTime.split(":"); + Integer hour1 = Integer.valueOf(split1[0]); + Calendar s = Calendar.getInstance(); + s.setTime(date); + s.set(Calendar.HOUR_OF_DAY, hour1); + s.set(Calendar.MINUTE, Integer.valueOf(split1[1])); + s.set(Calendar.SECOND, Integer.valueOf(split1[2])); + + String[] split2 = endTime.split(":"); + Integer hour2 = Integer.valueOf(split2[0]); + Calendar e = Calendar.getInstance(); + e.setTime(date); + e.set(Calendar.HOUR_OF_DAY, hour2); + e.set(Calendar.MINUTE, Integer.valueOf(split2[1])); + e.set(Calendar.SECOND, Integer.valueOf(split2[2])); + + if(hour1 > hour2){ + if(s.getTimeInMillis() > date.getTime()){ + s.set(Calendar.DAY_OF_YEAR, s.get(Calendar.DAY_OF_YEAR) - 1); + }else{ + e.set(Calendar.DAY_OF_YEAR, e.get(Calendar.DAY_OF_YEAR) + 1); + } + } + if(timeMillis >= s.getTimeInMillis() && timeMillis < e.getTimeInMillis() && paymentPrice.compareTo(cashPayment) > 0){ + paymentPrice = cashPayment; + } + } + }catch (Exception e){ + e.printStackTrace(); + } + } + } + coursePackagePaymentConfigVo.setPaymentPrice(paymentPrice); + }else{ + List<TCoursePackageDiscount> list2 = coursePackageDiscountService.list(new QueryWrapper<TCoursePackageDiscount>().eq("coursePackagePaymentConfigId", coursePackagePaymentConfig.getId()) + .eq("type", 1).eq("auditStatus", 2)); + Double vipPrice = coursePackagePaymentConfig.getCashPayment(); + for (TCoursePackageDiscount coursePackageDiscount : list2) { + Double num1 = JSON.parseObject(coursePackageDiscount.getContent()).getDouble("discountMember"); + if(vipPrice.compareTo(num1) > 0){ + vipPrice = num1; + } + } + coursePackagePaymentConfigVo.setPaymentPrice(vipPrice); + coursePackagePaymentConfigVo.setOriginalPrice(coursePackagePaymentConfig.getCashPayment()); + } + list.add(coursePackagePaymentConfigVo); + }); + coursePackageInfo.setList(list); + + Student student = studentClient.queryDefaultStudent(uid); + StudentVo studentVo = new StudentVo(); + if(null != student){ + studentVo.setId(student.getId()); + studentVo.setPhone(student.getPhone()); + studentVo.setName(student.getName()); + SimpleDateFormat sdf = new SimpleDateFormat("yyyy"); + studentVo.setAge(Integer.valueOf(sdf.format(new Date())) - Integer.valueOf(sdf.format(student.getBirthday()))); + } + coursePackageInfo.setStudent(studentVo); + return coursePackageInfo; } @@ -511,6 +732,8 @@ } return playPaiCoinPaymentCourse(appUser, price, paymentCourseVo); } + + return ResultUtil.success(); } @@ -551,8 +774,14 @@ coursePackagePaymentService.save(coursePackagePayment); } + Student student = studentClient.queryDefaultStudent(uid); + Integer sid=null; + if(student!=null){ + sid=student.getId(); + } ResultUtil weixinpay = payMoneyUtil.weixinpay("购买课程", "", code, paymentPrice.toString(), "/base/course/weChatPaymentCourseCallback", "APP", ""); if(weixinpay.getCode() == 200){ + Integer finalSid = sid; new Thread(new Runnable() { @Override public void run() { @@ -595,6 +824,10 @@ coursePackagePayment.setOrderNumber(transaction_id); } coursePackagePaymentService.updateBatchById(list); + // 2.0 + userCouponClient.sendUserCoupon(new SendCouponReq(uid,coursePackagePaymentConfig.getCouponIds())); + + addPackageStudent(paymentCourseVo.getId(),uid, finalSid,one.getId()); break; } if("USERPAYING".equals(s)){ @@ -648,8 +881,15 @@ coursePackagePaymentService.save(coursePackagePayment); } + Student student = studentClient.queryDefaultStudent(uid); + Integer sid=null; + if(student!=null){ + sid=student.getId(); + } + ResultUtil alipay = payMoneyUtil.alipay("购买课程", "购买课程", "", code, paymentPrice.toString(), "/base/course/aliPaymentCourseCallback"); if(alipay.getCode() == 200){ + Integer finalSid = sid; new Thread(new Runnable() { @Override public void run() { @@ -689,6 +929,16 @@ coursePackagePayment.setOrderNumber(tradeNo); } coursePackagePaymentService.updateBatchById(list); + + // 2.0 + userCouponClient.sendUserCoupon(new SendCouponReq(uid,coursePackagePaymentConfig.getCouponIds())); + + + + if(student!=null){ + + } + addPackageStudent(paymentCourseVo.getId(),uid, finalSid,one.getId()); break; } if("WAIT_BUYER_PAY".equals(s)){ @@ -739,12 +989,181 @@ coursePackagePayment.setState(1); coursePackagePayment.setInsertTime(new Date()); coursePackagePaymentService.save(coursePackagePayment); + Integer sId=null; + Student student = studentClient.queryDefaultStudent(appUser.getId()); + if(student!=null){ + sId=student.getId(); + } + addPackageStudent(paymentCourseVo.getId(),appUser.getId(),sId,coursePackagePayment.getId()); } Integer playPaiCoins = appUser.getPlayPaiCoins(); appUser.setPlayPaiCoins(playPaiCoins - paymentPrice.intValue()); appUserClient.updateAppUser(appUser); + + // 2.0 + String couponIds = coursePackagePaymentConfig.getCouponIds(); + if(ToolUtil.isNotEmpty(couponIds)){ + // 赠送优惠券 + userCouponClient.sendUserCoupon(new SendCouponReq(appUser.getId(),couponIds)); + } return ResultUtil.success(); + } + + + private void addPackageStudent(Integer courseId, Integer userId, Integer sId,Long paymentId){ + // 课包 + TCoursePackage tCoursePackage = this.baseMapper.selectById(courseId); + + + + String classWeeks = tCoursePackage.getClassWeeks(); + List<Integer> week = week(classWeeks); + + String[] split = tCoursePackage.getClassStartTime().split(","); + String[] split1 = tCoursePackage.getClassEndTime().split(","); + SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd"); + SimpleDateFormat format1 = new SimpleDateFormat("yyyy-MM-dd HH:mm"); + // 本周周几 + int i = DateUtil.dayOfWeek(new Date())-1; + for (Integer integer : week) { + if(integer<i){ + // 找下一周的时间 + Calendar instance = Calendar.getInstance(); + instance.add(Calendar.DATE,7-(i-integer)); + Date time = instance.getTime(); + + for (int i1 = 0; i1 < split.length; i1++) { + + CoursePackageScheduling coursePackageScheduling = new CoursePackageScheduling(); + coursePackageScheduling.setCourseId(tCoursePackage.getId()); + try { + Date parse = format1.parse(format.format(time) + " " + split[i1]); + Date parse1 = format1.parse(format.format(time) + " " + split1[i1]); + coursePackageScheduling.setClassDate(parse); + coursePackageScheduling.setEndDate(parse1); + coursePackageScheduling.setStatus(1); + coursePackageSchedulingService.save(coursePackageScheduling); + + CoursePackageStudent student1 = new CoursePackageStudent(); + student1.setAppUserId(userId); + student1.setStudentId(sId); + student1.setCoursePackageId(tCoursePackage.getId()); + student1.setCoursePackagePaymentId(paymentId); + student1.setCoursePackageSchedulingId(coursePackageScheduling.getId()); + student1.setSignInOrNot(0); + student1.setReservationStatus(1); + student1.setInsertTime(new Date()); + cpsMapper.insert(student1); + } catch (ParseException e) { + e.printStackTrace(); + } + + } + + }else if(integer>i) { + Calendar instance = Calendar.getInstance(); + instance.add(Calendar.DATE,integer-i); + Date time = instance.getTime(); + + for (int i1 = 0; i1 < split.length; i1++) { + CoursePackageScheduling coursePackageScheduling = new CoursePackageScheduling(); + coursePackageScheduling.setCourseId(tCoursePackage.getId()); + try { + Date parse = format1.parse(format.format(time) + " " + split[i1]); + Date parse1 = format1.parse(format.format(time) + " " + split1[i1]); + coursePackageScheduling.setClassDate(parse); + coursePackageScheduling.setEndDate(parse1); + coursePackageScheduling.setStatus(1); + coursePackageSchedulingService.save(coursePackageScheduling); + + CoursePackageStudent student1 = new CoursePackageStudent(); + student1.setAppUserId(userId); + student1.setStudentId(sId); + student1.setCoursePackageId(tCoursePackage.getId()); + student1.setCoursePackagePaymentId(paymentId); + student1.setCoursePackageSchedulingId(coursePackageScheduling.getId()); + student1.setSignInOrNot(0); + student1.setReservationStatus(1); + student1.setInsertTime(new Date()); + cpsMapper.insert(student1); + } catch (ParseException e) { + e.printStackTrace(); + } + } + }else { + Calendar instance = Calendar.getInstance(); + instance.add(Calendar.DATE,7); + Date time = instance.getTime(); + + for (int i1 = 0; i1 < split.length; i1++) { + CoursePackageScheduling coursePackageScheduling = new CoursePackageScheduling(); + coursePackageScheduling.setCourseId(tCoursePackage.getId()); + try { + Date parse = format1.parse(format.format(time) + " " + split[i1]); + Date parse1 = format1.parse(format.format(time) + " " + split1[i1]); + coursePackageScheduling.setClassDate(parse); + coursePackageScheduling.setEndDate(parse1); + coursePackageScheduling.setStatus(1); + coursePackageSchedulingService.save(coursePackageScheduling); + + CoursePackageStudent student1 = new CoursePackageStudent(); + student1.setAppUserId(userId); + student1.setStudentId(sId); + student1.setCoursePackageId(tCoursePackage.getId()); + student1.setCoursePackagePaymentId(paymentId); + student1.setCoursePackageSchedulingId(coursePackageScheduling.getId()); + student1.setSignInOrNot(0); + student1.setReservationStatus(1); + student1.setInsertTime(new Date()); + cpsMapper.insert(student1); + } catch (ParseException e) { + e.printStackTrace(); + } + } + } + } + // 2.0 + TCourseInfoRecord tCourseInfoRecord = new TCourseInfoRecord(); + tCourseInfoRecord.setUserId(userId); + tCourseInfoRecord.setCourseId(courseId); + tCourseInfoRecord.setName("报名假期班"); + tCourseInfoRecord.setNum(tCoursePackage.getNeedNum()); + tCourseInfoRecord.setTime(new Date()); + tCourseInfoRecord.setType(2); + appUserClient.addCourseInfoRecord(tCourseInfoRecord); + + + } + private List<Integer> week(String week){ + String[] split = week.split(";"); + ArrayList<Integer> integers = new ArrayList<>(); + for (String s : split) { + switch (s){ + case "周一": + integers.add(1); + break; + case "周二": + integers.add(2); + break; + case "周三": + integers.add(3); + break; + case "周四": + integers.add(4); + break; + case "周五": + integers.add(5); + break; + case "周六": + integers.add(6); + break; + case "周日": + integers.add(7); + break; + } + } + return integers; } @@ -961,4 +1380,14 @@ public String getHours(Integer coursePackageId) { return this.baseMapper.getHours(coursePackageId); } + + @Override + public ResultUtil paymentCourseCouponList(Integer uid, Integer coursePackagePaymentConfigId) { + CoursePackagePaymentConfig coursePackagePaymentConfig = coursePackagePaymentConfigService.getById(coursePackagePaymentConfigId); + if(ToolUtil.isEmpty(coursePackagePaymentConfig.getCouponIds())){ + coursePackagePaymentConfig.setCouponIds("-1"); + } + List<Coupon> coupons = couponClient.getCoupons(coursePackagePaymentConfig.getCouponIds()); + return ResultUtil.success(coupons); + } } diff --git a/cloud-server-course/src/main/java/com/dsh/course/util/TaskUtil.java b/cloud-server-course/src/main/java/com/dsh/course/util/TaskUtil.java index fb26c90..27a46f7 100644 --- a/cloud-server-course/src/main/java/com/dsh/course/util/TaskUtil.java +++ b/cloud-server-course/src/main/java/com/dsh/course/util/TaskUtil.java @@ -1,9 +1,26 @@ package com.dsh.course.util; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.dsh.course.entity.CoursePackageScheduling; +import com.dsh.course.entity.CoursePackageStudent; +import com.dsh.course.entity.TCoursePackagePayment; +import com.dsh.course.service.CoursePackageStudentService; import com.dsh.course.service.ICoursePackageSchedulingService; +import com.dsh.course.service.TCoursePackagePaymentService; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.web.client.RestTemplate; + +import java.text.SimpleDateFormat; +import java.util.*; /** * @author zhibing.pu @@ -15,6 +32,13 @@ @Autowired private ICoursePackageSchedulingService coursePackageSchedulingService; + @Autowired + private CoursePackageStudentService coursePackageStudentService; + + + @Autowired + private RestTemplate internalRestTemplate; + /** * 每隔一分钟去处理的定时任务 */ @@ -27,6 +51,42 @@ e.printStackTrace(); } } + /** + * 每隔一分钟去处理的定时任务 预约课时 + */ + @Scheduled(cron = "0 0 18 * * ?") + public void pushOne(){ + try { + Calendar instance = Calendar.getInstance(); + instance.add(Calendar.DATE,1); + Date time = instance.getTime(); + SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd"); + String format1 = format.format(time); + // 获取明天排课 + List<CoursePackageScheduling> list = coursePackageSchedulingService.list(new LambdaQueryWrapper<CoursePackageScheduling>().like(CoursePackageScheduling::getClassDate, format1)); + for (CoursePackageScheduling coursePackageScheduling : list) { + CoursePackageStudent one = coursePackageStudentService.getOne(new LambdaQueryWrapper<CoursePackageStudent>().eq(CoursePackageStudent::getCoursePackageSchedulingId, coursePackageScheduling.getId())); + if(one!=null && one.getReservationStatus()==1){ + Integer appUserId = one.getAppUserId(); + + //调用推送 + HttpHeaders headers = new HttpHeaders(); + // 以表单的方式提交 + headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); + String s1 = appUserId + "_" + "Class"; + //定时修改排课状态 + String s = internalRestTemplate.getForObject("http://mb-cloud-gateway/netty/sendMsgToClient?id="+s1, String.class); + JSONObject jsonObject1 = JSON.parseObject(s, JSONObject.class); + if(jsonObject1.getIntValue("code") != 200){ + System.err.println(jsonObject1.getString("msg")); + } + } + } + + } catch (Exception e) { + e.printStackTrace(); + } + } diff --git a/cloud-server-gateway/pom.xml b/cloud-server-gateway/pom.xml index a7e6fe4..1d58e08 100644 --- a/cloud-server-gateway/pom.xml +++ b/cloud-server-gateway/pom.xml @@ -16,6 +16,14 @@ <dependencies> + + + + <dependency> + <groupId>io.netty</groupId> + <artifactId>netty-all</artifactId> + <version>4.1.27.Final</version> + </dependency> <dependency> <groupId>cn.mb.cloud</groupId> <artifactId>mb-cloud-common-gateway</artifactId> diff --git a/cloud-server-gateway/src/main/java/cn/mb/cloud/gateway/controller/NettyController.java b/cloud-server-gateway/src/main/java/cn/mb/cloud/gateway/controller/NettyController.java new file mode 100644 index 0000000..f1d485b --- /dev/null +++ b/cloud-server-gateway/src/main/java/cn/mb/cloud/gateway/controller/NettyController.java @@ -0,0 +1,48 @@ +package cn.mb.cloud.gateway.controller; + + +import cn.mb.cloud.gateway.auth.ResultUtil; +import cn.mb.cloud.gateway.util.applets.NettyWebSocketController; +import cn.mb.cloud.gateway.util.echo.NettyChannelMap; +import cn.mb.cloud.gateway.util.echo.NettyServerController; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import io.netty.channel.ChannelHandlerContext; +import org.springframework.web.bind.annotation.*; + +import java.util.HashMap; +import java.util.Map; + +@RestController +@RequestMapping("/netty") +public class NettyController { + + + /** 3.4.5.6 + * 向客户端推送消息 + * @param id + * @param msg + */ + @ResponseBody + @GetMapping("/sendMsgToClient") + public String sendMsgToClient(String id, Integer type, String msg){ + System.out.println(id+"|"+type+"|"+msg+"!!!!!!!!"); + if(true){//用户端 + String[] split = id.split("_"); + ChannelHandlerContext channel = NettyChannelMap.getData("USER" + split[0]); + if(null != channel){ + JSONObject jsonObject = new JSONObject(); + jsonObject.put("code", 200); + jsonObject.put("msg", "SUCCESS"); + jsonObject.put("method", "CLASS"); + Map<String, Object> map = new HashMap<>(); + jsonObject.put("data", map); + NettyServerController.sendMsgToClient(channel, jsonObject.toJSONString()); + return JSON.toJSONString(ResultUtil.success()); + } + return JSON.toJSONString(ResultUtil.error("推送失败-----用户id=" + id)); + + } + return JSON.toJSONString(ResultUtil.error("推送失败")); + } +} diff --git a/cloud-server-gateway/src/main/java/cn/mb/cloud/gateway/util/SinataUtil.java b/cloud-server-gateway/src/main/java/cn/mb/cloud/gateway/util/SinataUtil.java new file mode 100644 index 0000000..1a17294 --- /dev/null +++ b/cloud-server-gateway/src/main/java/cn/mb/cloud/gateway/util/SinataUtil.java @@ -0,0 +1,405 @@ +package cn.mb.cloud.gateway.util; + +import java.io.UnsupportedEncodingException; +import java.text.DecimalFormat; +import java.text.NumberFormat; +import java.util.*; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * 基本数据处理工具类 + */ +public class SinataUtil { + /** + * List集合分页<br/> + * 创建人:Mryang<br/> + * 时间:2016年7月28日-下午2:58:14 <br/> + * @param <T> + * @param pageNo + * @param pageSize + * @param list + * @throws Exception List<UserOrderList> <br/> + */ + public static <T> List<T> listpage(int pageNo, int pageSize, List<T> list) throws Exception { + List<T> result = new ArrayList<T>(); + if (list != null && list.size() > 0) { + int allCount = list.size(); + if(pageNo > 1 && allCount < pageSize) { + return new ArrayList<>(); + } + int pageCount = (allCount + pageSize - 1) / pageSize; + if (pageNo >= pageCount) { + pageNo = pageCount; + } + int start = (pageNo - 1) * pageSize; + int end = pageNo * pageSize; + if (end >= allCount) { + end = allCount; + } + for (int i = start; i < end; i++) { + result.add(list.get(i)); + } + } + return (result != null && result.size() > 0) ? result : new ArrayList<T>(); + } + + /** + * Double类型取整 + * @param num + * @return + */ + public static String doubleTrans(double num) { + return String.valueOf((long) num); + } + + /** + * Double类型保留1位小数 + * + * @param num + * @return + */ + public static String doubleRetainOne(double num) { + DecimalFormat dfs = new DecimalFormat("0.0"); + return dfs.format(num); + } + + /** + * Double类型保留2位小数 + * + * @param num + * @return + */ + public static String doubleRetainTwo(double num) { + DecimalFormat dfs = new DecimalFormat("0.00"); + String.format("%.2f", num); + return dfs.format(num); + } + + /** + * Double类型保留1位小数(四舍五入) + * + * @param num + * @return + */ + public static String doubleForwardOne(double num) { + return String.format("%.1f", num); + } + + /** + * Double类型保留2位小数(四舍五入) + * + * @param num + * @return + */ + public static String doubleForwardTwo(double num) { + return String.format("%.2f", num); + } + + /** + * 字符串转换成Ascii + * + * @param value + * @return + */ + public static String stringToAscii(String value) { + StringBuffer sbu = new StringBuffer(); + char[] chars = value.toCharArray(); + for (int i = 0; i < chars.length; i++) { + if (i != chars.length - 1) { + sbu.append((int) chars[i]); + } else { + sbu.append((int) chars[i]); + } + } + return sbu.toString(); + } + + /** + * 小数转换为百分比 + * + * @param decimal + * @return + * @author TaoNingBo + */ + public static String decTurnPercent(double decimal) { + NumberFormat num = NumberFormat.getPercentInstance(); + num.setMaximumIntegerDigits(3); + num.setMaximumFractionDigits(2); + return num.format(decimal); + } + + /** + * Ascii转换成字符串 + * + * @param value + * @return + */ + public static String asciiToString(String value) { + String[] chars = value.split(","); + StringBuffer sbu = new StringBuffer(); + for (int i = 0; i < chars.length; i++) { + sbu.append((char) Integer.parseInt(chars[i])); + } + return sbu.toString(); + } + + /** + * 字符串转换unicode + * + * @param string + * @return + * @author TaoNingBo + */ + public static String string2Unicode(String string) { + StringBuffer unicode = new StringBuffer(); + for (int i = 0; i < string.length(); i++) { + // 取出每一个字符 + char c = string.charAt(i); + // 转换为unicode + unicode.append("\\u" + Integer.toHexString(c)); + } + return unicode.toString(); + } + + /** + * unicode 转字符串 + * + * @param unicode + * @return + * @author TaoNingBo + */ + public static String unicode2String(String unicode) { + StringBuffer string = new StringBuffer(); + String[] hex = unicode.split("\\\\u"); + for (int i = 1; i < hex.length; i++) { + // 转换出每一个代码点 + int data = Integer.parseInt(hex[i], 16); + // 追加成string + string.append((char) data); + } + return string.toString(); + } + + /** + * 字符串编码转换的实现方法 + * + * @param str + * 待转换编码的字符串 + * @param newCharset + * 目标编码 + * @return + * @throws UnsupportedEncodingException + */ + public static String changeCharset(String str, String newCharset) throws UnsupportedEncodingException { + if (str != null) { + // 用默认字符编码解码字符串。 + byte[] bs = str.getBytes(); + // 用新的字符编码生成字符串 + return new String(bs, newCharset); + } + return null; + } + + /** + * 注: \n 回车( ) \t 水平制表符( ) \s 空格(\u0008) \r 换行( ) + * + * @param str + * @return + */ + public static String replaceBlank(String str) { + String dest = ""; + if (str != null) { + Pattern p = Pattern.compile("\\s*|\t|\r|\n"); + Matcher m = p.matcher(str); + dest = m.replaceAll(""); + } + return dest; + } + + /** + * 判断该字符串不能为空 + * + * @param str + * @return + * @author TaoNingBo + */ + public static boolean isNotEmpty(Object str) { + return !isEmpty(str); + } + + + public static boolean isNotEmptyUndefined(Object str) { + return !isEmpty(str) && !str.toString().equals("undefined"); + } + + /** + * 字符串编码转换的实现方法 + * + * @param str + * 待转换编码的字符串 + * @param oldCharset + * 原编码 + * @param newCharset + * 目标编码 + * @return + * @throws UnsupportedEncodingException + */ + public static String changeCharset(String str, String oldCharset, String newCharset) throws UnsupportedEncodingException { + if (str != null) { + // 用旧的字符编码解码字符串。解码可能会出现异常。 + byte[] bs = str.getBytes(oldCharset); + // 用新的字符编码生成字符串 + return new String(bs, newCharset); + } + return null; + } + + /** + * 给手机号码加分割符 + * + * @param phone + * @return + * @author TaoNingBo + */ + public static String splitPhone(String phone) { + if (isNotEmpty(phone)) { + String strone = phone.substring(0, 3); + String strtwo = phone.substring(strone.length(), 7); + String strthree = phone.substring(strtwo.length() + strone.length(), phone.length()); + return strone + "-" + strtwo + "-" + strthree; + } + return ""; + } + + /** + * 非空判断 + * + * @param str + * @return + * @author TaoNingBo + */ + public static boolean isEmpty(Object str) { + return str == null || str.toString().length() == 0 || str.equals("") || str.toString().matches("\\s*"); + } + + /** + * 把米转换成公里 + * + * @param km + * @return + * @author TaoNingBo + */ + public static Double kmTransKilo(Integer m) { + return Math.round(m / 100d) / 10d; + } + + /** + * 将List<{@link Object}>转换成List<{@link T}> + * + * @param list + * 将要转换的对象 + * @param clazs + * 需要转换的泛型对象 + * @return + * @author TaoNingBo + */ + @SuppressWarnings("unchecked") + public static <T> List<T> fromToObject(List<?> list, Class<T> clazs) { + List<T> t = new ArrayList<T>(); + for (Object object : list) { + t.add((T) object); + } + return t; + } + + /** + * 生成 uuid, 即用来标识一笔单,也用做 nonce_str + * @return + */ + public static String generateUUID() { + return UUID.randomUUID().toString().replaceAll("-", "").substring(0, 32); + } + + /** + * 将List<{@link Object}>转换成List<{@link Map<String, Object>}> + * + * @param list + * @return + * @author TaoNingBo + */ + @SuppressWarnings("unchecked") + public static List<Map<String, Object>> fromToObject_M(List<?> list) { + List<Map<String, Object>> t = new ArrayList<Map<String, Object>>(); + for (Object object : list) { + t.add((Map<String, Object>) object); + } + return t; + } + + +/** + * 将对象中的null转换为空 + * @param obj + * @return + * @throws IllegalAccessException + */ + +public static Object checkObjFieldIsNull(Object obj) throws IllegalAccessException { + if(obj!=null){ + for(java.lang.reflect.Field f : obj.getClass().getDeclaredFields()){ + f.setAccessible(true); + if(f.get(obj) == null){ + if(f.getType()==String.class){ + f.set(obj, ""); + } + if(f.getType()==Double.class){ + f.set(obj, 0d); + } + if(f.getType()==Integer.class){ + f.set(obj, 0); + } + if(f.getType()==Date.class){ + f.set(obj, new Date()); + } + } + } + return obj; + } + return obj; +} +/** + * 获取六位标识码 + * @param length + * @return + */ +public static String createRandomCharData() +{ + StringBuilder sb=new StringBuilder(); + Random rand=new Random();//随机用以下三个随机生成器 + Random randdata=new Random(); + int data=0; + for(int i=0;i<6;i++) + { + int index=rand.nextInt(3); + //目的是随机选择生成数字,大小写字母 + switch(index) + { + case 0: + data=randdata.nextInt(10);//仅仅会生成0~9 + sb.append(data); + break; + case 1: + data=randdata.nextInt(26)+65;//保证只会产生65~90之间的整数 + sb.append((char)data); + break; + case 2: + data=randdata.nextInt(26)+97;//保证只会产生97~122之间的整数 + sb.append((char)data); + break; + } + } + String result=sb.toString().toLowerCase(); + return result; +} +} diff --git a/cloud-server-gateway/src/main/java/cn/mb/cloud/gateway/util/SpringUtil.java b/cloud-server-gateway/src/main/java/cn/mb/cloud/gateway/util/SpringUtil.java new file mode 100644 index 0000000..7a5564d --- /dev/null +++ b/cloud-server-gateway/src/main/java/cn/mb/cloud/gateway/util/SpringUtil.java @@ -0,0 +1,34 @@ +package cn.mb.cloud.gateway.util; + +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.stereotype.Component; + +@Component +public class SpringUtil implements ApplicationContextAware { + @Autowired + private static ApplicationContext applicationContext; + + @Override + public void setApplicationContext(ApplicationContext applicationContextParam) throws BeansException { + applicationContext = applicationContextParam; + } + public static Object getObject(String id) { + Object object = null; + object = applicationContext.getBean(id); + return object; + } + public static <T> T getObject(Class<T> tClass) { + return applicationContext.getBean(tClass); + } + + public static Object getBean(String tClass) { + return applicationContext.getBean(tClass); + } + + public <T> T getBean(Class<T> tClass) { + return applicationContext.getBean(tClass); + } +} \ No newline at end of file diff --git a/cloud-server-gateway/src/main/java/cn/mb/cloud/gateway/util/StringUtil.java b/cloud-server-gateway/src/main/java/cn/mb/cloud/gateway/util/StringUtil.java new file mode 100644 index 0000000..4ec8eaf --- /dev/null +++ b/cloud-server-gateway/src/main/java/cn/mb/cloud/gateway/util/StringUtil.java @@ -0,0 +1,121 @@ +package cn.mb.cloud.gateway.util; + +import org.apache.commons.lang.StringUtils; + +public class StringUtil { + + /** + * 判断字符串中是否包含表情 + * @param source + * @return + */ + public static boolean containsEmoji(String source) { + int len = 0; + if(null != source){ + len = source.length(); + } + boolean isEmoji = false; + for (int i = 0; i < len; i++) { + char hs = source.charAt(i); + if (0xd800 <= hs && hs <= 0xdbff) { + if (source.length() > 1) { + char ls = source.charAt(i + 1); + int uc = ((hs - 0xd800) * 0x400) + (ls - 0xdc00) + 0x10000; + if (0x1d000 <= uc && uc <= 0x1f77f) { + return true; + } + } + } else { + // non surrogate + if (0x2100 <= hs && hs <= 0x27ff && hs != 0x263b) { + return true; + } else if (0x2B05 <= hs && hs <= 0x2b07) { + return true; + } else if (0x2934 <= hs && hs <= 0x2935) { + return true; + } else if (0x3297 <= hs && hs <= 0x3299) { + return true; + } else if (hs == 0xa9 || hs == 0xae || hs == 0x303d + || hs == 0x3030 || hs == 0x2b55 || hs == 0x2b1c + || hs == 0x2b1b || hs == 0x2b50 || hs == 0x231a) { + return true; + } + if (!isEmoji && source.length() > 1 && i < source.length() - 1) { + char ls = source.charAt(i + 1); + if (ls == 0x20e3) { + return true; + } + } + } + } + return isEmoji; + } + + /** + * 判断某个字符是不是表情 + * @param codePoint + * @return + */ + private static boolean isEmojiCharacter(char codePoint) { + return (codePoint == 0x0) || (codePoint == 0x9) || (codePoint == 0xA) + || (codePoint == 0xD) + || ((codePoint >= 0x20) && (codePoint <= 0xD7FF)) + || ((codePoint >= 0xE000) && (codePoint <= 0xFFFD)) + || ((codePoint >= 0x10000) && (codePoint <= 0x10FFFF)); + } + + + /** + * 过滤掉字符串中的表情 + * @param source + * @return + */ + public static String filterEmoji(String source) { + if (StringUtils.isBlank(source)) { + return source; + } + StringBuilder buf = null; + int len = source.length(); + for (int i = 0; i < len; i++) { + char codePoint = source.charAt(i); + if (isEmojiCharacter(codePoint)) { + if (buf == null) { + buf = new StringBuilder(source.length()); + } + buf.append(codePoint); + } + } + if (buf == null) { + return source; + } else { + if (buf.length() == len) { + buf = null; + return source; + } else { + return buf.toString(); + } + } + } + + + /** + * 判断字符串为空 + * @param value + * @return + */ + public static boolean isEmpty(String value){ + if(null == value || value.trim().equals("")){ + return true; + } + return false; + } + + /** + * 判断字符串非空 + * @param value + * @return + */ + public static boolean isNotEmpty(String value){ + return !isEmpty(value); + } +} diff --git a/cloud-server-gateway/src/main/java/cn/mb/cloud/gateway/util/applets/CacheType.java b/cloud-server-gateway/src/main/java/cn/mb/cloud/gateway/util/applets/CacheType.java new file mode 100644 index 0000000..c47d65f --- /dev/null +++ b/cloud-server-gateway/src/main/java/cn/mb/cloud/gateway/util/applets/CacheType.java @@ -0,0 +1,86 @@ +package cn.mb.cloud.gateway.util.applets; + +/** + * 缓存消息类型 + * + * @author TaoNingBo + * @data 2016年9月21日 + * @version 1.0 + */ +public class CacheType { + + /** + * 用户通讯通道标识 + */ + public static final String userCtx = "USER_CTX_"; + + /** + * 司机通讯通道标识 + */ + public static final String driverCtx = "DRIVER_CTX_"; + + /** + * 出行-快车/专车/代驾-订单消息队列-自营车辆 + */ + public static final String travelOrder1 = "TRAVEL_ORDER1_"; + + /** + * 出行-快车/专车/代驾-订单消息队列-外来车辆 + */ + public static final String travelOrder2 = "TRAVEL_ORDER2_"; + + /** + * 快车-司机位置-自营车辆 + */ + public static final String location1 = "_LOCATION1"; + + /** + * 快车-司机位置-外来车辆 + */ + public static final String location2 = "_LOCATION2"; + + /** + * 快车-司机抢单成功后的消息 + */ + public static final String travelOrder = "TRAVEL_ORDER_"; + + /** + * 开始服务时间 + */ + public static final String startServerT = "START_SERVER_TIME_"; + + /** + * 司机上一次的位置(经纬度) + */ + public static final String location = "LAST_DRIVER_LOCATION_"; + + /** + * 司机上一次总共行驶距离 + */ + public static final String triverd = "LAST_TRIVER_Distance_"; + + /** + * 记录订单数据 司机 异常处理 + */ + public static final String dreco = "DRIVER_DATA_RECO"; + + /** + * 记录订单数据 用户 异常处理 + */ + public static final String ureco = "USER_DATA_RECO"; + + /** + * 记录司机跟用户的关系ID + */ + public final static String udID = "USER_DRIVER_ID_"; + + /** + * 记录下单乘客的出发点位置坐标 + */ + public final static String userLoc = "USER_LOCATION_"; + + /** + * 记录计费规则【用订单号获取】 + */ + public final static String rules = "RULES_ORDER_"; +} diff --git a/cloud-server-gateway/src/main/java/cn/mb/cloud/gateway/util/applets/ChildChannelHandler.java b/cloud-server-gateway/src/main/java/cn/mb/cloud/gateway/util/applets/ChildChannelHandler.java new file mode 100644 index 0000000..59c929f --- /dev/null +++ b/cloud-server-gateway/src/main/java/cn/mb/cloud/gateway/util/applets/ChildChannelHandler.java @@ -0,0 +1,36 @@ +package cn.mb.cloud.gateway.util.applets; + +import io.netty.channel.ChannelInitializer; +import io.netty.channel.socket.SocketChannel; +import io.netty.handler.codec.http.HttpObjectAggregator; +import io.netty.handler.codec.http.HttpServerCodec; +import io.netty.handler.ssl.SslHandler; +import io.netty.handler.stream.ChunkedWriteHandler; + +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLEngine; + +public class ChildChannelHandler extends ChannelInitializer<SocketChannel> { + @Override + protected void initChannel(SocketChannel socketChannel) throws Exception { + String path = "D:\\Program Files\\Apache Software Foundation\\Tomcat 8.5-80\\cert\\6855055_zhentonggongsi.com.pfx"; +// String path = "/usr/local/server/apache-tomcat-80/conf/cert/6064978_okyueche.com.pfx"; + SSLContext sslContext = createSSLContext.createSSLContext("PKCS12" + , path, "jBOjj2fR"); + //SSLEngine 此类允许使用ssl安全套接层协议进行安全通信 + SSLEngine engine = sslContext.createSSLEngine(); + engine.setUseClientMode(false); + socketChannel.pipeline().addLast("ssl", new SslHandler(engine)); + + // 设置30秒没有读到数据,则触发一个READER_IDLE事件。 + // pipeline.addLast(new IdleStateHandler(30, 0, 0)); + // HttpServerCodec:将请求和应答消息解码为HTTP消息 + socketChannel.pipeline().addLast("http-codec", new HttpServerCodec()); + // HttpObjectAggregator:将HTTP消息的多个部分合成一条完整的HTTP消息 + socketChannel.pipeline().addLast("aggregator", new HttpObjectAggregator(65536)); + // ChunkedWriteHandler:向客户端发送HTML5文件 + socketChannel.pipeline().addLast("http-chunked", new ChunkedWriteHandler()); + // 在管道中添加我们自己的接收数据实现方法 + socketChannel.pipeline().addLast("handler", new WebSocketHandler()); + } +} diff --git a/cloud-server-gateway/src/main/java/cn/mb/cloud/gateway/util/applets/ClientPingMessage.java b/cloud-server-gateway/src/main/java/cn/mb/cloud/gateway/util/applets/ClientPingMessage.java new file mode 100644 index 0000000..7640fdd --- /dev/null +++ b/cloud-server-gateway/src/main/java/cn/mb/cloud/gateway/util/applets/ClientPingMessage.java @@ -0,0 +1,59 @@ +package cn.mb.cloud.gateway.util.applets; + +import java.io.Serializable; + +/** + * 客户端心跳消息处理 + * + * @author TaoNingBo + * @data 2016年7月26日 + * @version 1.0 + */ +public class ClientPingMessage implements Serializable { + + private static final long serialVersionUID = -4953410803742767757L; + + /** + * 客户端标识ID + */ + private Integer id; + + /** + * 角色【0:用户,1:司机】 + */ + private Integer role; + + /** + * 客户端单点登录标识TOKEN + */ + private String token; + + public ClientPingMessage() { + + } + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public Integer getRole() { + return role; + } + + public void setRole(Integer role) { + this.role = role != null ? role : 0; + } + + public String getToken() { + return token; + } + + public void setToken(String token) { + this.token = token; + } + +} diff --git a/cloud-server-gateway/src/main/java/cn/mb/cloud/gateway/util/applets/Global.java b/cloud-server-gateway/src/main/java/cn/mb/cloud/gateway/util/applets/Global.java new file mode 100644 index 0000000..a16897a --- /dev/null +++ b/cloud-server-gateway/src/main/java/cn/mb/cloud/gateway/util/applets/Global.java @@ -0,0 +1,9 @@ +package cn.mb.cloud.gateway.util.applets; + +import io.netty.channel.group.ChannelGroup; +import io.netty.channel.group.DefaultChannelGroup; +import io.netty.util.concurrent.GlobalEventExecutor; + +public class Global { + public static ChannelGroup group = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE); +} diff --git a/cloud-server-gateway/src/main/java/cn/mb/cloud/gateway/util/applets/NettyServer0.java b/cloud-server-gateway/src/main/java/cn/mb/cloud/gateway/util/applets/NettyServer0.java new file mode 100644 index 0000000..40486de --- /dev/null +++ b/cloud-server-gateway/src/main/java/cn/mb/cloud/gateway/util/applets/NettyServer0.java @@ -0,0 +1,77 @@ +package cn.mb.cloud.gateway.util.applets; + +import io.netty.bootstrap.ServerBootstrap; +import io.netty.channel.Channel; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.nio.NioServerSocketChannel; + +import java.util.Timer; +import java.util.TimerTask; + + +/** + * 即时通讯服务启动类 + * + * @date 2016年6月25日 + * @version 1.0 + */ +public class NettyServer0 { + + /** + * 延迟启动设置 + * + * NettyServer启动方法. + */ + public void bind() { + final Thread thread = new Thread(new NettyRunnable()); + Timer timer = new Timer(); + timer.schedule(new TimerTask() { + @Override + public void run() { + thread.start(); + } + }, 1000 * 2); + } + + /** + * 即时通讯服务启动 + * + * @date 2016年6月24日 + * @version 1.0 + */ + public class NettyRunnable implements Runnable { + + /** + * 获取即时通讯启动端口 + */ + @Override + public void run() { + System.out.println("===========================Netty端口启动========"); + // Boss线程:由这个线程池提供的线程是boss种类的,用于创建、连接、绑定socket, + // (有点像门卫)然后把这些socket传给worker线程池。 + // 在服务器端每个监听的socket都有一个boss线程来处理。在客户端,只有一个boss线程来处理所有的socket。 + EventLoopGroup bossGroup = new NioEventLoopGroup(); + // Worker线程:Worker线程执行所有的异步I/O,即处理操作 + EventLoopGroup workrGroup = new NioEventLoopGroup(); + try { + + // ServerBootstrap 启动NIO服务的辅助启动类,负责初始话netty服务器,并且开始监听端口的socket请求 + ServerBootstrap b = new ServerBootstrap(); + b.group(bossGroup, workrGroup); + // 设置非阻塞,用它来建立新accept的连接,用于构造serversocketchannel的工厂类 + b.channel(NioServerSocketChannel.class); + // ChildChannelHandler 对出入的数据进行的业务操作,其继承ChannelInitializer + b.childHandler(new ChildChannelHandler()); + System.out.println("服务端开启等待客户端连接 ... ..."); + Channel ch = b.bind(9090).sync().channel(); + ch.closeFuture().sync(); + } catch (Exception e) { + e.printStackTrace(); + } finally { + bossGroup.shutdownGracefully(); + workrGroup.shutdownGracefully(); + } + } + } +} diff --git a/cloud-server-gateway/src/main/java/cn/mb/cloud/gateway/util/applets/NettyWebSocketController.java b/cloud-server-gateway/src/main/java/cn/mb/cloud/gateway/util/applets/NettyWebSocketController.java new file mode 100644 index 0000000..8bd7a5c --- /dev/null +++ b/cloud-server-gateway/src/main/java/cn/mb/cloud/gateway/util/applets/NettyWebSocketController.java @@ -0,0 +1,205 @@ +package cn.mb.cloud.gateway.util.applets; + + +import cn.mb.cloud.gateway.util.RedisUtil; +import cn.mb.cloud.gateway.util.SinataUtil; +import cn.mb.cloud.gateway.util.SpringUtil; +import cn.mb.cloud.gateway.util.StringUtil; +import cn.mb.cloud.gateway.util.echo.Method; +import cn.mb.cloud.gateway.util.echo.NettyChannelMap; +import com.alibaba.fastjson.JSONObject; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.http.websocketx.TextWebSocketFrame; + +import java.util.Hashtable; +import java.util.Timer; +import java.util.TimerTask; + +public class NettyWebSocketController { + + public static Hashtable<String, Hashtable<ChannelHandlerContext, String>> map = new Hashtable<String, Hashtable<ChannelHandlerContext, String>>(); + + private RedisUtil redisUtil = SpringUtil.getObject(RedisUtil.class); + + public static Hashtable<String, String> table; + + static { + if (table == null) { + table = new Hashtable<>(); + } + } + + public static boolean isdebug = false; + public static int i = 0; + + + /** + * 判断客户端要执行什么操作 + * + * @param ctx + * @param msg + * @author TaoNingBo + */ + public void JudgeOperation(ChannelHandlerContext ctx, String msg) { + try { + // 验证即时通讯命令是否正确有效 + if (SinataUtil.isEmpty(msg)) { + return; + } + String msgStr = msg.toString(); + if (msgStr.indexOf("{") == -1 || msgStr.indexOf("}") == -1 || msgStr.indexOf("code") == -1 || msgStr.indexOf("msg") == -1 || msgStr.indexOf("data") == -1 || msgStr.indexOf("method") == -1) { + return; + } + if (isdebug) { +// System.out.println("<<<--receive-->>>111" + msg); + } + + // 获取socket信息,保存相应的socket + JSONObject jsonMsg = JSONObject.parseObject(msg.toString()); + int code = jsonMsg.getIntValue("code"); + String message = jsonMsg.getString("msg"); + String method = jsonMsg.getString("method"); + if (code != 200 || !message.equals("SUCCESS")) { + return; + } + JSONObject jsonCon = JSONObject.parseObject(jsonMsg.get("data").toString()); + + if (null != ctx && ctx.channel().isActive()) { + jsonMsg.put("method", Method.pong); + sendMsgToClient(ctx, jsonMsg.toJSONString()); + } + + + // ############################### 心跳 ############################ + // 心跳 + if (method.equals(Method.ping)) { + String token = jsonCon.getString("token"); + String userId1 = jsonCon.getString("userId"); + if (StringUtil.isNotEmpty(userId1)) { + //确保账号在单个设备上登录 + if (StringUtil.isNotEmpty(token)) { + NettyChannelMap.update_(token.substring(0, 23), ctx);//存储单点登录的通道 + String token_ = redisUtil.getValue("USER_Applets_" + userId1);//获取缓存中最新的数据 + if (StringUtil.isNotEmpty(token_) && !token.equals(token_)) {//不在同一设备上登录,向其他设备发送数据 + JSONObject msg_ = new JSONObject(); + msg_.put("code", 200); + msg_.put("msg", "SUCCESS"); + msg_.put("method", "OFFLINE"); + msg_.put("data", new Object()); + this.sendMsgToClient(ctx, msg_.toJSONString()); + TimerTask timerTask = new TimerTask() { + @Override + public void run() { + NettyChannelMap.remove_(ctx); + } + }; + Timer timer = new Timer(); + timer.schedule(timerTask, 3000); + timer.cancel(); + } + if (StringUtil.isEmpty(token_)) {//确保登录的时候存储token失败的情况 + redisUtil.setStrValue("USER_Applets_" + userId1, token); + } + } + + //存储业务使用的通道 + if (null != ctx && ctx.channel().isActive()) { + NettyChannelMap.update("Applets" + userId1, ctx); +// String s = NettyMsg.setMsg(Method.ok, new HashMap<String, Object>()); +// ctx.writeAndFlush(Unpooled.copiedBuffer((s).getBytes())); + } + } + + + } + } catch (Exception e) { + if (isdebug) { + NettyWebSocketController.sendMsgToClient(ctx, "__error__" + msg.toString()); + } + e.printStackTrace(); + } + } + + /** + * 向客户端发送消息 + * + * @param ctx + * @param msg + * @author TaoNingBo + */ + public static void sendMsgToClient(ChannelHandlerContext ctx, String msg) { +// System.out.println(ctx.channel().isActive()); + if (ctx != null && ctx.channel().isActive()) { + ByteBuf buffer = Unpooled.copiedBuffer((msg).getBytes()); + ChannelFuture sync; + try { + sync = ctx.channel().writeAndFlush(new TextWebSocketFrame(msg)).sync(); + if (!sync.isSuccess()) { + boolean b = true; + for (int i = 0; i < 10; i++) { + ctx.wait(3000); + sync = ctx.channel().write(new TextWebSocketFrame(msg)).sync(); + if (sync.isSuccess()) { + b = false; + break; + } + System.err.println("小程序-》推送不成功,将继续推送" + msg); + } + if (b) { + NettyChannelMap.remove(ctx); + } + } + } catch (Exception e) { + System.err.println("小程序-》推送发生异常,记录:" + msg); + NettyChannelMap.remove(ctx); + } + if (isdebug) { + System.err.println("小程序-》 <<<--send-->>>" + msg); + } + } else { + System.err.println("小程序-》推送失败,长连接不存在"); + NettyChannelMap.remove(ctx); + } + } + + // **链接断开 将推送消息记录 + public static void sendMsgToClient(String cacheType, Integer id, String msg) { + ChannelHandlerContext ctx = NettyChannelMap.getData(cacheType + id); + if (ctx != null) { + ChannelFuture sync; + try { + sync = ctx.channel().write(new TextWebSocketFrame(msg)).sync(); + if (!sync.isSuccess()) { + for (int i = 0; i < 10; i++) { + sync = ctx.channel().write(new TextWebSocketFrame(msg)).sync(); + ; + if (!sync.isSuccess()) { + sync = ctx.channel().write(new TextWebSocketFrame(msg)).sync(); + ; + System.err.println("推送不成功,将继续推送" + msg); + if (i == 9) { + table.put(cacheType + id, msg); + ctx.close(); + System.err.println("推送发生异常,记录:" + msg); + } + } else { + break; + } + } + } + } catch (Exception e) { + table.put(cacheType + id, msg); + System.err.println("推送发生异常,记录:" + msg); + } + if (isdebug) { + System.err.println("<<<--send-->>>" + msg); + } + } else { + table.put(cacheType + id, msg); + System.err.println("链接断开,记录:id=" + cacheType + id + ",消息:" + msg); + } + } +} diff --git a/cloud-server-gateway/src/main/java/cn/mb/cloud/gateway/util/applets/WebSocketHandler.java b/cloud-server-gateway/src/main/java/cn/mb/cloud/gateway/util/applets/WebSocketHandler.java new file mode 100644 index 0000000..876dde0 --- /dev/null +++ b/cloud-server-gateway/src/main/java/cn/mb/cloud/gateway/util/applets/WebSocketHandler.java @@ -0,0 +1,180 @@ +package cn.mb.cloud.gateway.util.applets; + +import cn.mb.cloud.gateway.util.echo.Method; +import cn.mb.cloud.gateway.util.echo.NettyChannelMap; +import cn.mb.cloud.gateway.util.echo.NettyMsg; +import com.alibaba.fastjson.JSONObject; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelFutureListener; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.SimpleChannelInboundHandler; +import io.netty.handler.codec.http.*; +import io.netty.handler.codec.http.websocketx.*; +import io.netty.handler.timeout.IdleState; +import io.netty.handler.timeout.IdleStateEvent; +import io.netty.util.CharsetUtil; + +import java.util.HashMap; + + +public class WebSocketHandler extends SimpleChannelInboundHandler<Object> { + //用于websocket握手的处理类 + private WebSocketServerHandshaker handshaker; + + private static final String WEB_SOCKET_URL = "wss://localhost:9090/websocket"; + + + +// @Override +// protected void messageReceived(ChannelHandlerContext ctx, Object msg) throws Exception { +// if (msg instanceof FullHttpRequest) { +// // websocket连接请求 +// handleHttpRequest(ctx, (FullHttpRequest)msg); +// } else if (msg instanceof WebSocketFrame) { +// // websocket业务处理 +// handleWebSocketRequest(ctx, (WebSocketFrame)msg); +// } +// } + + @Override + public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { + ctx.flush(); + } + + /** 心跳 */ + @Override + public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { + if (evt instanceof IdleStateEvent) { + IdleStateEvent event = (IdleStateEvent) evt; + if (event.state().equals(IdleState.READER_IDLE)) + { + // + } + else if (event.state().equals(IdleState.WRITER_IDLE)) + { + // + } + else if (event.state().equals(IdleState.ALL_IDLE)) + { + String msg = NettyMsg.setMsg(Method.ok, new HashMap<String, Object>()); + if(ctx != null && ctx.channel().isActive()) { + ctx.writeAndFlush(Unpooled.copiedBuffer((msg).getBytes())); + } + } + } +// super.userEventTriggered(ctx, evt); + } + + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { + ctx.close(); + } + + private void handleHttpRequest(ChannelHandlerContext ctx, FullHttpRequest req) { + // Http解码失败,向服务器指定传输的协议为Upgrade:websocket + if(!req.getDecoderResult().isSuccess() || !("websocket").equals(req.headers().get("Upgrade"))){ + sendHttpResponse(ctx, req, new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.BAD_REQUEST)); + return; + } + // 握手相应处理,创建websocket握手的工厂类, + WebSocketServerHandshakerFactory wsFactory = new WebSocketServerHandshakerFactory(WEB_SOCKET_URL, null, false); + // 根据工厂类和HTTP请求创建握手类 + handshaker = wsFactory.newHandshaker(req); + if (handshaker == null) { + // 不支持websocket + WebSocketServerHandshakerFactory.sendUnsupportedWebSocketVersionResponse(ctx.channel()); + } else { + // 通过它构造握手响应消息返回给客户端 + handshaker.handshake(ctx.channel(), req); + } + } + + private void handleWebSocketRequest(ChannelHandlerContext ctx, WebSocketFrame req) throws Exception { + if (req instanceof CloseWebSocketFrame) { + // 关闭websocket连接 + handshaker.close(ctx.channel(), (CloseWebSocketFrame)req.retain()); + return; + } + if (req instanceof PingWebSocketFrame) { + ctx.channel().write(new PongWebSocketFrame(req.content().retain())); + return; + } + if (!(req instanceof TextWebSocketFrame)) { + throw new UnsupportedOperationException("当前只支持文本消息,不支持二进制消息"); + } + if (ctx == null || this.handshaker == null || ctx.isRemoved()) { + throw new Exception("尚未握手成功,无法向客户端发送WebSocket消息"); + } + String requestmsg = ((TextWebSocketFrame) req).text(); + + + //给连接的客户端返回数据 + //返回心跳 + JSONObject jsonObject = new JSONObject(); + jsonObject.put("code", 200); + jsonObject.put("method", Method.ok); + jsonObject.put("msg", "SUCCESS"); + jsonObject.put("data", new JSONObject()); + TextWebSocketFrame tws = new TextWebSocketFrame(jsonObject.toJSONString()); +// ctx.channel().writeAndFlush(tws); + + new NettyWebSocketController().JudgeOperation(ctx,requestmsg);//小程序心跳处理 + + // 群发服务端心跳响应 + Global.group.writeAndFlush(new TextWebSocketFrame((tws).text())); + } + + private void sendHttpResponse(ChannelHandlerContext ctx, FullHttpRequest req, FullHttpResponse res) { + // BAD_REQUEST(400) 客户端请求错误返回的应答消息 + if(res.getStatus().code() != 200){ + ByteBuf buf = Unpooled.copiedBuffer(res.getStatus().toString(), CharsetUtil.UTF_8); + res.content().writeBytes(buf); + buf.release(); + } + //服务端向客户端发送数据 + ChannelFuture f = ctx.channel().writeAndFlush(res); + // 非法连接直接关闭连接 + if(res.getStatus().code() != 200){ + f.addListener(ChannelFutureListener.CLOSE); + } + } + + + @Override + public void channelActive(ChannelHandlerContext ctx) throws Exception { + Global.group.add(ctx.channel()); + System.err.println("客户端与服务器端开启"); + } + + @Override + public void channelInactive(ChannelHandlerContext ctx) throws Exception { + Global.group.remove(ctx.channel()); + NettyChannelMap.remove(ctx); + System.err.println("客户端与服务器链接关闭"); + } + + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + if (msg instanceof FullHttpRequest) { + // websocket连接请求 + handleHttpRequest(ctx, (FullHttpRequest)msg); + } else if (msg instanceof WebSocketFrame) { + // websocket业务处理 + handleWebSocketRequest(ctx, (WebSocketFrame)msg); + } + } + + @Override + protected void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception { + if (msg instanceof FullHttpRequest) { + // websocket连接请求 + handleHttpRequest(ctx, (FullHttpRequest)msg); + } else if (msg instanceof WebSocketFrame) { + // websocket业务处理 + handleWebSocketRequest(ctx, (WebSocketFrame)msg); + } + } +} diff --git a/cloud-server-gateway/src/main/java/cn/mb/cloud/gateway/util/applets/createSSLContext.java b/cloud-server-gateway/src/main/java/cn/mb/cloud/gateway/util/applets/createSSLContext.java new file mode 100644 index 0000000..cdfc246 --- /dev/null +++ b/cloud-server-gateway/src/main/java/cn/mb/cloud/gateway/util/applets/createSSLContext.java @@ -0,0 +1,31 @@ +package cn.mb.cloud.gateway.util.applets; + +import javax.net.ssl.KeyManagerFactory; +import javax.net.ssl.SSLContext; +import java.io.FileInputStream; +import java.io.InputStream; +import java.security.KeyStore; + +public class createSSLContext { + + /** + * 获取SSLContext + * @param type + * @param path + * @param password + * @return + * @throws Exception + */ + public static SSLContext createSSLContext(String type , String path , String password) throws Exception { + KeyStore ks = KeyStore.getInstance(type); /// "JKS" + InputStream ksInputStream = new FileInputStream(path); /// 证书存放地址 + ks.load(ksInputStream, password.toCharArray()); + //KeyManagerFactory充当基于密钥内容源的密钥管理器的工厂。 + KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());//getDefaultAlgorithm:获取默认的 KeyManagerFactory 算法名称。 + kmf.init(ks, password.toCharArray()); + //SSLContext的实例表示安全套接字协议的实现,它充当用于安全套接字工厂或 SSLEngine 的工厂。 + SSLContext sslContext = SSLContext.getInstance("TLS"); + sslContext.init(kmf.getKeyManagers(), null, null); + return sslContext; + } +} diff --git a/cloud-server-gateway/src/main/java/cn/mb/cloud/gateway/util/echo/DiscardServerHandler.java b/cloud-server-gateway/src/main/java/cn/mb/cloud/gateway/util/echo/DiscardServerHandler.java new file mode 100644 index 0000000..37f79a1 --- /dev/null +++ b/cloud-server-gateway/src/main/java/cn/mb/cloud/gateway/util/echo/DiscardServerHandler.java @@ -0,0 +1,153 @@ +package cn.mb.cloud.gateway.util.echo; + +import io.netty.buffer.Unpooled; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelPromise; +import io.netty.channel.SimpleChannelInboundHandler; +import io.netty.handler.timeout.IdleState; +import io.netty.handler.timeout.IdleStateEvent; +import io.netty.util.ReferenceCountUtil; + +import java.net.InetSocketAddress; +import java.util.HashMap; + +public class DiscardServerHandler extends SimpleChannelInboundHandler<String> { + + private NettyServerController nettyServerController = new NettyServerController(); + + public static boolean isdebug = true; + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) { + InetSocketAddress insocket = (InetSocketAddress) ctx.channel().remoteAddress(); + if(isdebug) { +// System.err.println(insocket.getAddress() + ": 收到客户端数据......."); + } + try { + // 调用service + nettyServerController.JudgeOperation(ctx, msg); + } catch (Exception e) { + e.printStackTrace(); + } finally { + ReferenceCountUtil.release(msg); + } + } + + @Override + protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception { + InetSocketAddress insocket = (InetSocketAddress) ctx.channel().remoteAddress(); + if(isdebug) { +// System.err.println(insocket.getAddress() + ": 收到客户端数据......."); + } + try { + // 调用service + nettyServerController.JudgeOperation(ctx, msg); + } catch (Exception e) { + e.printStackTrace(); + } finally { + ReferenceCountUtil.release(msg); + } + } + +// @Override +// protected void messageReceived(ChannelHandlerContext channelHandlerContext, String s) throws Exception { +// +// } + +// @Override +// protected void channelRead0(ChannelHandlerContext channelHandlerContext, String s) throws Exception { +// +// } + +// @Override +// protected void messageReceived(ChannelHandlerContext channelHandlerContext, String s) throws Exception { +// +// } + + /** 在连接被建立并且准备进行通信时被调用 */ + public void channelActive(final ChannelHandlerContext ctx) throws Exception { + InetSocketAddress insocket = (InetSocketAddress) ctx.channel().remoteAddress(); + if(isdebug) { +// System.err.println(insocket.getAddress() + ": Connect successful......"); + } + } + + /** 心跳 */ + @Override + public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { + if (evt instanceof IdleStateEvent) { + IdleStateEvent event = (IdleStateEvent) evt; + if (event.state().equals(IdleState.READER_IDLE)) + { + // + } + else if (event.state().equals(IdleState.WRITER_IDLE)) + { + // + } + else if (event.state().equals(IdleState.ALL_IDLE)) + { + String msg = NettyMsg.setMsg(Method.ok, new HashMap<String, Object>()); + if(ctx != null && ctx.channel().isActive()) { + ctx.writeAndFlush(Unpooled.copiedBuffer((msg).getBytes())); +// System.err.println(msg); + } + } + } + //super.userEventTriggered(ctx, evt); + } + + /** 连接处于不活跃时调用(连接关闭) **/ + public void channelInactive(ChannelHandlerContext ctx) throws Exception { + if(isdebug) { + InetSocketAddress insocket = (InetSocketAddress) ctx.channel().remoteAddress(); +// System.err.println(insocket.getAddress() + ": Disconnect connection......"); + } + NettyChannelMap.remove(ctx); +// System.err.println("清除通道" + ctx); +// super.channelInactive(ctx); + } + + public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { + ctx.flush(); + } + + /** 处理方法是当出现Throwable对象才会被调用 **/ + public void exceptionCaught(ChannelHandlerContext ctx,Throwable cause) throws Exception { + ctx.close(); + } + + public void close(ChannelHandlerContext ctx, ChannelPromise promise) throws Exception { + if(isdebug) { + InetSocketAddress insocket = (InetSocketAddress) ctx.channel().remoteAddress(); +// System.err.println("close......." + insocket.getAddress()); + } + ctx.close(promise); + } + + public void read(ChannelHandlerContext ctx) throws Exception { + ctx.read(); + } + + public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { + ctx.write(msg, promise); + } + +// @Override +// protected void channelRead(ChannelHandlerContext ctx, String msg) throws Exception { +// // TODO Auto-generated method stub +// InetSocketAddress insocket = (InetSocketAddress) ctx.channel().remoteAddress(); +// if(isdebug) { +// System.out.println(insocket.getAddress() + ": 收到客户端数据......."); +// } +// try { +// // 调用service +// nettyServerController.JudgeOperation(ctx, msg); +// } catch (Exception e) { +// e.printStackTrace(); +// } finally { +// ReferenceCountUtil.release(msg); +// } +// } + +} diff --git a/cloud-server-gateway/src/main/java/cn/mb/cloud/gateway/util/echo/Method.java b/cloud-server-gateway/src/main/java/cn/mb/cloud/gateway/util/echo/Method.java new file mode 100644 index 0000000..be79edc --- /dev/null +++ b/cloud-server-gateway/src/main/java/cn/mb/cloud/gateway/util/echo/Method.java @@ -0,0 +1,26 @@ +package cn.mb.cloud.gateway.util.echo; + +/** + * 即时通讯【通讯类型类】 + * + * @author TaoNingBo + * @createDate 2016年6月14日 + * @version 1.0 + */ +public class Method { + + /** 心跳【推送】 */ + public static final String ok = "OK"; + + /** 心跳【接收】 */ + public final static String ping = "PING"; + + /** 心跳【响应】 */ + public final static String pong = "PONG"; + + /** 司机上传位置 */ + public static final String location = "LOCATION"; + + + +} diff --git a/cloud-server-gateway/src/main/java/cn/mb/cloud/gateway/util/echo/NettyChannelMap.java b/cloud-server-gateway/src/main/java/cn/mb/cloud/gateway/util/echo/NettyChannelMap.java new file mode 100644 index 0000000..1e42cb4 --- /dev/null +++ b/cloud-server-gateway/src/main/java/cn/mb/cloud/gateway/util/echo/NettyChannelMap.java @@ -0,0 +1,133 @@ +package cn.mb.cloud.gateway.util.echo; + +import io.netty.channel.ChannelHandlerContext; + +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + +public class NettyChannelMap { + + protected static Map<String, ChannelHandlerContext> map = new ConcurrentHashMap<>(); + + public static Map<String, ChannelHandlerContext> ctxMap = new HashMap<>();//单点登录存储的通道 + + + private NettyChannelMap() { + // 放置外部实例化 + } + + /** + * Get data from source. + * + * @param key + * @return + */ + public static ChannelHandlerContext getData(String key) { + if(map==null){ + map = new HashMap<String, ChannelHandlerContext>(); + } + return map.get(key); + } + + + public static ChannelHandlerContext getData_(String key) { + if(ctxMap==null){ + ctxMap = new HashMap<String, ChannelHandlerContext>(); + } + return ctxMap.get(key); + } + + + /** + * Save data from source. + * + * @param key + * @param val + */ + public static synchronized void saveData(String key, ChannelHandlerContext val) { + map.put(key, val); + } + + /** + * Determine whether the cache key contains the key. + * + * @param key + * @return true|false + * @author TaoNingBo + */ + public static synchronized boolean containsKey(String key) { + return map.containsKey(key); + } + + /** + * Determine whether the cache value contains the value. + * + * @param val + * @return + */ + public static synchronized boolean containsVal(ChannelHandlerContext val) { + return map.containsValue(val); + } + + /** + * Remove the data resources. + * + * @param value + */ + @SuppressWarnings("rawtypes") + public static synchronized void remove(ChannelHandlerContext value) { + Set<String> strings = map.keySet(); + for(String key : strings){ + ChannelHandlerContext channelHandlerContext = map.get(key); + String s = channelHandlerContext.channel().remoteAddress().toString(); + String s1 = value.channel().remoteAddress().toString(); + if(s.equals(s1)){ + channelHandlerContext.close();//关闭通道 + map.remove(key); + } + } + } + + + public static synchronized void remove_(ChannelHandlerContext value) { + Set<String> strings = ctxMap.keySet(); + for(String key : strings){ + ChannelHandlerContext channelHandlerContext = ctxMap.get(key); + String s = channelHandlerContext.channel().remoteAddress().toString(); + String s1 = value.channel().remoteAddress().toString(); + if(s.equals(s1)){ + channelHandlerContext.close();//关闭通道 + ctxMap.remove(key); + } + } + } + + + /** + * Remove the data resources. + * + * @param key + * @author TaoNingBo + */ + public static synchronized void remove(String key) { + map.remove(key); + } + + /** + * Update the data resources. + * + * @param key + * @param value + */ + public static synchronized void update(String key, ChannelHandlerContext value) { + map.put(key, value); + } + + + + public static synchronized void update_(String key, ChannelHandlerContext value) { + ctxMap.put(key, value); + } +} diff --git a/cloud-server-gateway/src/main/java/cn/mb/cloud/gateway/util/echo/NettyMsg.java b/cloud-server-gateway/src/main/java/cn/mb/cloud/gateway/util/echo/NettyMsg.java new file mode 100644 index 0000000..665fb61 --- /dev/null +++ b/cloud-server-gateway/src/main/java/cn/mb/cloud/gateway/util/echo/NettyMsg.java @@ -0,0 +1,165 @@ +package cn.mb.cloud.gateway.util.echo; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelHandlerContext; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + + +public class NettyMsg { + public static void main(String[] args) { + Map<String,Object> map = new HashMap<String, Object>(); + //用户信息 + map.put("imgUrl","1"); + map.put("nickName","1"); + map.put("licensePlate","1"); + map.put("phone",1); + map.put("driverId",1); + map.put("carColor","1"); + map.put("modelName","1"); + map.put("brandName","1"); + map.put("driverOrderNums",1); + map.put("score",1); + + + map.put("id",1); + map.put("orderNum", "123456"); + map.put("startAddress", "测试"); + map.put("endAddress", "测试1"); + map.put("departureTime", 1533608196000L); + map.put("type",1); + map.put("mileage",1); + map.put("mileageMoney",10); + map.put("duration",10); + map.put("durationMoney",10); + map.put("nightMoney",1); + map.put("serverMoney",1); + map.put("nightMileage",10); + map.put("longMileage",10); + map.put("longDurationMoney",10); + map.put("orderMoney",10); + map.put("payMoney",10); + map.put("couponsMoney",10); + System.out.println(setMsg(Method.ping, new HashMap<String, Object>())); + } + + /** + * 返回一个正确数据 + * + * @param method + * @param data + * @return + * @author TaoNingBo + */ + public static String setMsg(String method, Map<String, Object> data) { + StringBuffer json = new StringBuffer(); + json.append(getHeader(200, "SUCCESS", method)); + json.append(JSON.toJSONString(data)); + json.append("}"); + //return JSON.toJSONString(json); + return json.toString(); + } + + /** + * 返回一个正确数据 + * + * @param method + * @param data + * @return + */ + public static String setMsg(String method, List<Map<String, Object>> data) { + StringBuffer json = new StringBuffer(); + json.append(getHeader(200, "SUCCESS", method)); + List<JSONObject> jsonList = new ArrayList<JSONObject>(); + for(Map<String, Object> map : data) { + JSONObject dataJson = new JSONObject(map); + jsonList.add(dataJson); + } + json.append(jsonList); + json.append("}"); + +// return JSON.toJSONString(json); + return json.toString(); + } + + /** + * 返回一个错误数据 + * + * @param method + * @param data + * @return + * @author TaoNingBo + */ + public static String setErrMsg(String method, String data) { + StringBuffer json = new StringBuffer(); + json.append(getHeader(-1, "FAILURE", method)); + json.append("\"" + data + "\""); + json.append("}"); +// return JSON.toJSONString(json); + return json.toString(); + } + + /** + * 生成一个返回JSON的头 + * + * @param code + * @param msg + * @param method + * @return + * @author TaoNingBo + */ + private static String getHeader(int code, String msg, String method) { + StringBuffer header = new StringBuffer(); + header.append("{"); + header.append("\"code\":\"" + code); + header.append("\",\"msg\":\"" + msg); + header.append("\",\"method\":\"" + method); + header.append("\",\"data\":"); + return header.toString(); + } + + /** + * 发送消息给客户端 + * + * @param cacheType + * @param id + * @param method + * @param data + * @author TaoNingBo + */ + public static void sendMsg(String cacheType, Integer id, String method, Map<String, Object> data) { + //NettyServerController.sendMsgToClient(NettyChannelMap.getData(cacheType + id), setMsg(method, data)); + NettyServerController.sendMsgToClient(cacheType,id, setMsg(method, data)); + } + + + public static void resendMsg(String token){ + String msg = NettyServerController.table.get(token); + ChannelHandlerContext ctx = NettyChannelMap.getData(token); + if(null != msg && !"".equals(msg) && ctx != null && ctx.channel().isActive()){ + ByteBuf buffer = Unpooled.copiedBuffer((msg).getBytes()); + ChannelFuture sync; + try { + sync = ctx.writeAndFlush(buffer).sync(); + System.err.println("重发异常推送状态"+sync.isSuccess()+",位置:"+token+",消息内容:"+msg); + if(!sync.isSuccess()){ + resendMsg(token); + System.err.println("重发异常推送不成功,将继续推送"+msg); + } + NettyServerController.table.remove(token); + } catch (Exception e) { + resendMsg(token); + System.err.println("重发推送发生异常,记录:"+msg); + } + } + } + + +} diff --git a/cloud-server-gateway/src/main/java/cn/mb/cloud/gateway/util/echo/NettyServer.java b/cloud-server-gateway/src/main/java/cn/mb/cloud/gateway/util/echo/NettyServer.java new file mode 100644 index 0000000..a9bbb7b --- /dev/null +++ b/cloud-server-gateway/src/main/java/cn/mb/cloud/gateway/util/echo/NettyServer.java @@ -0,0 +1,95 @@ +package cn.mb.cloud.gateway.util.echo; + +import io.netty.bootstrap.ServerBootstrap; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelOption; +import io.netty.channel.ChannelPipeline; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.SocketChannel; +import io.netty.channel.socket.nio.NioServerSocketChannel; +import io.netty.handler.codec.LengthFieldBasedFrameDecoder; +import io.netty.handler.codec.LengthFieldPrepender; +import io.netty.handler.timeout.IdleStateHandler; + +import java.util.Timer; +import java.util.TimerTask; +import java.util.concurrent.TimeUnit; + +/** + * 即时通讯服务启动类 + * + * @date 2016年6月25日 + * @version 1.0 + */ +public class NettyServer { + + + /** + * NettyServer启动方法. + */ + public void bind() { + final Thread thread = new Thread(new NettyRunnable()); + Timer timer = new Timer(); + timer.schedule(new TimerTask() { + @Override + public void run() { + thread.start(); + } + }, 10000); + } + + /** + * 即时通讯服务启动 + * + * @date 2016年6月24日 + * @version 1.0 + */ + public class NettyRunnable implements Runnable { + + /** + * 获取即时通讯启动端口 + */ + private Integer nettyPort = 8888; + @Override + public void run() { + EventLoopGroup bossGroup = new NioEventLoopGroup(); + EventLoopGroup workerGroup = new NioEventLoopGroup(); + try { + ServerBootstrap bootstrap = new ServerBootstrap(); + bootstrap.group(bossGroup, workerGroup); + bootstrap.channel(NioServerSocketChannel.class); + bootstrap.option(ChannelOption.SO_BACKLOG, 1024); + // 通过TCP_NODELAY禁用NAGLE,使消息立即发出去,不用等待到一定的数据量才发出去 + bootstrap.option(ChannelOption.TCP_NODELAY, true); + // 保持长连接状态 + bootstrap.childOption(ChannelOption.SO_KEEPALIVE, true); + bootstrap.childHandler(new ServerInit() { + @Override + protected void initChannel(SocketChannel socketChannel) throws Exception { + ChannelPipeline pipeline = socketChannel.pipeline(); + pipeline.addLast("ping", new IdleStateHandler(120, 60, 5, TimeUnit.SECONDS)); + pipeline.addLast("decoder", new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE, 0, 4, 0, 4)); + pipeline.addLast("encoder", new LengthFieldPrepender(4)); + //pipeline.addLast(new LineBasedFrameDecoder(1048576 * 10)); + //pipeline.addLast(new StringDecoder(Charset.forName("UTF-8"))); + //pipeline.addLast(new StringEncoder(Charset.forName("UTF-8"))); + pipeline.addLast(new DiscardServerHandler()); + } + }); + // 服务器绑定端口监听 + ChannelFuture f = bootstrap.bind(nettyPort).sync(); + if(f.isSuccess()) { + System.out.println("******************************Netty启动成功******************************"); + } + // 监听服务器关闭监听 + f.channel().closeFuture().sync(); + } catch (Exception e) { + e.printStackTrace(); + } finally { + bossGroup.shutdownGracefully(); + workerGroup.shutdownGracefully(); + } + } + } +} diff --git a/cloud-server-gateway/src/main/java/cn/mb/cloud/gateway/util/echo/NettyServerController.java b/cloud-server-gateway/src/main/java/cn/mb/cloud/gateway/util/echo/NettyServerController.java new file mode 100644 index 0000000..8720df9 --- /dev/null +++ b/cloud-server-gateway/src/main/java/cn/mb/cloud/gateway/util/echo/NettyServerController.java @@ -0,0 +1,399 @@ +package cn.mb.cloud.gateway.util.echo; + +import cn.mb.cloud.gateway.util.RedisUtil; +import cn.mb.cloud.gateway.util.SinataUtil; +import cn.mb.cloud.gateway.util.SpringUtil; +import com.alibaba.csp.sentinel.util.StringUtil; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelHandlerContext; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.web.client.RestTemplate; + +import java.util.HashMap; +import java.util.Hashtable; +import java.util.Timer; +import java.util.TimerTask; + + +/** + * Netty业务逻辑层 + * @author sinata + * @createDate 2016年6月3日 + * @version 1.0 + */ +public class NettyServerController { + + public static Hashtable<String, Hashtable<ChannelHandlerContext, String>> map = new Hashtable<String, Hashtable<ChannelHandlerContext,String>>(); + + public static Hashtable<String,String> table; + + private RedisUtil redisUtil = SpringUtil.getObject(RedisUtil.class); + + + private RestTemplate internalRestTemplate = SpringUtil.getObject(RestTemplate.class); + + + + + static{ + if(table == null){ + table = new Hashtable<>(); + } + } + + public static boolean isdebug = false; + public static int i = 0; + + + /** + * 判断客户端要执行什么操作 + * + * @param ctx + * @param msg + * @author TaoNingBo + */ + public void JudgeOperation(ChannelHandlerContext ctx, Object msg) { + try { + // ByteBuf转String + ByteBuf byteBuf = (ByteBuf) msg; + + byte[] req = new byte[byteBuf.readableBytes()]; + byteBuf.readBytes(req); + msg = new String(req, "UTF-8"); + // 验证即时通讯命令是否正确有效 + if(SinataUtil.isEmpty(msg)) { + return; + } + String msgStr = msg.toString(); + if(msgStr.indexOf("{") == -1 || msgStr.indexOf("}") == -1 || msgStr.indexOf("code") == -1 || msgStr.indexOf("msg") == -1 || msgStr.indexOf("data") == -1 || msgStr.indexOf("method") == -1) { + return; + } + if(isdebug) { +// System.out.println("<<<--receive-->>>" + msg); + } + + // 获取socket信息,保存相应的socket + JSONObject jsonMsg = JSONObject.parseObject(msg.toString()); + int code = jsonMsg.getInteger("code"); + String message = jsonMsg.getString("msg"); + String method = jsonMsg.getString("method"); + if(code != 200 || !message.equals("SUCCESS")) { + return; + } + JSONObject jsonCon = JSONObject.parseObject(jsonMsg.get("data").toString()); + + if(null != ctx && ctx.channel().isActive()){ + jsonMsg.put("method", Method.pong); + sendMsgToClient(ctx, jsonMsg.toJSONString()); + } + + //心跳 + if(method.equals(Method.ping)) { + Integer type = jsonCon.getInteger("type"); + String token = jsonCon.getString("token"); + String userId1 = jsonCon.getString("userId"); + String device = jsonCon.getString("device"); + String version = jsonCon.getString("version"); + if(StringUtil.isNotEmpty(userId1)){ + + //判断用户或者司机长连接 + if(type==1){ + //确保账号在单个设备上登录 + if(StringUtil.isNotEmpty(token)){ + String token_ = redisUtil.getValue("USER_APP_"+ userId1);//获取缓存中最新的数据 + if(StringUtil.isNotEmpty(token_) && !token.equals(token_)){//不在同一设备上登录,向其他设备发送数据 + JSONObject msg_ = new JSONObject(); + msg_.put("code", 200); + msg_.put("msg", "SUCCESS"); + msg_.put("method", "OFFLINE"); + msg_.put("data", new Object()); + this.sendMsgToClient(ctx, msg_.toJSONString());//给当前通道发送消息 + TimerTask timerTask = new TimerTask() { + @Override + public void run() { + NettyChannelMap.remove_(ctx); + NettyChannelMap.remove(ctx); + } + }; + Timer timer = new Timer(); + timer.schedule(timerTask, 3000); + timer.cancel(); + }else{ + NettyChannelMap.update_(token.substring(0, 23), ctx); + NettyChannelMap.update("USER" + userId1, ctx); + String s = NettyMsg.setMsg(Method.ok, new HashMap<String, Object>()); + ctx.writeAndFlush(Unpooled.copiedBuffer((s).getBytes())); + } + if(StringUtil.isEmpty(token_)){//确保登录的时候存储token失败的情况 + redisUtil.setStrValue("USER_APP_" + userId1, token); + } + } + + }else{ + //添加司机在线 + HttpHeaders headers = new HttpHeaders(); + // 以表单的方式提交 + headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); + //将请求头部和参数合成一个请求 + MultiValueMap<String, Object> params = new LinkedMultiValueMap<>(); + params.add("driverId", userId1); + params.add("device", (null != device && device.equals("carDevice")) ? "2" : "1"); + params.add("version", version); + HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(params, headers); + String w = internalRestTemplate.postForObject("http://driver-server/base/driverOnline/addDriverOnline",requestEntity , String.class); + JSONObject jsonObject = JSON.parseObject(w, JSONObject.class); + if(jsonObject.getIntValue("code") != 200){ + System.err.println("调用driver-server添加司机在线数据出错了"); + } + + //TODO 存储最后一次上传的时间(用于保证车载端断电后1小时自动下班) + if(StringUtil.isNotEmpty(device) && device.equals("carDevice")){ + redisUtil.setStrValue("DEVICE_" + userId1, String.valueOf(System.currentTimeMillis())); + + String token_ = redisUtil.getValue("DRIVER_" + userId1);//缓存中拿最新数据 + if(StringUtil.isNotEmpty(token_) && !token_.equals(token)){ + //如果是车载端登录,则将其它端都强迫下线 + JSONObject msg_ = new JSONObject(); + msg_.put("code", 200); + msg_.put("msg", "SUCCESS"); + msg_.put("method", "OFFLINE"); + msg_.put("data", new Object()); + this.sendMsgToClient(ctx, msg_.toJSONString());//给当前通道发送消息 + TimerTask timerTask = new TimerTask() { + @Override + public void run() { + NettyChannelMap.remove_(ctx); + NettyChannelMap.remove(ctx); + } + }; + Timer timer = new Timer(); + timer.schedule(timerTask, 3000); + timer.cancel(); + }else{ +// System.err.println("开始存储司机通道" + userId1); + NettyChannelMap.update("DRIVER" + userId1, ctx); + NettyChannelMap.update_(token.substring(0, 23), ctx); + String s = NettyMsg.setMsg(Method.ok, new HashMap<String, Object>()); + ctx.writeAndFlush(Unpooled.copiedBuffer((s).getBytes())); + } + if(StringUtil.isEmpty(token_)){//确保登录的时候存储token失败的情况 + redisUtil.setStrValue("DRIVER_" + userId1, token); + } + } + + + //确保账号在单个设备上登录 + String value = redisUtil.getValue("DEVICE_" + userId1); + if(StringUtil.isNotEmpty(token) && StringUtil.isEmpty(device) && StringUtil.isEmpty(value)){//APP端登录的操作 + String token_ = redisUtil.getValue("DRIVER_" + userId1);//缓存中拿最新数据 + if(StringUtil.isNotEmpty(token_) && !token.equals(token_)){//不在同一设备上登录,向当前设备发送数据 + JSONObject msg_ = new JSONObject(); + msg_.put("code", 200); + msg_.put("msg", "SUCCESS"); + msg_.put("method", "OFFLINE"); + msg_.put("data", new Object()); + this.sendMsgToClient(ctx, msg_.toJSONString());//给当前通道发送消息 + TimerTask timerTask = new TimerTask() { + @Override + public void run() { + NettyChannelMap.remove_(ctx); + NettyChannelMap.remove(ctx); + } + }; + Timer timer = new Timer(); + timer.schedule(timerTask, 3000); + timer.cancel(); + }else{ +// System.err.println("开始存储司机通道" + userId1); + NettyChannelMap.update("DRIVER" + userId1, ctx); + NettyChannelMap.update_(token.substring(0, 23), ctx); + String s = NettyMsg.setMsg(Method.ok, new HashMap<String, Object>()); + ctx.writeAndFlush(Unpooled.copiedBuffer((s).getBytes())); + } + if(StringUtil.isEmpty(token_)){//确保登录的时候存储token失败的情况 + redisUtil.setStrValue("DRIVER_" + userId1, token); + } + } + + + //存储通讯通道 + if(null != ctx && ctx.channel().isActive()){ +// System.err.println("开始存储司机通道" + userId1); + NettyChannelMap.update("DRIVER" + userId1, ctx); + String s = NettyMsg.setMsg(Method.ok, new HashMap<String, Object>()); + ctx.writeAndFlush(Unpooled.copiedBuffer((s).getBytes())); + } + } + } + } + //司机上传位置 + if(method.equals(Method.location)){ + Integer driverId = jsonCon.getInteger("driverId"); + Integer orderId = jsonCon.getInteger("orderId"); + Integer orderType = jsonCon.getInteger("orderType"); + Double lon = jsonCon.getDouble("lon"); + Double lat = jsonCon.getDouble("lat"); + Double computeAzimuth = jsonCon.getDouble("computeAzimuth"); + Double altitude = jsonCon.getDouble("altitude"); + if(SinataUtil.isNotEmpty(driverId)){ + if(null != lon && 0 != lon && null != lat && 0 != lat){ + if(null != orderId && 0 != driverId && null != orderType && 0 != orderType){//开始存入数据库 + HttpHeaders headers = new HttpHeaders(); + // 以表单的方式提交 + headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); + //将请求头部和参数合成一个请求 + MultiValueMap<String, Object> params = new LinkedMultiValueMap<>(); + params.add("orderType", String.valueOf(orderType)); + params.add("orderId", String.valueOf(orderId)); + params.add("driverId", String.valueOf(driverId)); + params.add("lon", String.valueOf(lon)); + params.add("lat", String.valueOf(lat)); + params.add("directionAngle", String.valueOf(computeAzimuth)); + params.add("altitude", String.valueOf(altitude)); + HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(params, headers); + String s = internalRestTemplate.postForObject("http://driver-server/base/savePosition",requestEntity , String.class); + JSONObject jsonObject = JSON.parseObject(s, JSONObject.class); + if(jsonObject.getIntValue("code") != 200){ + System.err.println("调用driver-server存储位置数据出错了"); + } + } + redisUtil.setStrValue("DRIVER" + driverId, lon + "," + lat, 300);//实时位置存入redis中 + }else{ + NettyServerController.sendMsgToClient(ctx, "__error__" + msg.toString()); + } + }else{ + NettyServerController.sendMsgToClient(ctx, "__error__" + msg.toString()); + } + } + + } catch (Exception e) { + if(isdebug) { + NettyServerController.sendMsgToClient(ctx, "__error__" + msg.toString()); + } + e.printStackTrace(); + } + } + + /** + * 向客户端发送消息 + * + * @param ctx + * @param msg + * @author TaoNingBo + */ + public static void sendMsgToClient(ChannelHandlerContext ctx, String msg) { + if (ctx != null && ctx.channel().isActive()) { + ByteBuf buffer = Unpooled.copiedBuffer((msg).getBytes()); + ChannelFuture sync; + try { + sync = ctx.writeAndFlush(buffer).sync(); + if(!sync.isSuccess()){//如果推送失败则继续推送10次 + boolean b = true; + for (int i = 0; i < 10; i++) { + ctx.wait(3000); + sync = ctx.writeAndFlush(buffer).sync(); + if(sync.isSuccess()){ + b = false; + break; + } + System.err.println("推送不成功,将继续推送"+msg); + } + if(b){ + NettyChannelMap.remove(ctx); + } + } + } catch (Exception e) { + System.err.println("推送发生异常,记录:"+msg); + NettyChannelMap.remove(ctx); + } + if(isdebug) { + System.err.println("<<<--send-->>>" + msg) ; + } + }else{ + System.err.println("推送失败,长连接不存在"); + NettyChannelMap.remove(ctx); + } + } + +// **链接断开 将推送消息记录 + public static void sendMsgToClient(String cacheType, Integer id,String msg) { + ChannelHandlerContext ctx = NettyChannelMap.getData(cacheType + id); + if (ctx != null) { + ByteBuf buffer = Unpooled.copiedBuffer((msg).getBytes()); + ChannelFuture sync; + try { + sync = ctx.writeAndFlush(buffer).sync(); +// System.out.println("推送状态"+sync.isSuccess()); + if(!sync.isSuccess()){ + for (int i = 0; i < 10; i++) { + sync = ctx.writeAndFlush(buffer).sync(); + if(!sync.isSuccess()){ + sync = ctx.writeAndFlush(buffer).sync(); + System.err.println("推送不成功,将继续推送"+msg); + if(i == 9){ + table.put(cacheType+id, msg); + + ctx.close(); + System.err.println("推送发生异常,记录:"+msg); + } + }else{ + break; + } + } + } + } catch (Exception e) { + table.put(cacheType+id, msg); + System.err.println("推送发生异常,记录:"+msg); + } + if(isdebug) { +// System.out.println("<<<--send-->>>" + msg); + } + }else{ + table.put(cacheType+id, msg); + System.err.println("链接断开,记录:id="+cacheType+id+",消息:"+msg); + } + } + + /** + * 记录推送不成功消息,并在心跳连接续推 + * @param token + */ + public static void resendMsg(String token){ + String msg = table.get(token); + ChannelHandlerContext ctx = NettyChannelMap.getData(token); + if(SinataUtil.isNotEmpty(msg) && ctx != null && ctx.channel().isActive()){ + ByteBuf buffer = Unpooled.copiedBuffer((msg).getBytes()); + ChannelFuture sync; + try { + sync = ctx.writeAndFlush(buffer).sync(); + System.err.println("重发异常推送状态"+sync.isSuccess()+",位置:"+token+",消息内容:"+msg); + if(!sync.isSuccess()){ + i++; + if(i == 10){ + i =0; + ctx.close(); + return; + } + System.err.println("重发异常推送不成功,将继续推送"+msg); + resendMsg(token); + }else{ + i=0; + } + table.remove(token); + } catch (Exception e) { + resendMsg(token); + System.err.println("重发推送发生异常,记录:"+msg); + } + } + } + + +} diff --git a/cloud-server-gateway/src/main/java/cn/mb/cloud/gateway/util/echo/ServerInit.java b/cloud-server-gateway/src/main/java/cn/mb/cloud/gateway/util/echo/ServerInit.java new file mode 100644 index 0000000..2b131fa --- /dev/null +++ b/cloud-server-gateway/src/main/java/cn/mb/cloud/gateway/util/echo/ServerInit.java @@ -0,0 +1,25 @@ +package cn.mb.cloud.gateway.util.echo; + +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelPipeline; +import io.netty.channel.socket.SocketChannel; +import io.netty.handler.codec.string.StringDecoder; +import io.netty.handler.codec.string.StringEncoder; + +import java.nio.charset.Charset; + +public class ServerInit extends ChannelInitializer<SocketChannel> { + + private DiscardServerHandler discardServerHandler = new DiscardServerHandler(); + + @Override + protected void initChannel(SocketChannel ch) throws Exception { + ChannelPipeline pipeline = ch.pipeline(); + pipeline.addLast(new StringDecoder(Charset.forName("utf-8"))); + pipeline.addLast(new StringEncoder(Charset.forName("utf-8"))); + // 心跳监测机制 +// pipeline.addLast(new IdleStateHandler(5,7,10, TimeUnit.SECONDS)); + pipeline.addLast(discardServerHandler); + } + +} diff --git a/cloud-server-management/mb-cloud-management.iml b/cloud-server-management/mb-cloud-management.iml deleted file mode 100644 index 1daccae..0000000 --- a/cloud-server-management/mb-cloud-management.iml +++ /dev/null @@ -1,8 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<module version="4"> - <component name="FacetManager"> - <facet type="Spring" name="Spring"> - <configuration /> - </facet> - </component> -</module> \ No newline at end of file diff --git a/cloud-server-management/src/main/webapp/WEB-INF/view/system/tGoods/TGoods_detail_two.html b/cloud-server-management/src/main/webapp/WEB-INF/view/system/tGoods/TGoods_detail_two.html index 56fd499..7c62805 100644 --- a/cloud-server-management/src/main/webapp/WEB-INF/view/system/tGoods/TGoods_detail_two.html +++ b/cloud-server-management/src/main/webapp/WEB-INF/view/system/tGoods/TGoods_detail_two.html @@ -65,7 +65,7 @@ <label class="col-sm-3 control-label">所属门店:</label> <div class="col-sm-9"> <select class="form-control" id="storeId" name="storeId"> - <option value="">${item.name}</option> + <option value="">${shopName}</option> </select> </div> </div> @@ -74,7 +74,7 @@ <label class="col-sm-3 control-label">课包类型:</label> <div class="col-sm-9"> <select class="form-control" id="coursePackageTypeId" name="pCode" onchange="TGoodsInfoDlg.packageChange(this)"> - <option value="">${shopName}</option> + <option value="">${typeName}</option> </select> </div> </div> diff --git a/cloud-server-other/src/main/java/com/dsh/other/controller/SiteController.java b/cloud-server-other/src/main/java/com/dsh/other/controller/SiteController.java index d701c3b..9d8a468 100644 --- a/cloud-server-other/src/main/java/com/dsh/other/controller/SiteController.java +++ b/cloud-server-other/src/main/java/com/dsh/other/controller/SiteController.java @@ -1,13 +1,10 @@ package com.dsh.other.controller; -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.dsh.other.entity.Site; import com.dsh.other.entity.SiteBooking; import com.dsh.other.entity.SiteType; -import com.dsh.other.entity.TSite; import com.dsh.other.feignclient.account.CityManagerClient; -import com.dsh.other.feignclient.account.model.CityManager; import com.dsh.other.feignclient.activity.UserCouponClient; import com.dsh.other.feignclient.activity.model.QueryUserCouponByIdAndUserId; import com.dsh.other.feignclient.activity.model.UserCoupon; @@ -16,7 +13,6 @@ import com.dsh.other.feignclient.model.SiteVo; import com.dsh.other.model.*; import com.dsh.other.model.dto.siteDto.TSiteDTO; -import com.dsh.other.model.vo.questionVo.QuestionChangeStateVO; import com.dsh.other.model.vo.siteVo.ExpireSiteSearchVO; import com.dsh.other.model.vo.siteVo.SiteSearchVO; import com.dsh.other.service.ISiteBookingService; @@ -28,8 +24,8 @@ import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiImplicitParams; import io.swagger.annotations.ApiOperation; -import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; @@ -143,7 +139,6 @@ return ResultUtil.runErr(); } } - @@ -324,6 +319,8 @@ if(null == uid){ return ResultUtil.tokenErr(); } + + return siteService.cancelMySite(uid, id); }catch (Exception e){ e.printStackTrace(); diff --git a/cloud-server-other/src/main/java/com/dsh/other/controller/StoreController.java b/cloud-server-other/src/main/java/com/dsh/other/controller/StoreController.java index f1c96eb..9dc6cfa 100644 --- a/cloud-server-other/src/main/java/com/dsh/other/controller/StoreController.java +++ b/cloud-server-other/src/main/java/com/dsh/other/controller/StoreController.java @@ -246,7 +246,7 @@ */ @ResponseBody @PostMapping("/store/queryStoreListByName") - public List<Store> queryStoreListByName(@RequestParam("name") String name){ + public List<Store> queryStoreListByName(@RequestBody String name){ try { List<Store> stores = storeService.list(new QueryWrapper<Store>().eq("state", 1).like("name", name)); return stores; diff --git a/cloud-server-other/src/main/java/com/dsh/other/entity/Site.java b/cloud-server-other/src/main/java/com/dsh/other/entity/Site.java index 877477b..c85c10f 100644 --- a/cloud-server-other/src/main/java/com/dsh/other/entity/Site.java +++ b/cloud-server-other/src/main/java/com/dsh/other/entity/Site.java @@ -108,5 +108,15 @@ @TableField("insertTime") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") private Date insertTime; + @TableField("imgs") + private String imgs; + @TableField("introduce") + private String introduce; + @TableField("是否半场 1是 2否") + private Integer ishalf; + @TableField("场地名称 多个逗号分割") + private String nextName; + @TableField("半场名称 多个逗号分割") + private String halfName; } diff --git a/cloud-server-other/src/main/java/com/dsh/other/entity/SiteBooking.java b/cloud-server-other/src/main/java/com/dsh/other/entity/SiteBooking.java index 3c977b1..91a06f9 100644 --- a/cloud-server-other/src/main/java/com/dsh/other/entity/SiteBooking.java +++ b/cloud-server-other/src/main/java/com/dsh/other/entity/SiteBooking.java @@ -155,4 +155,12 @@ */ @TableField("insertTime") private Date insertTime; + @TableField("nextName") + private String nextName; + @TableField("isHalf") + private Integer isHalf; + @TableField("halfName") + private String halfName; + @TableField("goType") + private Integer goType; } diff --git a/cloud-server-other/src/main/java/com/dsh/other/model/QuerySiteInfoVo.java b/cloud-server-other/src/main/java/com/dsh/other/model/QuerySiteInfoVo.java index 58b3875..0826ae5 100644 --- a/cloud-server-other/src/main/java/com/dsh/other/model/QuerySiteInfoVo.java +++ b/cloud-server-other/src/main/java/com/dsh/other/model/QuerySiteInfoVo.java @@ -4,6 +4,8 @@ import io.swagger.annotations.ApiModelProperty; import lombok.Data; +import java.util.List; + /** * @author zhibing.pu * @date 2023/7/17 11:49 @@ -35,4 +37,15 @@ private Double cashPrice; @ApiModelProperty("玩湃币价格(x/半小时)") private Integer playPaiCoin; + @ApiModelProperty("图片 逗号拼接") + private String imgs; + @ApiModelProperty("多场地名称") + private List<String> nextName; + @ApiModelProperty("半场名称") + private List<String> halfName; + @ApiModelProperty("是否半场 1是 2否") + private Integer ishalf; + @ApiModelProperty("场地说明") + private String introduce; + } diff --git a/cloud-server-other/src/main/java/com/dsh/other/model/ReservationSite.java b/cloud-server-other/src/main/java/com/dsh/other/model/ReservationSite.java index fe90108..2e491b2 100644 --- a/cloud-server-other/src/main/java/com/dsh/other/model/ReservationSite.java +++ b/cloud-server-other/src/main/java/com/dsh/other/model/ReservationSite.java @@ -23,4 +23,10 @@ private String phone; @ApiModelProperty(value = "支付方式(1=微信,2=支付宝,3=玩湃比)", dataType = "int", required = true) private Integer payType; + @ApiModelProperty(value = "场地名称", dataType = "String", required = false) + private String nextName; + @ApiModelProperty(value = "是否半场 1是 2否",required = false) + private Integer isHalf; + @ApiModelProperty(value = "半场名称",required = false) + private String halfName; } diff --git a/cloud-server-other/src/main/java/com/dsh/other/service/impl/SiteServiceImpl.java b/cloud-server-other/src/main/java/com/dsh/other/service/impl/SiteServiceImpl.java index 98459ce..e1de1aa 100644 --- a/cloud-server-other/src/main/java/com/dsh/other/service/impl/SiteServiceImpl.java +++ b/cloud-server-other/src/main/java/com/dsh/other/service/impl/SiteServiceImpl.java @@ -1,5 +1,6 @@ package com.dsh.other.service.impl; +import cn.hutool.core.date.DateUtil; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; @@ -109,7 +110,24 @@ querySiteInfoVo.setStoreLon(store.getLon()); querySiteInfoVo.setStoreLat(store.getLat()); querySiteInfoVo.setStorePhone(store.getPhone()); + querySiteInfoVo.setImgs(site.getImgs()); querySiteInfoVo.setDistance(0D); + querySiteInfoVo.setIntroduce(site.getIntroduce()); + ArrayList<String> nextName = new ArrayList<>(); + ArrayList<String> halfName = new ArrayList<>(); + String nextName1 = site.getNextName(); + String halfName1 = site.getHalfName(); + + String[] split = nextName1.split(","); + for (String s : split) { + nextName.add(s); + } + String[] split1 = halfName1.split(","); + for (String s : split1) { + halfName.add(s); + } + querySiteInfoVo.setHalfName(halfName); + querySiteInfoVo.setNextName(nextName); if(ToolUtil.isNotEmpty(lon) && ToolUtil.isNotEmpty(lat)){ Map<String, Double> distance = GeodesyUtil.getDistance(lon + "," + lat, store.getLon() + "," + store.getLat()); double wgs84 = new BigDecimal(distance.get("WGS84")).divide(new BigDecimal(1000)).setScale(2, RoundingMode.HALF_EVEN).doubleValue(); @@ -269,6 +287,11 @@ siteBooking.setStatus(0); siteBooking.setState(1); siteBooking.setInsertTime(new Date()); + + // 2.0 + siteBooking.setNextName(reservationSite.getNextName()); + siteBooking.setIsHalf(reservationSite.getIsHalf()); + siteBooking.setHalfName(reservationSite.getHalfName()); siteBookingService.save(siteBooking); if(reservationSite.getPayType() == 1){//微信支付 @@ -459,6 +482,12 @@ @Override public ResultUtil cancelMySite(Integer uid, Integer id) throws Exception { SiteBooking siteBooking = siteBookingService.getById(id); + + SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd"); + Date startTime = siteBooking.getStartTime(); + if(format.format(new Date()).equals(format.format(startTime))){ + return ResultUtil.error("预约当天,不能取消"); + } if(siteBooking.getStatus() == 0){ return ResultUtil.error("请先进行支付"); } -- Gitblit v1.7.1