master:管理员推广营销功能完善;

pull/1121/head
liujiang 2025-05-13 16:08:13 +08:00
parent 2502dde831
commit cdc6f2dbeb
40 changed files with 1228 additions and 94 deletions

View File

@ -0,0 +1,99 @@
package com.ruoyi.web.controller.xkt;
import cn.hutool.core.bean.BeanUtil;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.XktBaseController;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.page.Page;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.web.controller.xkt.vo.adminAdvertRound.AdminAdRoundAuditVO;
import com.ruoyi.web.controller.xkt.vo.adminAdvertRound.AdminAdRoundPageVO;
import com.ruoyi.web.controller.xkt.vo.adminAdvertRound.AdminAdRoundSysInterceptVO;
import com.ruoyi.web.controller.xkt.vo.adminAdvertRound.AdminAdRoundUnsubscribeVO;
import com.ruoyi.web.controller.xkt.vo.advertRound.AdRoundUploadPicVO;
import com.ruoyi.xkt.dto.adminAdvertRound.*;
import com.ruoyi.xkt.dto.advertRound.AdRoundUploadPicDTO;
import com.ruoyi.xkt.service.IAdminAdvertRoundService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
/**
* 广Controller
*
* @author ruoyi
* @date 2025-03-26
*/
@Api(tags = "管理员管理推广营销列表")
@RestController
@RequiredArgsConstructor
@RequestMapping("/rest/v1/ad-rounds/admin")
public class AdminAdvertRoundController extends XktBaseController {
final IAdminAdvertRoundService adminAdvertRoundService;
/**
* 广
*/
@ApiOperation(value = "管理员获取推广营销列表", httpMethod = "POST", response = R.class)
@PostMapping("/page")
public R<Page<AdminAdRoundPageResDTO>> page(@Validated @RequestBody AdminAdRoundPageVO pageVO) {
return R.ok(adminAdvertRoundService.page(BeanUtil.toBean(pageVO, AdminAdRoundPageDTO.class)));
}
/**
* 广
*/
@ApiOperation(value = "管理员审核档口推广图", httpMethod = "PUT", response = R.class)
@Log(title = "管理员审核档口推广图", businessType = BusinessType.UPDATE)
@PutMapping("/audit-pic")
public R<Integer> auditPic(@Validated @RequestBody AdminAdRoundAuditVO auditVO) {
return R.ok(adminAdvertRoundService.auditPic(BeanUtil.toBean(auditVO, AdminAdRoundAuditDTO.class)));
}
/**
* 退
*/
@ApiOperation(value = "管理员退订", httpMethod = "PUT", response = R.class)
@Log(title = "管理员退订", businessType = BusinessType.UPDATE)
@PutMapping("/unsubscribe")
public R<Integer> unsubscribe(@Validated @RequestBody AdminAdRoundUnsubscribeVO unsubscribeVO) {
return R.ok(adminAdvertRoundService.unsubscribe(BeanUtil.toBean(unsubscribeVO, AdminAdRoundUnsubscribeDTO.class)));
}
/**
* 广
*/
@ApiOperation(value = "档口上传推广图", httpMethod = "PUT", response = R.class)
@Log(title = "管理员退订", businessType = BusinessType.UPDATE)
@PutMapping("/upload/pic")
public R<Integer> uploadAdvertPic(@Valid @RequestBody AdRoundUploadPicVO uploadPicVO) {
return R.ok(adminAdvertRoundService.uploadAdvertPic(BeanUtil.toBean(uploadPicVO, AdRoundUploadPicDTO.class)));
}
/**
* 广
*/
@ApiOperation(value = "系统拦截广告位", httpMethod = "PUT", response = R.class)
@Log(title = "系统拦截广告位", businessType = BusinessType.UPDATE)
@PutMapping("/intercept")
public R<Integer> sysIntercept(@Valid @RequestBody AdminAdRoundSysInterceptVO interceptVO) {
return R.ok(adminAdvertRoundService.sysIntercept(BeanUtil.toBean(interceptVO, AdminAdRoundSysInterceptDTO.class)));
}
/**
* 广
*/
@ApiOperation(value = "取消拦截广告位", httpMethod = "PUT", response = R.class)
@Log(title = "取消拦截广告位", businessType = BusinessType.UPDATE)
@PutMapping("/cancel-intercept/{advertRoundId}")
public R<Integer> cancelIntercept(@PathVariable Long advertRoundId) {
return R.ok(adminAdvertRoundService.cancelIntercept(advertRoundId));
}
}

View File

@ -7,10 +7,7 @@ import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.page.Page;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.web.controller.xkt.vo.advertRound.*;
import com.ruoyi.xkt.dto.advertRound.AdRoundLatestDTO;
import com.ruoyi.xkt.dto.advertRound.AdRoundStoreCreateDTO;
import com.ruoyi.xkt.dto.advertRound.AdvertRoundStorePageDTO;
import com.ruoyi.xkt.dto.advertRound.AdvertRoundStorePageResDTO;
import com.ruoyi.xkt.dto.advertRound.*;
import com.ruoyi.xkt.service.IAdvertRoundService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
@ -67,7 +64,7 @@ public class AdvertRoundController extends XktBaseController {
* 广广
*/
@ApiOperation(value = "位置枚举类型的推广位,获取推广商品", httpMethod = "GET", response = R.class)
@GetMapping(value = "/{advertRoundId}")
@GetMapping(value = "/position/{advertRoundId}")
public R<List<AdRoundSetProdResVO>> getSetProdInfo(@PathVariable("advertRoundId") Long advertRoundId) {
return R.ok(BeanUtil.copyToList(advertRoundService.getSetProdInfo(advertRoundId), AdRoundSetProdResVO.class));
}
@ -77,7 +74,7 @@ public class AdvertRoundController extends XktBaseController {
*/
@ApiOperation(value = "获取档口已购推广列表", httpMethod = "POST", response = R.class)
@PostMapping("/page")
public R<Page<AdvertRoundStorePageResDTO>> page(@Valid @RequestBody AdvertRoundStorePageVO pageVO) {
public R<Page<AdvertRoundStorePageResDTO>> page(@Validated @RequestBody AdvertRoundStorePageVO pageVO) {
return R.ok(advertRoundService.page(BeanUtil.toBean(pageVO, AdvertRoundStorePageDTO.class)));
}
@ -109,4 +106,14 @@ public class AdvertRoundController extends XktBaseController {
return R.ok(BeanUtil.copyToList(advertRoundService.getMostPopulars(), AdRoundPopularResVO.class));
}
/**
* 广
*/
@ApiOperation(value = "档口上传推广图", httpMethod = "PUT", response = R.class)
@PutMapping("/upload/pic")
public R<Integer> uploadAdvertPic(@Valid @RequestBody AdRoundUploadPicVO uploadPicVO) {
return R.ok(advertRoundService.uploadAdvertPic(BeanUtil.toBean(uploadPicVO, AdRoundUploadPicDTO.class)));
}
}

View File

@ -12,7 +12,6 @@ import com.ruoyi.xkt.service.IShoppingCartService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
@ -88,11 +87,11 @@ public class ShoppingCartController extends XktBaseController {
*
*/
// // @PreAuthorize("@ss.hasPermi('system:sale:remove')")
@ApiOperation(value = "用户进货车列表点击编辑", httpMethod = "DELETE", response = R.class)
@ApiOperation(value = "用户删除进货车商品", httpMethod = "DELETE", response = R.class)
@Log(title = "用户删除进货车商品", businessType = BusinessType.DELETE)
@DeleteMapping("/{shoppingCartId}")
public R<Integer> remove(@PathVariable Long shoppingCartId) {
return R.ok(shopCartService.delete(shoppingCartId));
@DeleteMapping
public R<Integer> remove(@Validated @RequestBody ShopCartDeleteVO deleteVO) {
return R.ok(shopCartService.delete(BeanUtil.toBean(deleteVO, ShopCartDeleteDTO.class)));
}

View File

@ -118,35 +118,14 @@ public class StoreController extends XktBaseController {
}
final OSSClientWrapper ossClient;
@GetMapping("/getKey")
public R getKey() {
return R.ok(ossClient.createStsCredentials());
/**
* 广
*/
@ApiOperation(value = "管理员审核推广图获取档口联系信息", httpMethod = "GET", response = R.class)
@GetMapping(value = "/advert/{storeId}")
public R<StoreAdvertResVO> getAdvertStoreInfo(@PathVariable("storeId") Long storeId) {
return R.ok(BeanUtil.toBean(storeService.getAdvertStoreInfo(storeId), StoreAdvertResVO.class));
}
@PostMapping("/upload")
public void test(@RequestParam("file") MultipartFile file) throws Exception {
final String uuid = IdUtil.randomUUID();
ossClient.upload(uuid + ".png", file.getInputStream());
}
@GetMapping("/getUrl/{key}/{expireTime}")
public R getUrl(@PathVariable("key") String key, @PathVariable("expireTime") Long expireTime) throws Exception {
return R.ok(ossClient.generateUrl(key, expireTime));
}
@GetMapping("/download/{key}")
public void download(@PathVariable("key") String key) throws Exception {
String name = "C:\\Users\\56980\\Desktop\\test.png";
ossClient.download(key, name);
}
}

View File

@ -0,0 +1,26 @@
package com.ruoyi.web.controller.xkt.vo.adminAdvertRound;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
/**
* @author liujiang
* @version v1.0
* @date 2025/3/27 15:12
*/
@ApiModel("管理员审核档口推广图")
@Data
public class AdminAdRoundAuditVO {
@NotNull(message = "advertRoundId不能为空")
@ApiModelProperty(value = "推广轮次ID")
private Long advertRoundId;
@ApiModelProperty(value = "图片审核状态 1 待审核 2 审核通过 3 审核驳回")
private Integer picAuditStatus;
@ApiModelProperty(value = "驳回原因")
private String rejectReason;
}

View File

@ -0,0 +1,39 @@
package com.ruoyi.web.controller.xkt.vo.adminAdvertRound;
import com.ruoyi.web.controller.xkt.vo.BasePageVO;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import javax.validation.constraints.NotNull;
/**
* @author liujiang
* @version v1.0
* @date 2025/3/27 15:12
*/
@EqualsAndHashCode(callSuper = true)
@ApiModel("管理员推广营销列表查询入参")
@Data
public class AdminAdRoundPageVO extends BasePageVO {
@NotNull(message = "投放状态不能为空!")
@ApiModelProperty(value = "投放状态 1投放中 2待投放")
private Integer launchStatus;
@ApiModelProperty(value = "平台ID")
private Long platformId;
@ApiModelProperty(value = "推广类型")
private Integer typeId;
@ApiModelProperty(value = "图片审核状态 1 待审核 2 审核通过 3 审核驳回")
private Integer picAuditStatus;
@ApiModelProperty(value = "图片设计 1自主设计、2平台设计")
private Integer picDesignType;
@ApiModelProperty(value = "系统拦截 0 未拦截 1已拦截")
private Integer sysIntercept;
@ApiModelProperty(value = "播放轮次 2第二轮 3第三轮 4第四轮 5第五轮")
private Integer roundId;
@ApiModelProperty(value = "档口ID")
private Long storeId;
}

View File

@ -0,0 +1,47 @@
package com.ruoyi.web.controller.xkt.vo.adminAdvertRound;
import com.fasterxml.jackson.annotation.JsonInclude;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.experimental.Accessors;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.math.BigDecimal;
import java.util.List;
/**
* @author liujiang
* @version v1.0
* @date 2025/3/27 15:12
*/
@ApiModel("系统拦截档口推广位")
@Data
@Accessors(chain = true)
@JsonInclude(JsonInclude.Include.NON_NULL)
public class AdminAdRoundSysInterceptVO {
@NotNull(message = "推广轮次ID不能为空")
@ApiModelProperty(value = "推广轮次ID")
private Long advertRoundId;
@NotBlank(message = "档口ID不能为空")
@ApiModelProperty(value = "档口ID")
private Long storeId;
@ApiModelProperty(value = "管理员上传推广图")
private AARSIFileVO file;
@ApiModelProperty(value = "档口商品ID集合")
private List<Long> storeProdIdList;
@Data
@ApiModel(value = "推广图对象")
public static class AARSIFileVO {
@ApiModelProperty(value = "文件名称")
private String fileName;
@ApiModelProperty(value = "文件路径")
private String fileUrl;
@ApiModelProperty(value = "文件大小")
private BigDecimal fileSize;
}
}

View File

@ -0,0 +1,28 @@
package com.ruoyi.web.controller.xkt.vo.adminAdvertRound;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
import java.math.BigDecimal;
/**
* @author liujiang
* @version v1.0
* @date 2025/3/27 15:12
*/
@ApiModel("管理员退订")
@Data
public class AdminAdRoundUnsubscribeVO {
@NotNull(message = "advertRoundId不能为空")
@ApiModelProperty(value = "推广轮次ID")
private Long advertRoundId;
@NotNull(message = "storeId不能为空")
@ApiModelProperty(value = "档口ID")
private Long storeId;
@ApiModelProperty(value = "扣除金额")
private BigDecimal deductionFee;
}

View File

@ -20,8 +20,8 @@ public class AdRoundLatestResVO {
@ApiModelProperty(value = "档口ID")
private Long storeId;
@ApiModelProperty(value = "档口负责人名称")
private String storeOwnerName;
@ApiModelProperty(value = "档口负责人联系电话")
private String contactPhone;
@ApiModelProperty(value = "最高价格")
private BigDecimal payPrice;
@ApiModelProperty(value = "档口设置的商品")

View File

@ -0,0 +1,37 @@
package com.ruoyi.web.controller.xkt.vo.advertRound;
import com.fasterxml.jackson.annotation.JsonInclude;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.experimental.Accessors;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.math.BigDecimal;
/**
* @author liujiang
* @version v1.0
* @date 2025/3/27 15:12
*/
@ApiModel("档口上传推广图")
@Data
@Accessors(chain = true)
@JsonInclude(JsonInclude.Include.NON_NULL)
public class AdRoundUploadPicVO {
@NotNull(message = "推广轮次ID不能为空!")
@ApiModelProperty(value = "推广轮次ID")
private Long advertRoundId;
@NotBlank(message = "文件名称不能为空!")
@ApiModelProperty(value = "文件名称")
private String fileName;
@NotBlank(message = "文件路径不能为空!")
@ApiModelProperty(value = "文件路径")
private String fileUrl;
@NotNull(message = "文件大小不能为空!")
@ApiModelProperty(value = "文件大小")
private BigDecimal fileSize;
}

View File

@ -8,6 +8,7 @@ import lombok.EqualsAndHashCode;
import javax.validation.constraints.NotNull;
import java.util.Date;
import java.util.List;
/**
* @author liujiang
@ -19,15 +20,18 @@ import java.util.Date;
@Data
public class AdvertRoundStorePageVO extends BasePageVO {
@NotNull(message = "storeId不能为空")
@NotNull(message = "档口ID不能为空!")
@ApiModelProperty(value = "档口ID")
private Long storeId;
@ApiModelProperty(value = "平台ID")
private Long platformId;
@ApiModelProperty(value = "推广类型")
private Integer typeId;
@ApiModelProperty(value = "投放状态")
private Integer launchStatus;
@NotNull(message = "竞价状态不能为空!")
@ApiModelProperty(value = "竞价状态 只查看 已出价 或 竞价成功的状态")
private Integer biddingStatus;
private List<Integer> biddingStatusList;
@ApiModelProperty(value = "图片是否设置 1 未设置 2已设置")
private Integer picSetType;
@ApiModelProperty(value = "图片设计 1自主设计、2平台设计")

View File

@ -0,0 +1,29 @@
package com.ruoyi.web.controller.xkt.vo.store;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* @author liujiang
* @version v1.0
* @date 2025/3/27 15:12
*/
@ApiModel("档口App基本信息")
@Data
public class StoreAdvertResVO {
@ApiModelProperty(value = "档口ID")
private Long storeId;
@ApiModelProperty(value = "档口名称")
private String storeName;
@ApiModelProperty(value = "联系电话")
private String contactPhone;
@ApiModelProperty(value = "备选联系电话")
private String contactBackPhone;
@ApiModelProperty(name = "微信账号")
private String wechatAccount;
@ApiModelProperty(name = "QQ账号")
private String qqAccount;
}

View File

@ -0,0 +1,25 @@
package com.ruoyi.web.controller.xkt.vo.userShoppingCart;
import com.fasterxml.jackson.annotation.JsonInclude;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
import java.util.List;
/**
* @author liujiang
* @version v1.0
* @date 2025/3/27 15:12
*/
@ApiModel("进货车删除")
@Data
@JsonInclude(JsonInclude.Include.NON_NULL)
public class ShopCartDeleteVO {
@NotNull(message = "进货车ID列表不可为空!")
@ApiModelProperty(value = "进货车ID列表")
private List<Long> shoppingCartIdList;
}

View File

@ -333,8 +333,9 @@ public class XktTask {
final String position = String.valueOf((char) ('A' + j));
// 当前播放轮次id
final int roundId = i + 1;
updateList.add(new AdvertRound().setAdvertId(advert.getId()).setTypeId(advert.getTypeId()).setRoundId(roundId).setLaunchStatus(launchStatus).setShowType(advert.getShowType())
.setStartTime(java.sql.Date.valueOf(now)).setEndTime(java.sql.Date.valueOf(endDate)).setPosition(position).setStartPrice(advert.getStartPrice()).setSysIntercept(0)
updateList.add(new AdvertRound().setAdvertId(advert.getId()).setTypeId(advert.getTypeId()).setRoundId(roundId).setLaunchStatus(launchStatus)
.setStartTime(java.sql.Date.valueOf(now)).setEndTime(java.sql.Date.valueOf(endDate)).setPosition(position).setStartPrice(advert.getStartPrice())
.setSysIntercept(AdSysInterceptType.UN_INTERCEPT.getValue()).setShowType(advert.getShowType())
.setSymbol(Objects.equals(advert.getShowType(), AdShowType.POSITION_ENUM.getValue())
// 如果是位置枚举的推广位则需要精确到某一个position的推广位反之若是时间范围则直接精确到播放轮次即可
? advert.getBasicSymbol() + roundId + position : advert.getBasicSymbol() + roundId));
@ -380,8 +381,9 @@ public class XktTask {
// 依次按照26个字母顺序 如果i == 0 则A i == 1 则B i==2则C
final String position = String.valueOf((char) ('A' + j));
// 生成最新的下一轮推广位
updateList.add(new AdvertRound().setAdvertId(advert.getId()).setTypeId(advert.getTypeId()).setRoundId(maxRoundId).setShowType(advert.getShowType())
.setLaunchStatus(AdLaunchStatus.UN_LAUNCH.getValue()).setPosition(position).setStartPrice(advert.getStartPrice()).setSysIntercept(0)
updateList.add(new AdvertRound().setAdvertId(advert.getId()).setTypeId(advert.getTypeId()).setRoundId(maxRoundId)
.setLaunchStatus(AdLaunchStatus.UN_LAUNCH.getValue()).setPosition(position).setStartPrice(advert.getStartPrice())
.setSysIntercept(AdSysInterceptType.UN_INTERCEPT.getValue()).setShowType(advert.getShowType())
// java.sql.Date 直接转化成yyyy-MM-dd格式
.setStartTime(java.sql.Date.valueOf(startDate)).setEndTime(java.sql.Date.valueOf(endDate))
.setSymbol(Objects.equals(advert.getShowType(), AdShowType.POSITION_ENUM.getValue())

View File

@ -115,5 +115,9 @@ public class AdvertRound extends XktBaseEntity {
* 0 1
*/
private Integer sysIntercept;
/**
*
*/
private String rejectReason;
}

View File

@ -111,5 +111,9 @@ public class AdvertRoundRecord extends XktBaseEntity {
*
*/
private Integer sysIntercept;
/**
*
*/
private String rejectReason;
}

View File

@ -6,8 +6,6 @@ import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.math.BigDecimal;
/**
* 广 advert_store_file
*
@ -18,6 +16,7 @@ import java.math.BigDecimal;
@Data
@Accessors(chain = true)
public class AdvertStoreFile extends XktBaseEntity {
private static final long serialVersionUID = 1L;
/**
@ -25,6 +24,10 @@ public class AdvertStoreFile extends XktBaseEntity {
*/
@TableId
private Long id;
/**
* 广ID
*/
private Long advertRoundId;
/**
* ID
*/

View File

@ -0,0 +1,25 @@
package com.ruoyi.xkt.dto.adminAdvertRound;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
/**
* @author liujiang
* @version v1.0
* @date 2025/3/27 15:12
*/
@ApiModel("管理员审核档口推广图")
@Data
public class AdminAdRoundAuditDTO {
@ApiModelProperty(value = "推广轮次ID")
private Long advertRoundId;
@ApiModelProperty(value = "图片审核状态 1 待审核 2 审核通过 3 审核驳回")
private Integer picAuditStatus;
@ApiModelProperty(value = "驳回原因")
private String rejectReason;
}

View File

@ -0,0 +1,39 @@
package com.ruoyi.xkt.dto.adminAdvertRound;
import com.ruoyi.xkt.dto.BasePageDTO;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import javax.validation.constraints.NotNull;
import java.util.Date;
/**
* @author liujiang
* @version v1.0
* @date 2025/3/27 15:12
*/
@EqualsAndHashCode(callSuper = true)
@ApiModel("管理员推广营销列表查询入参")
@Data
public class AdminAdRoundPageDTO extends BasePageDTO {
@ApiModelProperty(value = "投放状态 1投放中 2待投放")
private Integer launchStatus;
@ApiModelProperty(value = "平台ID")
private Long platformId;
@ApiModelProperty(value = "推广类型")
private Integer typeId;
@ApiModelProperty(value = "图片审核状态 1 待审核 2 审核通过 3 审核驳回")
private Integer picAuditStatus;
@ApiModelProperty(value = "图片设计 1自主设计、2平台设计")
private Integer picDesignType;
@ApiModelProperty(value = "系统拦截 0 未拦截 1已拦截")
private Integer sysIntercept;
@ApiModelProperty(value = "播放轮次 2第二轮 3第三轮 4第四轮 5第五轮")
private Integer roundId;
@ApiModelProperty(value = "档口ID")
private Long storeId;
}

View File

@ -0,0 +1,61 @@
package com.ruoyi.xkt.dto.adminAdvertRound;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.experimental.Accessors;
/**
* @author liujiang
* @version v1.0
* @date 2025/3/27 15:12
*/
@ApiModel("档口已订购推广返回列表")
@Data
@Accessors(chain = true)
public class AdminAdRoundPageResDTO {
@ApiModelProperty(value = "推广轮次ID")
private Long advertRoundId;
@ApiModelProperty(value = "档口名称")
private String storeName;
@ApiModelProperty(value = "投放平台")
private Integer platformId;
@ApiModelProperty(value = "投放平台")
private String platformName;
@ApiModelProperty(value = "投放类型")
private Integer typeId;
@ApiModelProperty(value = "投放类型")
private String typeName;
@ApiModelProperty(value = "投放位置")
private String position;
@ApiModelProperty(value = "投放开始时间")
private String startTime;
@ApiModelProperty(value = "投放结束时间")
private String endTime;
@ApiModelProperty(value = "出价")
private String payPrice;
@ApiModelProperty(value = "投放状态")
private Integer launchStatus;
@ApiModelProperty(value = "投放状态")
private String launchStatusName;
@ApiModelProperty(value = "竞价状态")
private Integer biddingStatus;
@ApiModelProperty(value = "竞价状态")
private String biddingStatusName;
@ApiModelProperty(value = "图片设计类型")
private Integer picDesignType;
@ApiModelProperty(value = "竞价状态")
private String picDesignTypeName;
@ApiModelProperty(value = "图片是否设置")
private Integer picSetType;
@ApiModelProperty(value = "图片是否设置")
private String picSetTypeName;
@ApiModelProperty(value = "图片审核状态")
private Integer picAuditStatus;
@ApiModelProperty(value = "图片审核状态")
private String picAuditStatusName;
@ApiModelProperty(value = "系统拦截 0 未拦截 1拦截")
private Integer sysIntercept;
}

View File

@ -0,0 +1,43 @@
package com.ruoyi.xkt.dto.adminAdvertRound;
import com.fasterxml.jackson.annotation.JsonInclude;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.experimental.Accessors;
import java.math.BigDecimal;
import java.util.List;
/**
* @author liujiang
* @version v1.0
* @date 2025/3/27 15:12
*/
@ApiModel("系统拦截档口推广位")
@Data
@Accessors(chain = true)
@JsonInclude(JsonInclude.Include.NON_NULL)
public class AdminAdRoundSysInterceptDTO {
@ApiModelProperty(value = "推广轮次ID")
private Long advertRoundId;
@ApiModelProperty(value = "档口ID")
private Long storeId;
@ApiModelProperty(value = "管理员上传推广图")
private AARSIFileVO file;
@ApiModelProperty(value = "档口商品ID集合")
private List<Long> storeProdIdList;
@Data
@ApiModel(value = "推广图对象")
public static class AARSIFileVO {
@ApiModelProperty(value = "文件名称")
private String fileName;
@ApiModelProperty(value = "文件路径")
private String fileUrl;
@ApiModelProperty(value = "文件大小")
private BigDecimal fileSize;
}
}

View File

@ -0,0 +1,26 @@
package com.ruoyi.xkt.dto.adminAdvertRound;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
import java.math.BigDecimal;
/**
* @author liujiang
* @version v1.0
* @date 2025/3/27 15:12
*/
@ApiModel("管理员退订")
@Data
public class AdminAdRoundUnsubscribeDTO {
@ApiModelProperty(value = "推广轮次ID")
private Long advertRoundId;
@ApiModelProperty(value = "档口ID")
private Long storeId;
@ApiModelProperty(value = "扣除金额")
private BigDecimal deductionFee;
}

View File

@ -20,8 +20,8 @@ public class AdRoundLatestResDTO {
@ApiModelProperty(value = "档口ID")
private Long storeId;
@ApiModelProperty(value = "档口负责人名称")
private String storeOwnerName;
@ApiModelProperty(value = "档口负责人联系电话")
private String contactPhone;
@ApiModelProperty(value = "最高价格")
private BigDecimal payPrice;
@ApiModelProperty(value = "档口设置的商品")

View File

@ -0,0 +1,33 @@
package com.ruoyi.xkt.dto.advertRound;
import com.fasterxml.jackson.annotation.JsonInclude;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.experimental.Accessors;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.math.BigDecimal;
/**
* @author liujiang
* @version v1.0
* @date 2025/3/27 15:12
*/
@ApiModel("档口上传推广图")
@Data
@Accessors(chain = true)
@JsonInclude(JsonInclude.Include.NON_NULL)
public class AdRoundUploadPicDTO {
@ApiModelProperty(value = "推广轮次ID")
private Long advertRoundId;
@ApiModelProperty(value = "文件名称")
private String fileName;
@ApiModelProperty(value = "文件路径")
private String fileUrl;
@ApiModelProperty(value = "文件大小")
private BigDecimal fileSize;
}

View File

@ -7,6 +7,7 @@ import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.Date;
import java.util.List;
/**
* @author liujiang
@ -20,12 +21,14 @@ public class AdvertRoundStorePageDTO extends BasePageDTO {
@ApiModelProperty(value = "档口ID")
private Long storeId;
@ApiModelProperty(value = "平台ID")
private Long platformId;
@ApiModelProperty(value = "推广类型")
private Integer typeId;
@ApiModelProperty(value = "投放状态")
private Integer launchStatus;
@ApiModelProperty(value = "竞价状态 只查看 已出价 或 竞价成功的状态")
private Integer biddingStatus;
private List<Integer> biddingStatusList;
@ApiModelProperty(value = "图片是否设置 1 未设置 2已设置")
private Integer picSetType;
@ApiModelProperty(value = "图片设计 1自主设计、2平台设计")

View File

@ -15,6 +15,10 @@ import lombok.experimental.Accessors;
@Accessors(chain = true)
public class AdvertRoundStorePageResDTO {
@ApiModelProperty(value = "推广轮次ID")
private Long advertRoundId;
@ApiModelProperty(value = "档口名称")
private String storeName;
@ApiModelProperty(value = "投放平台")
private Integer platformId;
@ApiModelProperty(value = "投放平台")

View File

@ -0,0 +1,29 @@
package com.ruoyi.xkt.dto.store;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* @author liujiang
* @version v1.0
* @date 2025/3/27 15:12
*/
@ApiModel("档口App基本信息")
@Data
public class StoreAdvertResDTO {
@ApiModelProperty(value = "档口ID")
private Long storeId;
@ApiModelProperty(value = "档口名称")
private String storeName;
@ApiModelProperty(value = "联系电话")
private String contactPhone;
@ApiModelProperty(value = "备选联系电话")
private String contactBackPhone;
@ApiModelProperty(name = "微信账号")
private String wechatAccount;
@ApiModelProperty(name = "QQ账号")
private String qqAccount;
}

View File

@ -0,0 +1,24 @@
package com.ruoyi.xkt.dto.userShoppingCart;
import com.fasterxml.jackson.annotation.JsonInclude;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
import java.util.List;
/**
* @author liujiang
* @version v1.0
* @date 2025/3/27 15:12
*/
@ApiModel("进货车删除")
@Data
@JsonInclude(JsonInclude.Include.NON_NULL)
public class ShopCartDeleteDTO {
@ApiModelProperty(value = "进货车ID列表")
private List<Long> shoppingCartIdList;
}

View File

@ -0,0 +1,37 @@
package com.ruoyi.xkt.enums;
import com.ruoyi.common.constant.HttpStatus;
import com.ruoyi.common.exception.ServiceException;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 广
*
* @author liujiang
* @date 2025-04-02 23:42
*/
@Getter
@AllArgsConstructor
public enum AdSysInterceptType {
// 未拦截
UN_INTERCEPT(0, "未拦截"),
// 已拦截
INTERCEPT(1, "已拦截"),
;
private final Integer value;
private final String label;
public static AdSysInterceptType of(Integer value) {
for (AdSysInterceptType e : AdSysInterceptType.values()) {
if (e.getValue().equals(value)) {
return e;
}
}
throw new ServiceException("推广营销系统拦截类型不存在!", HttpStatus.ERROR);
}
}

View File

@ -2,6 +2,8 @@ package com.ruoyi.xkt.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.ruoyi.xkt.domain.AdvertRound;
import com.ruoyi.xkt.dto.adminAdvertRound.AdminAdRoundPageDTO;
import com.ruoyi.xkt.dto.adminAdvertRound.AdminAdRoundPageResDTO;
import com.ruoyi.xkt.dto.advertRound.AdvertRoundStorePageDTO;
import com.ruoyi.xkt.dto.advertRound.AdvertRoundStorePageResDTO;
import org.apache.ibatis.annotations.Param;
@ -37,6 +39,14 @@ public interface AdvertRoundMapper extends BaseMapper<AdvertRound> {
*/
List<AdvertRoundStorePageResDTO> selectStoreAdvertPage(AdvertRoundStorePageDTO pageDTO);
/**
* 广
*
* @param pageDTO
* @return List<AdvertRoundStorePageResDTO>
*/
List<AdminAdRoundPageResDTO> selectAdminAdvertPage(AdminAdRoundPageDTO pageDTO);
/**
* null
*
@ -60,12 +70,5 @@ public interface AdvertRoundMapper extends BaseMapper<AdvertRound> {
*/
BigDecimal selectMaxPayPrice(@Param("advertId") Long advertId, @Param("roundId") Integer roundId);
/**
*
* @param storeId ID
* @return
*/
String getStoreOwnerName(Long storeId);
}

View File

@ -0,0 +1,63 @@
package com.ruoyi.xkt.service;
import com.ruoyi.common.core.page.Page;
import com.ruoyi.xkt.dto.adminAdvertRound.*;
import com.ruoyi.xkt.dto.advertRound.AdRoundUploadPicDTO;
/**
* 广Service
*
* @author ruoyi
* @date 2025-03-26
*/
public interface IAdminAdvertRoundService {
/**
* 广
*
* @param pageDTO
* @return Page<AdminAdRoundPageResDTO>
*/
Page<AdminAdRoundPageResDTO> page(AdminAdRoundPageDTO pageDTO);
/**
* 广
*
* @param auditDTO 广
* @return Integer
*/
Integer auditPic(AdminAdRoundAuditDTO auditDTO);
/**
* 退
*
* @param unsubscribeDTO 退
* @return
*/
Integer unsubscribe(AdminAdRoundUnsubscribeDTO unsubscribeDTO);
/**
*
*
* @param picDTO 广
* @return Integer
*/
Integer uploadAdvertPic(AdRoundUploadPicDTO picDTO);
/**
* 广
*
* @param interceptDTO 广
* @return Integer
*/
Integer sysIntercept(AdminAdRoundSysInterceptDTO interceptDTO);
/**
* 广
*
* @param advertRoundId 广ID
* @return Integer
*/
Integer cancelIntercept(Long advertRoundId);
}

View File

@ -102,4 +102,9 @@ public interface IAdvertRoundService {
*/
AdRoundLatestResDTO getLatestInfo(AdRoundLatestDTO latestDTO);
/**
* @param picDTO 广
* @return Integer
*/
Integer uploadAdvertPic(AdRoundUploadPicDTO picDTO);
}

View File

@ -48,10 +48,10 @@ public interface IShoppingCartService {
/**
*
*
* @param shoppingCartId ID
* @param deleteDTO ID
* @return
*/
Integer delete(Long shoppingCartId);
Integer delete(ShopCartDeleteDTO deleteDTO);
/**
* storeProdid

View File

@ -74,4 +74,13 @@ public interface IStoreService {
* @return StoreAppResDTO
*/
StoreAppResDTO getAppInfo(Long storeId);
/**
* 广
*
* @param storeId ID
* @return StoreAdvertResDTO
*/
StoreAdvertResDTO getAdvertStoreInfo(Long storeId);
}

View File

@ -0,0 +1,270 @@
package com.ruoyi.xkt.service.impl;
import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.constant.HttpStatus;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.core.page.Page;
import com.ruoyi.common.enums.AdType;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.xkt.domain.AdvertRound;
import com.ruoyi.xkt.domain.AdvertStoreFile;
import com.ruoyi.xkt.domain.SysFile;
import com.ruoyi.xkt.dto.adminAdvertRound.*;
import com.ruoyi.xkt.dto.advertRound.AdRoundUploadPicDTO;
import com.ruoyi.xkt.enums.*;
import com.ruoyi.xkt.mapper.AdvertRoundMapper;
import com.ruoyi.xkt.mapper.AdvertStoreFileMapper;
import com.ruoyi.xkt.mapper.SysFileMapper;
import com.ruoyi.xkt.service.IAdminAdvertRoundService;
import com.ruoyi.xkt.service.IAssetService;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.RandomUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
/**
* 广Service
*
* @author ruoyi
* @date 2025-03-26
*/
@Service
@RequiredArgsConstructor
public class AdminAdvertRoundServiceImpl implements IAdminAdvertRoundService {
final IAssetService assetService;
final AdvertRoundMapper advertRoundMapper;
final SysFileMapper fileMapper;
final AdvertStoreFileMapper advertStoreFileMapper;
/**
* 广
*
* @param pageDTO
* @return Page<AdminAdRoundPageResDTO>
*/
@Override
@Transactional(readOnly = true)
public Page<AdminAdRoundPageResDTO> page(AdminAdRoundPageDTO pageDTO) {
// TODO 判断当前是否是管理员
this.isSuperAdmin();
Optional.ofNullable(pageDTO.getLaunchStatus()).orElseThrow(() -> new ServiceException("投放状态launchStatus必传", HttpStatus.ERROR));
PageHelper.startPage(pageDTO.getPageNum(), pageDTO.getPageSize());
List<AdminAdRoundPageResDTO> list = this.advertRoundMapper.selectAdminAdvertPage(pageDTO);
list.forEach(item -> item.setPlatformName(AdPlatformType.of(item.getPlatformId()).getLabel())
.setLaunchStatusName(ObjectUtils.isNotEmpty(item.getLaunchStatus()) ? AdLaunchStatus.of(item.getLaunchStatus()).getLabel() : "")
.setPicAuditStatusName(ObjectUtils.isNotEmpty(item.getPicAuditStatus()) ? AdPicAuditStatus.of(item.getPicAuditStatus()).getLabel() : "")
.setPicDesignTypeName(ObjectUtils.isNotEmpty(item.getPicDesignType()) ? AdDesignType.of(item.getPicDesignType()).getLabel() : "")
.setPicAuditStatusName(ObjectUtils.isNotEmpty(item.getPicAuditStatus()) ? AdPicAuditStatus.of(item.getPicAuditStatus()).getLabel() : "")
.setPicSetTypeName(ObjectUtils.isNotEmpty(item.getPicSetType()) ? AdPicSetType.of(item.getPicSetType()).getLabel() : "")
.setTypeName(AdType.of(item.getTypeId()).getLabel())
.setBiddingStatusName(ObjectUtils.isNotEmpty(item.getBiddingStatus()) ? AdBiddingStatus.of(item.getBiddingStatus()).getLabel() : ""));
return Page.convert(new PageInfo<>(BeanUtil.copyToList(list, AdminAdRoundPageResDTO.class)));
}
/**
* 广
*
* @param auditDTO 广
* @return Integer
*/
@Override
@Transactional
public Integer auditPic(AdminAdRoundAuditDTO auditDTO) {
// TODO 是否为超级管理管理员
this.isSuperAdmin();
AdvertRound advertRound = Optional.ofNullable(this.advertRoundMapper.selectOne(new LambdaQueryWrapper<AdvertRound>()
.eq(AdvertRound::getId, auditDTO.getAdvertRoundId()).eq(AdvertRound::getDelFlag, Constants.UNDELETED)))
.orElseThrow(() -> new ServiceException("推广位不存在!", HttpStatus.ERROR));
// 校验图片审核类型是否存在
AdPicAuditStatus.of(auditDTO.getPicAuditStatus());
advertRound.setPicAuditStatus(auditDTO.getPicAuditStatus()).setRejectReason(auditDTO.getRejectReason());
return this.advertRoundMapper.updateById(advertRound);
}
/**
* 退广
*
* @param unsubscribeDTO 退
* @return Integer
*/
@Override
@Transactional
public Integer unsubscribe(AdminAdRoundUnsubscribeDTO unsubscribeDTO) {
// TODO 判断当前是否是管理员
this.isSuperAdmin();
AdvertRound advertRound = Optional.ofNullable(this.advertRoundMapper.selectOne(new LambdaQueryWrapper<AdvertRound>()
.eq(AdvertRound::getId, unsubscribeDTO.getAdvertRoundId()).eq(AdvertRound::getDelFlag, Constants.UNDELETED)
.eq(AdvertRound::getStoreId, unsubscribeDTO.getStoreId())))
.orElseThrow(() -> new ServiceException("档口购买的推广位不存在!", HttpStatus.ERROR));
// 判断当前时间距离开播是否小于12h若是则不可取消
Date twelveHoursAfter = DateUtils.toDate(LocalDateTime.now().plusHours(12));
if (twelveHoursAfter.after(advertRound.getStartTime())) {
throw new ServiceException("距推广开播小于12小时不可退订!");
}
// 如果扣除了费用,则减去退回金额
BigDecimal remainPayPrice = advertRound.getPayPrice().subtract(ObjectUtils.defaultIfNull(unsubscribeDTO.getDeductionFee(), BigDecimal.ZERO));
// 将费用退回到档口余额中
assetService.refundAdvertFee(advertRound.getStoreId(), remainPayPrice);
// 将推广位置为空
return this.advertRoundMapper.updateAttrNull(advertRound.getId());
}
/**
* @param picDTO 广
* @return Integer
*/
@Override
@Transactional
public Integer uploadAdvertPic(AdRoundUploadPicDTO picDTO) {
// TODO 判断当前是否是管理员
this.isSuperAdmin();
AdvertRound advertRound = Optional.ofNullable(this.advertRoundMapper.selectOne(new LambdaQueryWrapper<AdvertRound>()
.eq(AdvertRound::getId, picDTO.getAdvertRoundId()).eq(AdvertRound::getDelFlag, Constants.UNDELETED)))
.orElseThrow(() -> new ServiceException("推广位不存在!", HttpStatus.ERROR));
SysFile file = BeanUtil.toBean(picDTO, SysFile.class);
int count = this.fileMapper.insert(file);
// 更新推广位的图片ID
advertRound.setPicId(file.getId());
this.advertRoundMapper.updateById(advertRound);
// 将档口上传图片保存到AdvertStoreFile
AdvertStoreFile advertStoreFile = new AdvertStoreFile().setAdvertRoundId(advertRound.getId())
.setStoreId(advertRound.getStoreId()).setFileId(file.getId()).setTypeId(advertRound.getTypeId());
this.advertStoreFileMapper.insert(advertStoreFile);
return count;
}
/**
* 广
*
* @param interceptDTO 广
* @return Integer
*/
@Override
@Transactional
public Integer sysIntercept(AdminAdRoundSysInterceptDTO interceptDTO) {
// TODO 判断当前是否是管理员
this.isSuperAdmin();
final LocalDateTime nineThirty = LocalDateTime.of(LocalDate.now(), LocalTime.of(21, 30));
final LocalDateTime tenFive = LocalDateTime.of(LocalDate.now(), LocalTime.of(22, 5));
// 判断当前时间是否为晚上9:30 - 10:05区间若是则管理员不可操作推广拦截
if (LocalDateTime.now().isAfter(nineThirty) && LocalDateTime.now().isBefore(tenFive)) {
throw new ServiceException("21:30 - 22:05之间为档口购买推广时间管理员不可操作推广拦截!", HttpStatus.ERROR);
}
AdvertRound advertRound = Optional.ofNullable(this.advertRoundMapper.selectOne(new LambdaQueryWrapper<AdvertRound>()
.eq(AdvertRound::getId, interceptDTO.getAdvertRoundId()).eq(AdvertRound::getDelFlag, Constants.UNDELETED)))
.orElseThrow(() -> new ServiceException("推广位不存在!", HttpStatus.ERROR));
// 如果该广告位已被拦截,则不可再次拦截
if (Objects.equals(advertRound.getSysIntercept(), AdSysInterceptType.INTERCEPT.getValue())) {
throw new ServiceException("该推广位已被拦截,不可再次拦截!", HttpStatus.ERROR);
}
// 若该推广位已投放
if (Objects.equals(advertRound.getLaunchStatus(), AdLaunchStatus.LAUNCHING.getValue())) {
// 若该广告位 为时间范围 且 为档口正常购买(也有可能为系统拦截),则均不可不可拦截该推广位
if (Objects.equals(advertRound.getShowType(), AdShowType.TIME_RANGE.getValue()) && ObjectUtils.isNotEmpty(advertRound.getStoreId())) {
throw new ServiceException("该推广位为档口正常购买,已投放,不可拦截!", HttpStatus.ERROR);
}
// 若该广告位为位置枚举,则不可购买,因为位置枚举一般都是第二天播放
if (Objects.equals(advertRound.getShowType(), AdShowType.POSITION_ENUM.getValue())) {
throw new ServiceException("该推广位为位置枚举,不可购买,因为位置枚举一般都是第二天播放!", HttpStatus.ERROR);
}
// 若为待投放推广
} else {
// 判断拦截的推广位,是否档口已经购买。
if (ObjectUtils.isNotEmpty(advertRound.getStoreId()) && Objects.equals(advertRound.getSysIntercept(), AdSysInterceptType.UN_INTERCEPT.getValue())) {
// 判断当前时间是否为投放前一天22:00之后 若是,则不可拦截,因该推广位已售出
LocalDateTime twoHourBeforeStartTime = advertRound.getStartTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime().withHour(22).withMinute(0).withSecond(0);
if (LocalDateTime.now().isAfter(twoHourBeforeStartTime)) {
throw new ServiceException("当前推广位已被档口购买,不可拦截!", HttpStatus.ERROR);
}
}
}
// 如果该推广位是被档口正常购买,则直接退费
if (ObjectUtils.isNotEmpty(advertRound.getStoreId()) && Objects.equals(advertRound.getSysIntercept(), AdSysInterceptType.UN_INTERCEPT.getValue())) {
assetService.refundAdvertFee(advertRound.getStoreId(), ObjectUtils.defaultIfNull(advertRound.getPayPrice(), BigDecimal.ZERO));
}
// 设置系统拦截的数据 并将系统拦截设置为1
advertRound.setStoreId(interceptDTO.getStoreId()).setSysIntercept(AdSysInterceptType.INTERCEPT.getValue())
.setVoucherDate(java.sql.Date.valueOf(LocalDate.now())).setBiddingStatus(AdBiddingStatus.BIDDING_SUCCESS.getValue())
.setBiddingTempStatus(AdBiddingStatus.BIDDING_SUCCESS.getValue());
if (ObjectUtils.isNotEmpty(interceptDTO.getFile())) {
SysFile file = BeanUtil.toBean(interceptDTO.getFile(), SysFile.class);
this.fileMapper.insert(file);
advertRound.setPicId(file.getId()).setPicAuditStatus(AdPicAuditStatus.AUDIT_PASS.getValue()).setPicDesignType(AdDesignType.SYS_DESIGN.getValue());
}
if (ObjectUtils.isNotEmpty(interceptDTO.getStoreProdIdList())) {
advertRound.setProdIdStr(StringUtils.join(interceptDTO.getStoreProdIdList(), ","));
}
// 如果是位置枚举则设置一个很高的价格400 - 600范围有其它档口愿意出更高价格拿下就随他去
if (Objects.equals(advertRound.getShowType(), AdShowType.POSITION_ENUM.getValue())) {
advertRound.setPayPrice(BigDecimal.valueOf(RandomUtils.nextLong(40, 60 + 1) * 10));
}
return this.advertRoundMapper.updateById(advertRound);
}
/**
* 广
*
* @param advertRoundId 广ID
* @return Integer
*/
@Override
@Transactional
public Integer cancelIntercept(Long advertRoundId) {
// TODO 判断当前是否是管理员
this.isSuperAdmin();
// 该推广位是否被拦截
AdvertRound advertRound = Optional.ofNullable(this.advertRoundMapper.selectOne(new LambdaQueryWrapper<AdvertRound>()
.eq(AdvertRound::getId, advertRoundId).eq(AdvertRound::getDelFlag, Constants.UNDELETED)
.eq(AdvertRound::getSysIntercept, AdSysInterceptType.INTERCEPT.getValue())))
.orElseThrow(() -> new ServiceException("推广位不存在!", HttpStatus.ERROR));
// 被系统拦截的推广位不用退费,直接清空数据即可
return this.advertRoundMapper.updateAttrNull(advertRound.getId());
}
/**
*
*/
private void isSuperAdmin() {
// 获取当前登录用户
LoginUser loginUser = SecurityUtils.getLoginUser();
if (ObjectUtils.isEmpty(loginUser)) {
throw new ServiceException("当前用户不存在!", HttpStatus.ERROR);
}
if (!SecurityUtils.isAdmin(loginUser.getUserId())) {
throw new ServiceException("当前用户不是超级管理员,不可操作!", HttpStatus.ERROR);
}
}
}

View File

@ -11,10 +11,7 @@ import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.enums.AdType;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.xkt.domain.AdvertRound;
import com.ruoyi.xkt.domain.AdvertRoundRecord;
import com.ruoyi.xkt.domain.StoreProduct;
import com.ruoyi.xkt.domain.SysFile;
import com.ruoyi.xkt.domain.*;
import com.ruoyi.xkt.dto.advertRound.*;
import com.ruoyi.xkt.enums.*;
import com.ruoyi.xkt.mapper.*;
@ -62,6 +59,7 @@ public class AdvertRoundServiceImpl implements IAdvertRoundService {
final StoreProductMapper storeProdMapper;
final SysFileMapper fileMapper;
final IAssetService assetService;
final AdvertStoreFileMapper advertStoreFileMapper;
// 推广营销位锁 keysymbol + roundId 或者 symbol + roundId + position 。value都是new Object()
public static Map<String, Object> advertLockMap = new ConcurrentHashMap<>();
@ -525,18 +523,21 @@ public class AdvertRoundServiceImpl implements IAdvertRoundService {
.eq(AdvertRound::getAdvertId, latestDTO.getAdvertId()).eq(AdvertRound::getRoundId, latestDTO.getRoundId())
.eq(AdvertRound::getDelFlag, Constants.UNDELETED).orderByDesc(AdvertRound::getPayPrice, AdvertRound::getCreateTime)
.last("LIMIT 1"));
// 有人竞拍情况,才获取该位置的档口负责人名称
if (ObjectUtils.isNotEmpty(advertRound)) {
latestInfo.setStoreOwnerName(this.advertRoundMapper.getStoreOwnerName(advertRound.getStoreId()));
}
return latestInfo.setStoreId(advertRound.getStoreId()).setPayPrice(advertRound.getPayPrice());
} else {
Optional.ofNullable(latestDTO.getPosition()).orElseThrow(() -> new ServiceException("位置枚举类型position必传", HttpStatus.ERROR));
advertRound = Optional.ofNullable(this.advertRoundMapper.selectOne(new LambdaQueryWrapper<AdvertRound>()
.eq(AdvertRound::getAdvertId, latestDTO.getAdvertId()).eq(AdvertRound::getRoundId, latestDTO.getRoundId())
.eq(AdvertRound::getPosition, latestDTO.getPosition()).eq(AdvertRound::getDelFlag, Constants.UNDELETED)))
.orElseThrow(() -> new ServiceException("推广位不存在!", HttpStatus.ERROR));
latestInfo.setPayPrice(advertRound.getPayPrice());
}
// 有人竞拍情况,才获取该位置的档口负责人名称
if (ObjectUtils.isNotEmpty(advertRound.getStoreId())) {
Store store = Optional.ofNullable(this.storeMapper.selectOne(new LambdaQueryWrapper<Store>()
.eq(Store::getId, advertRound.getStoreId()).eq(Store::getDelFlag, Constants.UNDELETED)))
.orElseThrow(() -> new ServiceException("档口不存在!", HttpStatus.ERROR));
latestInfo.setStoreId(advertRound.getStoreId()).setPayPrice(advertRound.getPayPrice())
// 对手机号中间位数进行*号替换处理
.setContactPhone(this.maskPhoneNum(store.getContactPhone()));
}
// 如果当前档口购买该推广位,且设置商品不为空,则返回设置的商品信息
if (Objects.equals(advertRound.getStoreId(), latestDTO.getStoreId()) && StringUtils.isNotBlank(advertRound.getProdIdStr())) {
@ -550,6 +551,30 @@ public class AdvertRoundServiceImpl implements IAdvertRoundService {
return latestInfo;
}
/**
* @param picDTO 广
* @return Integer
*/
@Override
@Transactional
public Integer uploadAdvertPic(AdRoundUploadPicDTO picDTO) {
AdvertRound advertRound = Optional.ofNullable(this.advertRoundMapper.selectOne(new LambdaQueryWrapper<AdvertRound>()
.eq(AdvertRound::getId, picDTO.getAdvertRoundId()).eq(AdvertRound::getDelFlag, Constants.UNDELETED)))
.orElseThrow(() -> new ServiceException("推广位不存在!", HttpStatus.ERROR));
SysFile file = BeanUtil.toBean(picDTO, SysFile.class);
int count = this.fileMapper.insert(file);
// 更新推广位的图片ID
advertRound.setPicId(file.getId());
this.advertRoundMapper.updateById(advertRound);
// 将档口上传图片保存到AdvertStoreFile
AdvertStoreFile advertStoreFile = new AdvertStoreFile().setAdvertRoundId(advertRound.getId())
.setStoreId(advertRound.getStoreId()).setFileId(file.getId()).setTypeId(advertRound.getTypeId());
this.advertStoreFileMapper.insert(advertStoreFile);
return count;
}
/**
* 广
*
@ -758,4 +783,24 @@ public class AdvertRoundServiceImpl implements IAdvertRoundService {
return boughtRoundList;
}
/**
* *
*
* @param phoneNumber
* @return String
*/
private String maskPhoneNum(String phoneNumber) {
if (StringUtils.isEmpty(phoneNumber) || phoneNumber.length() < 4) {
return "";
}
int length = phoneNumber.length();
String prefix = phoneNumber.substring(0, 2); // 前两位
String suffix = phoneNumber.substring(length - 2); // 后两位
StringBuilder middle = new StringBuilder();
for (int i = 0; i < length - 4; i++) {
middle.append('*'); // 中间替换为*
}
return prefix + middle + suffix;
}
}

View File

@ -242,22 +242,22 @@ public class ShoppingCartServiceImpl implements IShoppingCartService {
/**
*
*
* @param shoppingCartId ID
* @param deleteDTO ID
* @return
*/
@Override
@Transactional
public Integer delete(Long shoppingCartId) {
public Integer delete(ShopCartDeleteDTO deleteDTO) {
LoginUser loginUser = SecurityUtils.getLoginUser();
ShoppingCart shopCart = Optional.ofNullable(this.shopCartMapper.selectOne(new LambdaQueryWrapper<ShoppingCart>()
.eq(ShoppingCart::getId, shoppingCartId).eq(ShoppingCart::getDelFlag, Constants.UNDELETED)
List<ShoppingCart> shopCartList = Optional.ofNullable(this.shopCartMapper.selectList(new LambdaQueryWrapper<ShoppingCart>()
.in(ShoppingCart::getId, deleteDTO.getShoppingCartIdList()).eq(ShoppingCart::getDelFlag, Constants.UNDELETED)
.eq(ShoppingCart::getUserId, loginUser.getUserId())))
.orElseThrow(() -> new ServiceException("用户购物车不存在!", HttpStatus.ERROR));
shopCart.setDelFlag(Constants.DELETED);
int count = this.shopCartMapper.updateById(shopCart);
shopCartList.forEach(x -> x.setDelFlag(DELETED));
int count = this.shopCartMapper.updateById(shopCartList).size();
// 找到进货车明细
List<ShoppingCartDetail> detailList = this.shopCartDetailMapper.selectList(new LambdaQueryWrapper<ShoppingCartDetail>()
.eq(ShoppingCartDetail::getShoppingCartId, shoppingCartId).eq(ShoppingCartDetail::getDelFlag, Constants.UNDELETED));
.in(ShoppingCartDetail::getShoppingCartId, deleteDTO.getShoppingCartIdList()).eq(ShoppingCartDetail::getDelFlag, Constants.UNDELETED));
detailList.forEach(x -> x.setDelFlag(Constants.DELETED));
this.shopCartDetailMapper.updateById(detailList);
return count;

View File

@ -179,6 +179,26 @@ public class StoreProductServiceImpl implements IStoreProductService {
@Override
@Transactional
public int insertStoreProduct(StoreProdDTO storeProdDTO) throws IOException {
// TODO 富文本标签过滤
// TODO 富文本标签过滤
// TODO 富文本标签过滤
// TODO 富文本标签过滤
// TODO 富文本标签过滤
// TODO 富文本标签过滤
// TODO 富文本标签过滤
// 组装StoreProduct数据
StoreProduct storeProd = BeanUtil.toBean(storeProdDTO, StoreProduct.class).setVoucherDate(DateUtils.getNowDate())
.setRecommendWeight(0L).setSaleWeight(0L).setPopularityWeight(0L);
@ -204,6 +224,22 @@ public class StoreProductServiceImpl implements IStoreProductService {
@Override
@Transactional
public int updateStoreProduct(final Long storeProdId, StoreProdDTO storeProdDTO) throws IOException {
// TODO 富文本标签过滤
// TODO 富文本标签过滤
// TODO 富文本标签过滤
// TODO 富文本标签过滤
// TODO 富文本标签过滤
// TODO 富文本标签过滤
// TODO 富文本标签过滤
StoreProduct storeProd = Optional.ofNullable(this.storeProdMapper.selectOne(new LambdaQueryWrapper<StoreProduct>()
.eq(StoreProduct::getId, storeProdId).eq(StoreProduct::getDelFlag, Constants.UNDELETED)))
.orElseThrow(() -> new ServiceException("档口商品不存在!", HttpStatus.ERROR));

View File

@ -200,6 +200,21 @@ public class StoreServiceImpl implements IStoreService {
.setTagList(storeTagList.stream().map(DailyStoreTag::getTag).collect(Collectors.toList()));
}
/**
* 广
*
* @param storeId ID
* @return StoreAdvertResDTO
*/
@Override
@Transactional(readOnly = true)
public StoreAdvertResDTO getAdvertStoreInfo(Long storeId) {
Store store = Optional.ofNullable(this.storeMapper.selectOne(new LambdaQueryWrapper<Store>()
.eq(Store::getId, storeId).eq(Store::getDelFlag, Constants.UNDELETED)))
.orElseThrow(() -> new ServiceException("档口不存在!", HttpStatus.ERROR));
return BeanUtil.toBean(store, StoreAdvertResDTO.class);
}
/**
*
*

View File

@ -27,9 +27,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<select id="selectStoreAdvertPage" parameterType="com.ruoyi.xkt.dto.advertRound.AdvertRoundStorePageDTO" resultType="com.ruoyi.xkt.dto.advertRound.AdvertRoundStorePageResDTO">
SELECT
ar.id AS advertRoundId,
a.platform_id,
s.store_name,
ar.type_id,
ar.position,
CONCAT('位置', ar.position) AS position,
ar.start_time,
ar.end_time,
ar.pay_price,
@ -40,22 +42,63 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
ar.pic_audit_status
FROM
advert_round ar
JOIN advert a ON ar.advert_id = a.id
JOIN advert a ON ar.advert_id = a.id
LEFT JOIN store s ON ar.store_id = s.id
WHERE
ar.del_flag = 0
AND ar.store_id = #{storeId}
AND ar.bidding_status IN
<foreach item="biddingStatus" collection="biddingStatusList" open="(" separator="," close=")">
#{biddingStatus}
</foreach>
<if test="platformId != null "> and a.platform_id = #{platformId}</if>
<if test="typeId != null "> and ar.type_id = #{typeId}</if>
<if test="launchStatus != null "> and ar.launch_status = #{launchStatus}</if>
<if test="biddingStatus != null "> and ar.bidding_status = #{biddingStatus}</if>
<if test="picSetType != null "> and ar.pic_set_type = #{picSetType}</if>
<if test="picDesignType != null "> and ar.pic_design_type = #{picDesignType}</if>
<if test="picAuditStatus != null "> and ar.pic_audit_status = #{picAuditStatus}</if>
<if test="startTime != null "> and ar.start_time &gt;= #{startTime}</if>
<if test="endTime != null "> and ar.end_time &lt;= #{endTime}</if>
ORDER BY
ar.create_time DESC
ar.start_time DESC
</select>
<select id="selectAdminAdvertPage" parameterType="com.ruoyi.xkt.dto.adminAdvertRound.AdminAdRoundPageDTO" resultType="com.ruoyi.xkt.dto.adminAdvertRound.AdminAdRoundPageResDTO">
SELECT
ar.id AS advertRoundId,
s.store_name,
a.platform_id,
ar.type_id,
CONCAT('位置', ar.position) AS position,
ar.start_time,
ar.end_time,
ar.pay_price,
ar.launch_status,
ar.bidding_status,
ar.pic_design_type,
ar.pic_set_type,
ar.pic_audit_status,
ar.sys_intercept
FROM
advert_round ar
JOIN advert a ON ar.advert_id = a.id
LEFT JOIN store s ON ar.store_id = s.id
WHERE
ar.del_flag = 0
AND ar.launch_status = #{launchStatus}
<if test="platformId != null "> and a.platform_id = #{platformId}</if>
<if test="storeId != null "> and ar.store_id = #{storeId}</if>
<if test="typeId != null "> and ar.type_id = #{typeId}</if>
<if test="picDesignType != null "> and ar.pic_design_type = #{picDesignType}</if>
<if test="picAuditStatus != null "> and ar.pic_audit_status = #{picAuditStatus}</if>
<if test="roundId != null "> and ar.round_id = #{roundId}</if>
<if test="sysIntercept != null "> and ar.sys_intercept = #{sysIntercept}</if>
ORDER BY
ar.start_time DESC
</select>
<update id="updateAttrNull">
UPDATE advert_round
SET voucher_date = NULL,
@ -68,7 +111,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
pic_id = NULL,
prod_id_str = NULL,
pic_design_type = NULL,
sys_intercept = NULL
sys_intercept = 0
WHERE
id = #{advertRoundId}
</update>
@ -99,16 +142,5 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
AND round_id = #{roundId}
</select>
<select id="getStoreOwnerName">
SELECT DISTINCT
u.nick_name
FROM
store s
JOIN sys_user u ON s.user_id = u.user_id
WHERE
s.id = #{storeId}
AND s.del_flag = 0
</select>
</mapper>