| | |
| | | package cn.lili.controller.lmk; |
| | | |
| | | import cn.lili.group.Update; |
| | | import cn.lili.base.Result; |
| | | import cn.lili.group.Add; |
| | | import org.springframework.validation.annotation.Validated; |
| | | import org.springframework.security.access.prepost.PreAuthorize; |
| | | import lombok.RequiredArgsConstructor; |
| | | import java.util.List; |
| | | import org.springframework.validation.annotation.Validated; |
| | | import javax.validation.constraints.NotEmpty; |
| | | import cn.lili.modules.lmk.domain.form.ActionRecordForm; |
| | | import cn.lili.modules.lmk.domain.form.ShareActionForm; |
| | | import cn.lili.modules.lmk.service.ActionRecordService; |
| | | import cn.lili.modules.lmk.service.ShareActionService; |
| | | import io.swagger.annotations.Api; |
| | | import io.swagger.annotations.ApiOperation; |
| | | import cn.lili.modules.lmk.service.ActionRecordService; |
| | | import cn.lili.base.Result; |
| | | import cn.lili.modules.lmk.domain.form.ActionRecordForm; |
| | | import cn.lili.modules.lmk.domain.query.ActionRecordQuery; |
| | | import lombok.RequiredArgsConstructor; |
| | | import org.springframework.validation.annotation.Validated; |
| | | import org.springframework.web.bind.annotation.*; |
| | | |
| | | /** |
| | |
| | | public class ActionRecordBuyerController { |
| | | |
| | | private final ActionRecordService actionRecordService; |
| | | private final ShareActionService shareActionService; |
| | | |
| | | @PostMapping |
| | | @ApiOperation(value = "添加", notes = "添加") |
| | | public Result add(@RequestBody @Validated(Add.class) ActionRecordForm form) { |
| | | return actionRecordService.add(form); |
| | | } |
| | | @PostMapping("/share") |
| | | @ApiOperation(value = "添加分享", notes = "添加分享") |
| | | public Result shareAdd(@RequestBody @Validated(Add.class) ShareActionForm form) { |
| | | return shareActionService.add(form); |
| | | } |
| | | @GetMapping("/sessionId") |
| | | @ApiOperation(value = "获取会话id", notes = "获取会话id") |
| | | public Result grantSessionId() { |
| | |
| | | @ApiModelProperty(value = "商品参数json") |
| | | private String params; |
| | | |
| | | @ApiModelProperty(value = "商品排序") |
| | | private Integer goodsSort; |
| | | |
| | | |
| | | @ApiModelProperty(value = "预售结束时间") |
| | | @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd") |
| | |
| | | * @param queryWrapper 查询条件 |
| | | * @return 售后VO分页 |
| | | */ |
| | | @Select("SELECT *,g.params as params,g.pre_sale_end_date,g.pre_sale_begin_date FROM li_goods_sku gs inner join li_goods g on gs.goods_id = g.id ${ew.customSqlSegment}") |
| | | @Select("SELECT *,g.params as params,g.goods_sort as goodsSort,g.pre_sale_end_date,g.pre_sale_begin_date FROM li_goods_sku gs inner join li_goods g on gs.goods_id = g.id ${ew.customSqlSegment}") |
| | | IPage<GoodsSkuDTO> queryByParams(IPage<GoodsSkuDTO> page, @Param(Constants.WRAPPER) Wrapper<GoodsSkuDTO> queryWrapper); |
| | | |
| | | @Select("SELECT id as sku_id, quantity, goods_id,simple_specs,sn,goods_name FROM li_goods_sku ${ew.customSqlSegment}") |
New file |
| | |
| | | package cn.lili.modules.lmk.domain.entity; |
| | | |
| | | import cn.lili.mybatis.BaseEntity; |
| | | import com.baomidou.mybatisplus.annotation.TableField; |
| | | import com.baomidou.mybatisplus.annotation.TableName; |
| | | import java.io.Serializable; |
| | | import lombok.Data; |
| | | |
| | | /** |
| | | * 用户行为分享 |
| | | * |
| | | * @author peng |
| | | * @since 2025-09-25 |
| | | */ |
| | | @Data |
| | | @TableName("lmk_share_action") |
| | | public class ShareAction extends BaseEntity { |
| | | |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | @TableField("user_id") |
| | | /** 用户id */ |
| | | private String userId; |
| | | |
| | | @TableField("share_option") |
| | | /** 分享参数 */ |
| | | private String shareOption; |
| | | |
| | | @TableField("page_code") |
| | | /** 页面编码 */ |
| | | private String pageCode; |
| | | |
| | | @TableField("page_type") |
| | | /** 页面类型 */ |
| | | private String pageType; |
| | | |
| | | @TableField("pid") |
| | | /** pid */ |
| | | private Long pid; |
| | | |
| | | |
| | | } |
New file |
| | |
| | | package cn.lili.modules.lmk.domain.form; |
| | | |
| | | import cn.lili.group.Update; |
| | | import cn.lili.group.Add; |
| | | import cn.lili.base.AbsForm; |
| | | import cn.lili.modules.lmk.domain.entity.ShareAction; |
| | | import org.springframework.beans.BeanUtils; |
| | | import javax.validation.constraints.NotBlank; |
| | | import javax.validation.constraints.NotNull; |
| | | import org.springframework.lang.NonNull; |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Data; |
| | | import java.util.Date; |
| | | |
| | | /** |
| | | * 用户行为分享表单 |
| | | * |
| | | * @author peng |
| | | * @since 2025-09-25 |
| | | */ |
| | | @Data |
| | | @ApiModel(value = "ShareAction表单", description = "用户行为分享表单") |
| | | public class ShareActionForm extends AbsForm { |
| | | |
| | | @ApiModelProperty("用户id") |
| | | private Long userId; |
| | | |
| | | @NotBlank(message = "分享参数不能为空", groups = {Add.class, Update.class}) |
| | | @ApiModelProperty("分享参数") |
| | | private String shareOption; |
| | | |
| | | @NotBlank(message = "页面编码不能为空", groups = {Add.class, Update.class}) |
| | | @ApiModelProperty("页面编码") |
| | | private String pageCode; |
| | | |
| | | @NotBlank(message = "页面类型不能为空", groups = {Add.class, Update.class}) |
| | | @ApiModelProperty("页面类型") |
| | | private String pageType; |
| | | |
| | | @ApiModelProperty("pid") |
| | | private Long pid; |
| | | |
| | | public static ShareAction getEntityByForm(@NonNull ShareActionForm form, ShareAction entity) { |
| | | if(entity == null) { |
| | | entity = new ShareAction(); |
| | | } |
| | | BeanUtils.copyProperties(form, entity); |
| | | return entity; |
| | | } |
| | | |
| | | } |
New file |
| | |
| | | package cn.lili.modules.lmk.domain.query; |
| | | |
| | | import cn.lili.base.AbsQuery; |
| | | import java.util.List; |
| | | import org.springframework.lang.NonNull; |
| | | import javax.validation.constraints.NotBlank; |
| | | import javax.validation.constraints.NotNull; |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Data; |
| | | |
| | | /** |
| | | * 用户行为分享查询 |
| | | * |
| | | * @author peng |
| | | * @since 2025-09-25 |
| | | */ |
| | | @Data |
| | | @ApiModel(value = "ShareAction查询参数", description = "用户行为分享查询参数") |
| | | public class ShareActionQuery extends AbsQuery { |
| | | } |
| | | |
New file |
| | |
| | | package cn.lili.modules.lmk.domain.vo; |
| | | |
| | | |
| | | import lombok.AllArgsConstructor; |
| | | import lombok.Data; |
| | | import lombok.NoArgsConstructor; |
| | | |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * lmk-shop-java |
| | | * |
| | | * @author : zxl |
| | | * @date : 2025-09-19 15:26 |
| | | **/ |
| | | @Data |
| | | @AllArgsConstructor |
| | | @NoArgsConstructor |
| | | public class PvUvVO { |
| | | |
| | | /** |
| | | * pv折线图数据 |
| | | */ |
| | | private List<Long> pvData; |
| | | |
| | | /** |
| | | * uv折线图数据 |
| | | */ |
| | | private List<Long> uvData; |
| | | |
| | | } |
New file |
| | |
| | | package cn.lili.modules.lmk.domain.vo; |
| | | |
| | | |
| | | import lombok.AllArgsConstructor; |
| | | import lombok.Data; |
| | | import lombok.NoArgsConstructor; |
| | | |
| | | /** |
| | | * lmk-shop-java |
| | | * |
| | | * @author : zxl |
| | | * @date : 2025-09-22 10:09 |
| | | **/ |
| | | @Data |
| | | @AllArgsConstructor |
| | | @NoArgsConstructor |
| | | public class SelectVO { |
| | | /** |
| | | * 下拉框id |
| | | */ |
| | | private String id; |
| | | /** |
| | | * 下拉框label |
| | | */ |
| | | private String label; |
| | | } |
New file |
| | |
| | | package cn.lili.modules.lmk.domain.vo; |
| | | |
| | | import cn.lili.base.AbsVo; |
| | | import cn.lili.modules.lmk.domain.entity.ShareAction; |
| | | import java.util.List; |
| | | import org.springframework.lang.NonNull; |
| | | import org.springframework.beans.BeanUtils; |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Data; |
| | | import java.util.Date; |
| | | |
| | | /** |
| | | * 用户行为分享展示 |
| | | * |
| | | * @author peng |
| | | * @since 2025-09-25 |
| | | */ |
| | | @Data |
| | | @ApiModel(value = "用户行为分享响应数据", description = "用户行为分享响应数据") |
| | | public class ShareActionVO extends AbsVo { |
| | | |
| | | /** 用户id */ |
| | | @ApiModelProperty("用户id") |
| | | private Long userId; |
| | | |
| | | /** 分享参数 */ |
| | | @ApiModelProperty("分享参数") |
| | | private String shareOption; |
| | | |
| | | /** 页面编码 */ |
| | | @ApiModelProperty("页面编码") |
| | | private String pageCode; |
| | | |
| | | /** 页面类型 */ |
| | | @ApiModelProperty("页面类型") |
| | | private String pageType; |
| | | |
| | | /** pid */ |
| | | @ApiModelProperty("pid") |
| | | private Long pid; |
| | | |
| | | public static ShareActionVO getVoByEntity(@NonNull ShareAction entity, ShareActionVO vo) { |
| | | if(vo == null) { |
| | | vo = new ShareActionVO(); |
| | | } |
| | | BeanUtils.copyProperties(entity, vo); |
| | | return vo; |
| | | } |
| | | |
| | | } |
New file |
| | |
| | | package cn.lili.modules.lmk.domain.vo; |
| | | |
| | | |
| | | import lombok.AllArgsConstructor; |
| | | import lombok.Data; |
| | | import lombok.NoArgsConstructor; |
| | | |
| | | /** |
| | | * lmk-shop-java |
| | | * |
| | | * @author : zxl |
| | | * @date : 2025-09-25 15:36 |
| | | **/ |
| | | @Data |
| | | @NoArgsConstructor |
| | | @AllArgsConstructor |
| | | public class VideoViewCompletionRateVO { |
| | | private String complete_rate; |
| | | |
| | | private Long total_views; |
| | | |
| | | } |
New file |
| | |
| | | package cn.lili.modules.lmk.enums.general; |
| | | |
| | | import lombok.AllArgsConstructor; |
| | | import lombok.Getter; |
| | | |
| | | /** |
| | | * 统计搜索类型枚举 |
| | | */ |
| | | @Getter |
| | | @AllArgsConstructor |
| | | public enum StatisticsSearchTypeEnum { |
| | | |
| | | TODAY("今天"), |
| | | YESTERDAY("昨天"), |
| | | LAST_SEVEN("过去七天"), |
| | | LAST_THIRTY("过去一个月"); |
| | | |
| | | private final String desc; |
| | | |
| | | |
| | | } |
New file |
| | |
| | | package cn.lili.modules.lmk.enums.general; |
| | | |
| | | import lombok.AllArgsConstructor; |
| | | |
| | | @AllArgsConstructor |
| | | public enum UserActionInPageStatusEnum { |
| | | JOIN("进入"), |
| | | LEAVE("离开"); |
| | | private final String des; |
| | | |
| | | public UserActionInPageStatusEnum select(String name){ |
| | | for (UserActionInPageStatusEnum value : UserActionInPageStatusEnum.values()) { |
| | | if (value.name().equals(name)) { |
| | | return value; |
| | | } |
| | | } |
| | | return null; |
| | | } |
| | | } |
New file |
| | |
| | | package cn.lili.modules.lmk.enums.general; |
| | | |
| | | import lombok.AllArgsConstructor; |
| | | |
| | | @AllArgsConstructor |
| | | public enum UserActionJoinPageTypeEnum { |
| | | SCAN("扫码"), |
| | | SELF("自己"), |
| | | SHARE("分享"); |
| | | private final String des; |
| | | |
| | | public UserActionJoinPageTypeEnum select(String name){ |
| | | for (UserActionJoinPageTypeEnum value : UserActionJoinPageTypeEnum.values()) { |
| | | if (value.name().equals(name)) { |
| | | return value; |
| | | } |
| | | } |
| | | return null; |
| | | } |
| | | } |
| | |
| | | ORDER_LIST("订单列表"), |
| | | ORDER_DETAIL("订单详情"), |
| | | ACTIVITY("活动"), |
| | | PRIZE_DETAIL("抽奖活动"), |
| | | CART_LIST("购物车"), |
| | | TBA_BAR_MY("我的页面"), |
| | | SHOPPING_SQUARE("商品广场"), |
| | | ACTIVITY_LIST("活动列表"), |
| | | ACTIVITY_DETAIL("活动详情"), |
| | | PUBLISH_VIDEO("视频发布"), |
| | | SWIPER_GOODS("滑动商品"), |
| | | COUPON_CENTER("领卷中心"), |
| | | MY_COUPON("我的优惠卷"), |
| | | AFTER_SALE("售后列表"), |
| | | APPLY_SALE("申请售后"), |
| | | REFUND_ORDER("退款/退货"), |
| | | GOODS_DETAILS("商品详情页面"); |
| | | private final String des; |
| | | |
New file |
| | |
| | | package cn.lili.modules.lmk.enums.general; |
| | | |
| | | import lombok.AllArgsConstructor; |
| | | |
| | | @AllArgsConstructor |
| | | public enum UserActionPageTypeEnum { |
| | | LIST("列表页"), |
| | | DETAIL("详情页"); |
| | | private final String des; |
| | | |
| | | public UserActionPageTypeEnum select(String name){ |
| | | for (UserActionPageTypeEnum value : UserActionPageTypeEnum.values()) { |
| | | if (value.name().equals(name)) { |
| | | return value; |
| | | } |
| | | } |
| | | return null; |
| | | } |
| | | } |
New file |
| | |
| | | package cn.lili.modules.lmk.enums.general; |
| | | |
| | | import lombok.AllArgsConstructor; |
| | | |
| | | @AllArgsConstructor |
| | | public enum UserActionTypeEnum { |
| | | PAGE("页面"), |
| | | BTN("功能"); |
| | | private final String des; |
| | | |
| | | public UserActionTypeEnum select(String name){ |
| | | for (UserActionTypeEnum value : UserActionTypeEnum.values()) { |
| | | if (value.name().equals(name)) { |
| | | return value; |
| | | } |
| | | } |
| | | return null; |
| | | } |
| | | } |
New file |
| | |
| | | package cn.lili.modules.lmk.mapper; |
| | | |
| | | import cn.lili.modules.lmk.domain.entity.ShareAction; |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | | import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
| | | import cn.lili.modules.lmk.domain.vo.ShareActionVO; |
| | | import cn.lili.modules.lmk.domain.form.ShareActionForm; |
| | | import cn.lili.modules.lmk.domain.query.ShareActionQuery; |
| | | import java.util.List; |
| | | import org.apache.ibatis.annotations.Mapper; |
| | | import org.apache.ibatis.annotations.Param; |
| | | |
| | | /** |
| | | * 用户行为分享 Mapper 接口 |
| | | * |
| | | * @author peng |
| | | * @since 2025-09-25 |
| | | */ |
| | | @Mapper |
| | | public interface ShareActionMapper extends BaseMapper<ShareAction> { |
| | | |
| | | /** |
| | | * id查找用户行为分享 |
| | | * @param id |
| | | * @return |
| | | */ |
| | | ShareActionVO getById(String id); |
| | | |
| | | /** |
| | | * 分页 |
| | | */ |
| | | IPage getPage(IPage page, @Param("query") ShareActionQuery query); |
| | | |
| | | } |
New file |
| | |
| | | package cn.lili.modules.lmk.service; |
| | | |
| | | import cn.lili.modules.lmk.domain.entity.ShareAction; |
| | | import com.baomidou.mybatisplus.extension.service.IService; |
| | | import cn.lili.base.Result; |
| | | import cn.lili.modules.lmk.domain.form.ShareActionForm; |
| | | import cn.lili.modules.lmk.domain.query.ShareActionQuery; |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * 用户行为分享 服务类 |
| | | * |
| | | * @author peng |
| | | * @since 2025-09-25 |
| | | */ |
| | | public interface ShareActionService extends IService<ShareAction> { |
| | | |
| | | /** |
| | | * 添加 |
| | | * @param form |
| | | * @return |
| | | */ |
| | | Result add(ShareActionForm form); |
| | | |
| | | /** |
| | | * 修改 |
| | | * @param form |
| | | * @return |
| | | */ |
| | | Result update(ShareActionForm form); |
| | | |
| | | /** |
| | | * 批量删除 |
| | | * @param ids |
| | | * @return |
| | | */ |
| | | Result remove(List<String> ids); |
| | | |
| | | /** |
| | | * id删除 |
| | | * @param id |
| | | * @return |
| | | */ |
| | | Result removeById(String id); |
| | | |
| | | /** |
| | | * 分页查询 |
| | | * @param query |
| | | * @return |
| | | */ |
| | | Result page(ShareActionQuery query); |
| | | |
| | | /** |
| | | * 根据id查找 |
| | | * @param id |
| | | * @return |
| | | */ |
| | | Result detail(String id); |
| | | |
| | | /** |
| | | * 列表 |
| | | * @return |
| | | */ |
| | | Result all(); |
| | | } |
New file |
| | |
| | | package cn.lili.modules.lmk.service.impl; |
| | | |
| | | import cn.lili.common.security.AuthUser; |
| | | import cn.lili.common.security.context.UserContext; |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | | import cn.lili.modules.lmk.domain.entity.ShareAction; |
| | | import cn.lili.modules.lmk.mapper.ShareActionMapper; |
| | | import cn.lili.modules.lmk.service.ShareActionService; |
| | | import cn.lili.base.Result; |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | import cn.lili.modules.lmk.domain.form.ShareActionForm; |
| | | import cn.lili.modules.lmk.domain.vo.ShareActionVO; |
| | | import cn.lili.modules.lmk.domain.query.ShareActionQuery; |
| | | import org.springframework.stereotype.Service; |
| | | import lombok.RequiredArgsConstructor; |
| | | import cn.lili.utils.PageUtil; |
| | | import org.springframework.beans.BeanUtils; |
| | | import org.springframework.util.Assert; |
| | | |
| | | import java.util.List; |
| | | import java.util.stream.Collectors; |
| | | |
| | | /** |
| | | * 用户行为分享 服务实现类 |
| | | * |
| | | * @author peng |
| | | * @since 2025-09-25 |
| | | */ |
| | | @Service |
| | | @RequiredArgsConstructor |
| | | public class ShareActionServiceImpl extends ServiceImpl<ShareActionMapper, ShareAction> implements ShareActionService { |
| | | |
| | | private final ShareActionMapper shareActionMapper; |
| | | |
| | | /** |
| | | * 添加 |
| | | * @param form |
| | | * @return |
| | | */ |
| | | @Override |
| | | public Result add(ShareActionForm form) { |
| | | AuthUser currentUser = UserContext.getCurrentUser(); |
| | | if (currentUser == null) { |
| | | return Result.ok(); |
| | | } |
| | | |
| | | ShareAction entity = ShareActionForm.getEntityByForm(form, null); |
| | | entity.setUserId(currentUser.getId()); |
| | | baseMapper.insert(entity); |
| | | return Result.ok("添加成功").data(entity.getId()); |
| | | } |
| | | |
| | | /** |
| | | * 修改 |
| | | * @param form |
| | | * @return |
| | | */ |
| | | @Override |
| | | public Result update(ShareActionForm form) { |
| | | ShareAction entity = baseMapper.selectById(form.getId()); |
| | | |
| | | // 为空抛IllegalArgumentException,做全局异常处理 |
| | | Assert.notNull(entity, "记录不存在"); |
| | | BeanUtils.copyProperties(form, entity); |
| | | baseMapper.updateById(entity); |
| | | return Result.ok("修改成功"); |
| | | } |
| | | |
| | | /** |
| | | * 批量删除 |
| | | * @param ids |
| | | * @return |
| | | */ |
| | | @Override |
| | | public Result remove(List<String> ids) { |
| | | baseMapper.deleteBatchIds(ids); |
| | | return Result.ok("删除成功"); |
| | | } |
| | | |
| | | /** |
| | | * id删除 |
| | | * @param id |
| | | * @return |
| | | */ |
| | | @Override |
| | | public Result removeById(String id) { |
| | | baseMapper.deleteById(id); |
| | | return Result.ok("删除成功"); |
| | | } |
| | | |
| | | /** |
| | | * 分页查询 |
| | | * @param query |
| | | * @return |
| | | */ |
| | | @Override |
| | | public Result page(ShareActionQuery query) { |
| | | IPage<ShareActionVO> page = PageUtil.getPage(query, ShareActionVO.class); |
| | | baseMapper.getPage(page, query); |
| | | return Result.ok().data(page.getRecords()).total(page.getTotal()); |
| | | } |
| | | |
| | | /** |
| | | * 根据id查找 |
| | | * @param id |
| | | * @return |
| | | */ |
| | | @Override |
| | | public Result detail(String id) { |
| | | ShareActionVO vo = baseMapper.getById(id); |
| | | Assert.notNull(vo, "记录不存在"); |
| | | return Result.ok().data(vo); |
| | | } |
| | | |
| | | /** |
| | | * 列表 |
| | | * @return |
| | | */ |
| | | @Override |
| | | public Result all() { |
| | | List<ShareAction> entities = baseMapper.selectList(null); |
| | | List<ShareActionVO> vos = entities.stream() |
| | | .map(entity -> ShareActionVO.getVoByEntity(entity, null)) |
| | | .collect(Collectors.toList()); |
| | | return Result.ok().data(vos); |
| | | } |
| | | } |
| | |
| | | import cn.lili.modules.member.entity.dos.FootPrint; |
| | | import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
| | | import org.apache.ibatis.annotations.Delete; |
| | | import org.apache.ibatis.annotations.Param; |
| | | import org.apache.ibatis.annotations.Select; |
| | | |
| | | import java.util.Date; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * 浏览历史数据处理层 |
| | |
| | | "WHERE li_foot_print.member_id = ${memberId} AND latest_footprints.id IS NULL; ") |
| | | void deleteLastFootPrint(String memberId); |
| | | |
| | | |
| | | @Select("SELECT " + |
| | | "lfp.ref_id AS GoodsId, " + |
| | | "lg.goods_name AS GoodsName, "+ |
| | | "COUNT(*) AS view_count " + |
| | | "FROM li_foot_print lfp " + |
| | | "LEFT JOIN li_goods lg ON lfp.ref_id = lg.id " + |
| | | "WHERE lfp.delete_flag = 0 " + |
| | | "AND lfp.create_time BETWEEN #{startTime} AND #{endTime} " + |
| | | "AND lfp.view_type = 'goods' " + |
| | | "AND lg.goods_name is not null " + |
| | | "GROUP BY lfp.ref_id " + // 按商品ID分组 |
| | | "ORDER BY view_count DESC " + |
| | | "LIMIT #{currentLimit}" |
| | | ) |
| | | List<Map<String,Object>> selectViewAndCompletionRateCountByDay(Date startTime, |
| | | Date endTime, |
| | | Integer currentLimit); |
| | | |
| | | /** |
| | | * 按视频维度统计:每个视频的总浏览数和完播率 |
| | | * @param startTime 开始时间 |
| | | * @param endTime 结束时间 |
| | | * @return 包含视频ID、名称、总浏览数、完播率的列表 |
| | | */ |
| | | @Select({ |
| | | "SELECT", |
| | | " lfp.ref_id AS video_id, " + |
| | | " lmk.title, " + |
| | | " COUNT(*) AS total_views, " + |
| | | " ROUND(" + |
| | | " IF(COUNT(*) = 0, 0," + |
| | | " (SUM(" + |
| | | " CASE WHEN ( " + |
| | | " CAST(lfp.play_at AS DECIMAL(10,3)) >= CAST(lmk.video_duration AS DECIMAL(10,3)) " + |
| | | " OR " + |
| | | " CAST(lfp.play_at AS DECIMAL(10,3)) / CAST(lmk.video_duration AS DECIMAL(10,3)) > 0.9 " + |
| | | " ) THEN 1 " + |
| | | " ELSE 0 " + |
| | | " END " + |
| | | " ) / COUNT(*)) * 100 " + |
| | | " ), 2 " + |
| | | " ) AS complete_rate " + |
| | | "FROM li_foot_print lfp" + |
| | | " LEFT JOIN lmk_video lmk ON lfp.ref_id = lmk.id " + // 按实际关联字段调整 |
| | | "WHERE " + |
| | | " lfp.delete_flag = 0", |
| | | " AND lfp.view_type = 'video' " +// 只统计视频类型 |
| | | " AND lfp.create_time BETWEEN #{startTime} AND #{endTime} " + |
| | | " AND lmk.video_duration > 0 " + |
| | | " AND ref_id IS NOT NULL AND lmk.title IS NOT NULL "+ |
| | | "GROUP BY lfp.ref_id "+ |
| | | "ORDER BY total_views DESC " + |
| | | "LIMIT #{currentLimit}" |
| | | }) |
| | | List<Map<String, Object>> selectEachVideoStats( |
| | | Date startTime, |
| | | Date endTime, |
| | | Integer currentLimit |
| | | ); |
| | | |
| | | } |
| | |
| | | import cn.lili.modules.member.entity.dos.FootPrint; |
| | | import cn.lili.modules.member.entity.dto.FootPrintQueryParams; |
| | | import cn.lili.modules.search.entity.dos.EsGoodsIndex; |
| | | import cn.lili.modules.statistics.entity.dto.StatisticsQueryParam; |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | | import com.baomidou.mybatisplus.extension.service.IService; |
| | | |
| | |
| | | */ |
| | | long getFootprintNum(); |
| | | |
| | | Result getViewAndCompletionRateCount(StatisticsQueryParam queryParam); |
| | | } |
| | |
| | | |
| | | import cn.lili.base.Result; |
| | | import cn.lili.common.security.context.UserContext; |
| | | import cn.lili.common.utils.StringUtils; |
| | | import cn.lili.modules.goods.entity.dos.GoodsSku; |
| | | import cn.lili.modules.goods.service.GoodsSkuService; |
| | | import cn.lili.modules.lmk.domain.query.FootPrintQuery; |
| | | import cn.lili.modules.lmk.domain.vo.SimpleVideoTagVO; |
| | | import cn.lili.modules.lmk.domain.vo.VideoFootInfoVo; |
| | | import cn.lili.modules.lmk.domain.vo.VideoFootVO; |
| | | import cn.lili.modules.lmk.domain.vo.VideoVO; |
| | | import cn.lili.modules.lmk.domain.vo.*; |
| | | import cn.lili.modules.lmk.mapper.VideoMapper; |
| | | import cn.lili.modules.member.entity.dos.FootPrint; |
| | | import cn.lili.modules.member.entity.dto.FootPrintQueryParams; |
| | | import cn.lili.modules.member.mapper.FootprintMapper; |
| | | import cn.lili.modules.member.service.FootprintService; |
| | | import cn.lili.modules.search.entity.dos.EsGoodsIndex; |
| | | import cn.lili.modules.statistics.entity.dto.StatisticsQueryParam; |
| | | import cn.lili.mybatis.util.PageUtil; |
| | | import cn.lili.utils.COSUtil; |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | |
| | | |
| | | import java.math.BigDecimal; |
| | | import java.math.RoundingMode; |
| | | import java.text.SimpleDateFormat; |
| | | import java.util.*; |
| | | import java.util.stream.Collectors; |
| | | import java.util.stream.IntStream; |
| | |
| | | return this.count(lambdaQueryWrapper); |
| | | } |
| | | |
| | | @Override |
| | | public Result getViewAndCompletionRateCount(StatisticsQueryParam queryParam) { |
| | | Date startTime = null; |
| | | Date endTime = new Date(); // 结束时间默认是当前时间 |
| | | List<String> dateList = new ArrayList<>(); |
| | | |
| | | Calendar calendar = Calendar.getInstance(); // 用于日期计算的日历实例 |
| | | SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); |
| | | int days = 0; |
| | | switch (queryParam.getSearchType()) { |
| | | case "TODAY": |
| | | // 今天:从今天0点到现在 |
| | | calendar.setTime(new Date()); // 重置为当前时间 |
| | | calendar.set(Calendar.HOUR_OF_DAY, 0); // 小时设为0(24小时制) |
| | | calendar.set(Calendar.MINUTE, 0); // 分钟设为0 |
| | | calendar.set(Calendar.SECOND, 0); // 秒设为0 |
| | | calendar.set(Calendar.MILLISECOND, 0); // 毫秒设为0 |
| | | startTime = calendar.getTime(); // 得到今天0点的Date对象 |
| | | dateList.add(sdf.format(startTime)); |
| | | break; |
| | | case "YESTERDAY": |
| | | // 昨天:从昨天0点到昨天23:59:59.999 |
| | | calendar.setTime(new Date()); |
| | | calendar.add(Calendar.DATE, -1); // 日期减1天(变为昨天) |
| | | |
| | | // 设置昨天0点 |
| | | calendar.set(Calendar.HOUR_OF_DAY, 0); |
| | | calendar.set(Calendar.MINUTE, 0); |
| | | calendar.set(Calendar.SECOND, 0); |
| | | calendar.set(Calendar.MILLISECOND, 0); |
| | | startTime = calendar.getTime(); |
| | | |
| | | // 设置昨天23:59:59.999 |
| | | calendar.set(Calendar.HOUR_OF_DAY, 23); |
| | | calendar.set(Calendar.MINUTE, 59); |
| | | calendar.set(Calendar.SECOND, 59); |
| | | calendar.set(Calendar.MILLISECOND, 999); |
| | | endTime = calendar.getTime(); |
| | | |
| | | dateList.add(sdf.format(startTime)); |
| | | break; |
| | | case "LAST_SEVEN": |
| | | // 过去七天:从7天前0点到现在(含今天共7天) |
| | | calendar.setTime(new Date()); |
| | | calendar.add(Calendar.DATE, -6); // 日期减6天(7天前的今天) |
| | | |
| | | // 设置7天前0点 |
| | | calendar.set(Calendar.HOUR_OF_DAY, 0); |
| | | calendar.set(Calendar.MINUTE, 0); |
| | | calendar.set(Calendar.SECOND, 0); |
| | | calendar.set(Calendar.MILLISECOND, 0); |
| | | startTime = calendar.getTime(); |
| | | |
| | | days = 7; |
| | | // 循环生成7天的日期字符串 |
| | | Calendar tempCalendar = Calendar.getInstance(); |
| | | tempCalendar.setTime(startTime); |
| | | for (int i = 0; i < days; i++) { |
| | | dateList.add(sdf.format(tempCalendar.getTime())); |
| | | tempCalendar.add(Calendar.DATE, 1); // 每天累加1天 |
| | | } |
| | | break; |
| | | case "LAST_THIRTY": |
| | | // 过去30天:从30天前0点到现在(含今天共30天) |
| | | calendar.setTime(new Date()); |
| | | calendar.add(Calendar.DATE, -29); // 日期减29天(30天前的今天) |
| | | |
| | | // 设置30天前0点 |
| | | calendar.set(Calendar.HOUR_OF_DAY, 0); |
| | | calendar.set(Calendar.MINUTE, 0); |
| | | calendar.set(Calendar.SECOND, 0); |
| | | calendar.set(Calendar.MILLISECOND, 0); |
| | | startTime = calendar.getTime(); |
| | | |
| | | days = 30; |
| | | // 循环生成30天的日期字符串 |
| | | Calendar tempCalendar30 = Calendar.getInstance(); |
| | | tempCalendar30.setTime(startTime); |
| | | for (int i = 0; i < days; i++) { |
| | | dateList.add(sdf.format(tempCalendar30.getTime())); |
| | | tempCalendar30.add(Calendar.DATE, 1); // 每天累加1天 |
| | | } |
| | | break; |
| | | default: |
| | | return Result.error("不支持的时间范围类型"); |
| | | } |
| | | if ("goods".equals(queryParam.getCurrentType())){ |
| | | List<Map<String, Object>> maps = baseMapper.selectViewAndCompletionRateCountByDay(startTime, endTime,queryParam.getCurrentLimit()); |
| | | Map<String,Long> viewPrintMap = maps.stream() |
| | | .collect(Collectors.toMap( |
| | | map -> { |
| | | String goodsId = Objects.toString(map.get("GoodsId"), ""); // 空值处理 |
| | | String goodsName = Objects.toString(map.get("GoodsName"), ""); // 空值处理 |
| | | return goodsName + " | " + goodsId; // 用|分隔,方便后续拆分 |
| | | }, |
| | | map-> Long.valueOf(map.get("view_count").toString()), |
| | | (existing, replacement) -> existing, |
| | | LinkedHashMap::new // 指定使用 LinkedHashMap,保留插入顺序 |
| | | )); |
| | | List<String> yData = new ArrayList<>(); |
| | | List<Long> xData = new ArrayList<>(); |
| | | |
| | | for (Map.Entry<String, Long> entry : viewPrintMap.entrySet()){ |
| | | yData.add(entry.getKey()); |
| | | xData.add(entry.getValue()); |
| | | } |
| | | Map<String,Object> data = new HashMap<>(); |
| | | data.put("yData", yData); |
| | | data.put("xData", xData); |
| | | return Result.ok().data(data); |
| | | }else{ |
| | | List<Map<String, Object>> maps = baseMapper.selectEachVideoStats(startTime, endTime,queryParam.getCurrentLimit()); |
| | | Map<String, VideoViewCompletionRateVO> viewPrintMap = maps.stream() |
| | | .collect(Collectors.toMap( |
| | | map -> { |
| | | String videoId = Objects.toString(map.get("video_id"), ""); // 空值处理 |
| | | String videoName = Objects.toString(map.get("title"), ""); // 空值处理 |
| | | return videoName + " | " + videoId; // 用|分隔,方便后续拆分 |
| | | }, |
| | | map-> { |
| | | VideoViewCompletionRateVO vo = new VideoViewCompletionRateVO(); |
| | | vo.setTotal_views(Long.valueOf(map.get("total_views").toString())); |
| | | vo.setComplete_rate(map.get("complete_rate").toString()); |
| | | return vo; |
| | | }, |
| | | (existing, replacement) -> existing, |
| | | LinkedHashMap::new // 指定使用 LinkedHashMap,保留插入顺序 |
| | | )); |
| | | List<String> yData = new ArrayList<>(); |
| | | List<Long> xData = new ArrayList<>(); |
| | | List<String> rateData = new ArrayList<>(); |
| | | |
| | | for (Map.Entry<String, VideoViewCompletionRateVO> entry : viewPrintMap.entrySet()){ |
| | | yData.add(entry.getKey()); |
| | | xData.add(entry.getValue().getTotal_views()); |
| | | rateData.add(entry.getValue().getComplete_rate()); |
| | | } |
| | | Map<String,Object> data = new HashMap<>(); |
| | | data.put("yData", yData); |
| | | data.put("xData", xData); |
| | | data.put("rateData", rateData); |
| | | return Result.ok().data(data); |
| | | } |
| | | |
| | | } |
| | | |
| | | |
| | | } |
| | |
| | | import cn.lili.common.utils.BeanUtil; |
| | | import cn.lili.common.utils.CurrencyUtil; |
| | | import cn.lili.common.utils.SnowFlake; |
| | | import cn.lili.common.utils.StringUtils; |
| | | import cn.lili.modules.order.aftersale.aop.AfterSaleLogPoint; |
| | | import cn.lili.modules.order.aftersale.entity.dos.AfterSale; |
| | | import cn.lili.modules.order.aftersale.entity.dto.AfterSaleDTO; |
| | |
| | | afterSaleApplyVO.setReturnGoods(false); |
| | | } else { |
| | | afterSaleApplyVO.setReturnMoney(true); |
| | | afterSaleApplyVO.setReturnGoods(true); |
| | | |
| | | if(StringUtils.isNotBlank(order.getOrderStatus()) && DeliverStatusEnum.UNDELIVERED.name().equals(order.getOrderStatus())){ |
| | | afterSaleApplyVO.setReturnGoods(false); |
| | | }else { |
| | | afterSaleApplyVO.setReturnGoods(true); |
| | | } |
| | | |
| | | } |
| | | |
| | | afterSaleApplyVO.setAccountType(order.getPaymentMethod()); |
| | |
| | | |
| | | private String couponFlag; |
| | | |
| | | private String storeSelectId; |
| | | |
| | | public <T> QueryWrapper<T> queryWrapper() { |
| | | AuthUser currentUser = UserContext.getCurrentUser(); |
| | |
| | | if (CharSequenceUtil.isNotEmpty(keywords)) { |
| | | wrapper.and(keyWrapper -> keyWrapper.like("o.sn", keywords).or().like("oi.goods_name", keywords)); |
| | | } |
| | | //更具角色查询的 |
| | | if (currentUser != null) { |
| | | //按卖家查询 |
| | | wrapper.eq(CharSequenceUtil.equals(currentUser.getRole().name(), UserEnums.STORE.name()), "o.store_id", currentUser.getStoreId()); |
| | |
| | | wrapper.eq(CharSequenceUtil.equals(currentUser.getRole().name(), UserEnums.MEMBER.name()) && memberId == null, "o.member_id", currentUser.getId()); |
| | | |
| | | } |
| | | //按下拉框选择查询 |
| | | wrapper.eq(CharSequenceUtil.isNotEmpty(storeSelectId), "o.store_id", storeSelectId); |
| | | |
| | | //按照买家查询 |
| | | wrapper.like(CharSequenceUtil.isNotEmpty(memberId), "o.member_id", memberId); |
| | | |
| | |
| | | import org.apache.ibatis.annotations.Select; |
| | | import org.apache.ibatis.annotations.Update; |
| | | |
| | | import java.util.Date; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * 订单数据处理层 |
| | |
| | | List<Order> queryListByParams(@Param(Constants.WRAPPER) Wrapper<Order> queryWrapper); |
| | | |
| | | |
| | | @Select("SELECT " + |
| | | " DATE(create_time) AS day, " + |
| | | " COUNT(*) AS count " + |
| | | " FROM" + |
| | | " li_order o" + |
| | | " WHERE " + |
| | | " o.create_time BETWEEN #{startTime} AND #{endTime} " + |
| | | " GROUP BY" + |
| | | " day " + |
| | | " ORDER BY " + |
| | | " day ASC") |
| | | List<Map<String, Object>> selectOrderCountByDay(Date startTime, Date endTime); |
| | | |
| | | @Select("SELECT " + |
| | | " DATE(create_time) AS day, " + |
| | | " HOUR(create_time) AS hour," + |
| | | " COUNT(*) AS count " + |
| | | " FROM" + |
| | | " li_order o" + |
| | | " WHERE " + |
| | | " o.create_time BETWEEN #{startTime} AND #{endTime} " + |
| | | " GROUP BY" + |
| | | " day " + |
| | | " ORDER BY " + |
| | | " day , hour ASC") |
| | | List<Map<String, Object>> selectOrderTimePeriod(Date startTime, Date endTime); |
| | | } |
| | |
| | | package cn.lili.modules.order.order.service; |
| | | |
| | | import cn.lili.base.Result; |
| | | import cn.lili.common.vo.ResultMessage; |
| | | import cn.lili.modules.lmk.domain.vo.OrderCountVO; |
| | | import cn.lili.modules.member.entity.dto.MemberAddressDTO; |
| | |
| | | import cn.lili.modules.order.order.entity.vo.OrderSimpleVO; |
| | | import cn.lili.modules.order.order.entity.vo.OrderSimpleXcxVO; |
| | | import cn.lili.modules.order.order.entity.vo.PaymentLog; |
| | | import cn.lili.modules.statistics.entity.dto.StatisticsQueryParam; |
| | | import cn.lili.modules.system.entity.vo.Traces; |
| | | import com.baomidou.mybatisplus.core.conditions.Wrapper; |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | |
| | | Order updateSellerRemark(String orderSn, String sellerRemark); |
| | | |
| | | |
| | | /** |
| | | * 获得每日订单统计数据 订单统计折线图用 |
| | | * @param queryParam |
| | | * @return |
| | | */ |
| | | Result getOrderCount(StatisticsQueryParam queryParam); |
| | | |
| | | Result getOrderTimePeriod(StatisticsQueryParam queryParam); |
| | | } |
| | |
| | | import cn.hutool.poi.excel.ExcelReader; |
| | | import cn.hutool.poi.excel.ExcelUtil; |
| | | import cn.hutool.poi.excel.ExcelWriter; |
| | | import cn.lili.base.Result; |
| | | import cn.lili.common.enums.ClientTypeEnum; |
| | | import cn.lili.common.enums.PromotionTypeEnum; |
| | | import cn.lili.common.enums.ResultCode; |
| | |
| | | import cn.lili.modules.promotion.entity.dos.Pintuan; |
| | | import cn.lili.modules.promotion.service.CouponService; |
| | | import cn.lili.modules.promotion.service.PintuanService; |
| | | import cn.lili.modules.statistics.entity.dto.StatisticsQueryParam; |
| | | import cn.lili.modules.store.entity.dto.StoreDeliverGoodsAddressDTO; |
| | | import cn.lili.modules.store.service.StoreDetailService; |
| | | import cn.lili.modules.system.aspect.annotation.SystemLogPoint; |
| | |
| | | import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | | import com.baomidou.mybatisplus.core.toolkit.Wrappers; |
| | | import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper; |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | import io.reactivex.rxjava3.core.Maybe; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.apache.poi.ss.usermodel.Cell; |
| | | import org.apache.poi.ss.usermodel.Row; |
| | |
| | | import java.io.InputStream; |
| | | import java.math.BigDecimal; |
| | | import java.net.URLEncoder; |
| | | import java.text.SimpleDateFormat; |
| | | import java.time.LocalDate; |
| | | import java.time.LocalDateTime; |
| | | import java.time.LocalTime; |
| | | import java.util.*; |
| | | import java.util.concurrent.TimeUnit; |
| | | import java.util.stream.Collectors; |
| | |
| | | return order; |
| | | } |
| | | |
| | | @Override |
| | | public Result getOrderCount(StatisticsQueryParam queryParam) { |
| | | Date startTime = null; |
| | | Date endTime = new Date(); // 结束时间默认是当前时间 |
| | | List<String> dateList = new ArrayList<>(); |
| | | |
| | | Calendar calendar = Calendar.getInstance(); // 用于日期计算的日历实例 |
| | | SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); |
| | | int days = 0; |
| | | switch (queryParam.getSearchType()) { |
| | | case "TODAY": |
| | | // 今天:从今天0点到现在 |
| | | calendar.setTime(new Date()); // 重置为当前时间 |
| | | calendar.set(Calendar.HOUR_OF_DAY, 0); // 小时设为0(24小时制) |
| | | calendar.set(Calendar.MINUTE, 0); // 分钟设为0 |
| | | calendar.set(Calendar.SECOND, 0); // 秒设为0 |
| | | calendar.set(Calendar.MILLISECOND, 0); // 毫秒设为0 |
| | | startTime = calendar.getTime(); // 得到今天0点的Date对象 |
| | | dateList.add(sdf.format(startTime)); |
| | | break; |
| | | case "YESTERDAY": |
| | | // 昨天:从昨天0点到昨天23:59:59.999 |
| | | calendar.setTime(new Date()); |
| | | calendar.add(Calendar.DATE, -1); // 日期减1天(变为昨天) |
| | | |
| | | // 设置昨天0点 |
| | | calendar.set(Calendar.HOUR_OF_DAY, 0); |
| | | calendar.set(Calendar.MINUTE, 0); |
| | | calendar.set(Calendar.SECOND, 0); |
| | | calendar.set(Calendar.MILLISECOND, 0); |
| | | startTime = calendar.getTime(); |
| | | |
| | | // 设置昨天23:59:59.999 |
| | | calendar.set(Calendar.HOUR_OF_DAY, 23); |
| | | calendar.set(Calendar.MINUTE, 59); |
| | | calendar.set(Calendar.SECOND, 59); |
| | | calendar.set(Calendar.MILLISECOND, 999); |
| | | endTime = calendar.getTime(); |
| | | |
| | | dateList.add(sdf.format(startTime)); |
| | | break; |
| | | case "LAST_SEVEN": |
| | | // 过去七天:从7天前0点到现在(含今天共7天) |
| | | calendar.setTime(new Date()); |
| | | calendar.add(Calendar.DATE, -6); // 日期减6天(7天前的今天) |
| | | |
| | | // 设置7天前0点 |
| | | calendar.set(Calendar.HOUR_OF_DAY, 0); |
| | | calendar.set(Calendar.MINUTE, 0); |
| | | calendar.set(Calendar.SECOND, 0); |
| | | calendar.set(Calendar.MILLISECOND, 0); |
| | | startTime = calendar.getTime(); |
| | | |
| | | days = 7; |
| | | // 循环生成7天的日期字符串 |
| | | Calendar tempCalendar = Calendar.getInstance(); |
| | | tempCalendar.setTime(startTime); |
| | | for (int i = 0; i < days; i++) { |
| | | dateList.add(sdf.format(tempCalendar.getTime())); |
| | | tempCalendar.add(Calendar.DATE, 1); // 每天累加1天 |
| | | } |
| | | break; |
| | | case "LAST_THIRTY": |
| | | // 过去30天:从30天前0点到现在(含今天共30天) |
| | | calendar.setTime(new Date()); |
| | | calendar.add(Calendar.DATE, -29); // 日期减29天(30天前的今天) |
| | | |
| | | // 设置30天前0点 |
| | | calendar.set(Calendar.HOUR_OF_DAY, 0); |
| | | calendar.set(Calendar.MINUTE, 0); |
| | | calendar.set(Calendar.SECOND, 0); |
| | | calendar.set(Calendar.MILLISECOND, 0); |
| | | startTime = calendar.getTime(); |
| | | |
| | | days = 30; |
| | | // 循环生成30天的日期字符串 |
| | | Calendar tempCalendar30 = Calendar.getInstance(); |
| | | tempCalendar30.setTime(startTime); |
| | | for (int i = 0; i < days; i++) { |
| | | dateList.add(sdf.format(tempCalendar30.getTime())); |
| | | tempCalendar30.add(Calendar.DATE, 1); // 每天累加1天 |
| | | } |
| | | break; |
| | | default: |
| | | return Result.error("不支持的时间范围类型"); |
| | | } |
| | | List<Map<String, Object>> maps = baseMapper.selectOrderCountByDay(startTime,endTime); |
| | | |
| | | Map<String, Long> dayCountMap = maps.stream() |
| | | .collect(Collectors.toMap( |
| | | map -> map.get("day").toString(), // 日期字符串(如2023-09-19) |
| | | map -> Long.valueOf(map.get("count").toString()) // 订单数量 |
| | | )); |
| | | |
| | | List<Long> orderCounts = new ArrayList<>(); |
| | | for (String date : dateList) { |
| | | // 核心:存在则取查询结果,不存在则补0 |
| | | orderCounts.add(dayCountMap.getOrDefault(date, 0L)); |
| | | } |
| | | |
| | | |
| | | return Result.ok().data(orderCounts); |
| | | } |
| | | |
| | | @Override |
| | | public Result getOrderTimePeriod(StatisticsQueryParam queryParam) { |
| | | Date startTime = null; |
| | | Date endTime = new Date(); // 结束时间默认是当前时间 |
| | | List<String> dateList = new ArrayList<>(); |
| | | |
| | | Calendar calendar = Calendar.getInstance(); // 用于日期计算的日历实例 |
| | | for (int i =0;i<=24;i++){ |
| | | dateList.add(i + "点"); |
| | | } |
| | | switch (queryParam.getSearchType()) { |
| | | case "TODAY": |
| | | // 今天:从今天0点到现在 |
| | | calendar.setTime(new Date()); // 重置为当前时间 |
| | | calendar.set(Calendar.HOUR_OF_DAY, 0); // 小时设为0(24小时制) |
| | | calendar.set(Calendar.MINUTE, 0); // 分钟设为0 |
| | | calendar.set(Calendar.SECOND, 0); // 秒设为0 |
| | | calendar.set(Calendar.MILLISECOND, 0); // 毫秒设为0 |
| | | startTime = calendar.getTime(); // 得到今天0点的Date对象 |
| | | break; |
| | | case "YESTERDAY": |
| | | // 昨天:从昨天0点到昨天23:59:59.999 |
| | | calendar.setTime(new Date()); |
| | | calendar.add(Calendar.DATE, -1); // 日期减1天(变为昨天) |
| | | |
| | | // 设置昨天0点 |
| | | calendar.set(Calendar.HOUR_OF_DAY, 0); |
| | | calendar.set(Calendar.MINUTE, 0); |
| | | calendar.set(Calendar.SECOND, 0); |
| | | calendar.set(Calendar.MILLISECOND, 0); |
| | | startTime = calendar.getTime(); |
| | | |
| | | // 设置昨天23:59:59.999 |
| | | calendar.set(Calendar.HOUR_OF_DAY, 23); |
| | | calendar.set(Calendar.MINUTE, 59); |
| | | calendar.set(Calendar.SECOND, 59); |
| | | calendar.set(Calendar.MILLISECOND, 999); |
| | | endTime = calendar.getTime(); |
| | | |
| | | break; |
| | | case "LAST_SEVEN": |
| | | // 过去七天:从7天前0点到现在(含今天共7天) |
| | | calendar.setTime(new Date()); |
| | | calendar.add(Calendar.DATE, -6); // 日期减6天(7天前的今天) |
| | | |
| | | // 设置7天前0点 |
| | | calendar.set(Calendar.HOUR_OF_DAY, 0); |
| | | calendar.set(Calendar.MINUTE, 0); |
| | | calendar.set(Calendar.SECOND, 0); |
| | | calendar.set(Calendar.MILLISECOND, 0); |
| | | startTime = calendar.getTime(); |
| | | |
| | | break; |
| | | case "LAST_THIRTY": |
| | | // 过去30天:从30天前0点到现在(含今天共30天) |
| | | calendar.setTime(new Date()); |
| | | calendar.add(Calendar.DATE, -29); // 日期减29天(30天前的今天) |
| | | |
| | | // 设置30天前0点 |
| | | calendar.set(Calendar.HOUR_OF_DAY, 0); |
| | | calendar.set(Calendar.MINUTE, 0); |
| | | calendar.set(Calendar.SECOND, 0); |
| | | calendar.set(Calendar.MILLISECOND, 0); |
| | | startTime = calendar.getTime(); |
| | | |
| | | break; |
| | | default: |
| | | return Result.error("不支持的时间范围类型"); |
| | | } |
| | | List<Map<String, Object>> maps = baseMapper.selectOrderTimePeriod(startTime,endTime); |
| | | |
| | | Map<String, Long> dayCountMap = maps.stream() |
| | | .collect(Collectors.toMap( |
| | | map -> map.get("day").toString(), // 日期字符串(如2023-09-19) |
| | | map -> Long.valueOf(map.get("count").toString()) // 订单数量 |
| | | )); |
| | | |
| | | List<Long> orderCounts = new ArrayList<>(); |
| | | for (String date : dateList) { |
| | | // 核心:存在则取查询结果,不存在则补0 |
| | | orderCounts.add(dayCountMap.getOrDefault(date, 0L)); |
| | | } |
| | | |
| | | |
| | | return Result.ok().data(orderCounts); |
| | | } |
| | | |
| | | /** |
| | | * 虚拟成团 |
| | | * |
| | |
| | | import cn.lili.modules.search.service.EsGoodsSearchService; |
| | | import cn.lili.rocketmq.RocketmqSendCallbackBuilder; |
| | | import cn.lili.rocketmq.tags.GoodsTagsEnum; |
| | | import com.alibaba.fastjson.JSON; |
| | | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | |
| | | if (CollUtil.isNotEmpty(promotionGoods)) { |
| | | esGoodsIndex.setPromotionMapJson(JSONUtil.toJsonStr(promotionService.wrapperPromotionMapList(promotionGoods))); |
| | | } |
| | | |
| | | log.info("构建出es的索引信息为{}", JSON.toJSONString(esGoodsIndex)); |
| | | esGoodsIndex.setGoodsSort(goodsSku.getGoodsSort()); |
| | | esGoodsIndices.add(esGoodsIndex); |
| | | //库存锁是在redis做的,所以生成索引,同时更新一下redis中的库存数量 |
| | | cache.put(GoodsSkuService.getStockCacheKey(goodsSku.getId()), goodsSku.getQuantity()); |
| | |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Data; |
| | | |
| | | import cn.lili.modules.lmk.enums.general.StatisticsSearchTypeEnum; |
| | | /** |
| | | * 统计查询参数 |
| | | * |
| | |
| | | public class StatisticsQueryParam { |
| | | |
| | | @ApiModelProperty(value = "快捷搜索", allowableValues = "TODAY, YESTERDAY, LAST_SEVEN, LAST_THIRTY") |
| | | /** |
| | | * @see StatisticsSearchTypeEnum |
| | | */ |
| | | private String searchType; |
| | | |
| | | @ApiModelProperty(value = "类型:年(YEAR)、月(MONTH)") |
| | |
| | | @ApiModelProperty(value = "店铺ID") |
| | | private String storeId; |
| | | |
| | | @ApiModelProperty(value = "类型:商品goods 、视频video") |
| | | private String currentType; |
| | | |
| | | @ApiModelProperty(value = "显示排名:10,20,30") |
| | | private Integer currentLimit; |
| | | |
| | | } |
| | |
| | | //获取当前时间 |
| | | Calendar calendar = Calendar.getInstance(); |
| | | |
| | | |
| | | calendar.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.DAY_OF_MONTH), 0, 0, 0); |
| | | calendar.set(Calendar.MILLISECOND, 0); |
| | | //如果是今天的统计,则从redis 中拿,否则从数据库中拿 |
New file |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> |
| | | <mapper namespace="cn.lili.modules.lmk.mapper.ShareActionMapper"> |
| | | |
| | | <!-- 通用查询映射结果 --> |
| | | <resultMap id="BaseResultMap" type="cn.lili.modules.lmk.domain.vo.ShareActionVO"> |
| | | <id column="id" property="id"/> |
| | | <result column="user_id" property="userId" /> |
| | | <result column="share_option" property="shareOption" /> |
| | | <result column="page_code" property="pageCode" /> |
| | | <result column="page_type" property="pageType" /> |
| | | <result column="pid" property="pid" /> |
| | | </resultMap> |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | <select id="getById" resultMap="BaseResultMap"> |
| | | SELECT |
| | | LSA.user_id, |
| | | LSA.share_option, |
| | | LSA.page_code, |
| | | LSA.page_type, |
| | | LSA.pid, |
| | | LSA.id |
| | | FROM |
| | | lmk_share_action LSA |
| | | WHERE |
| | | LSA.id = #{id} AND LSA.delete_flag = 0 |
| | | </select> |
| | | |
| | | |
| | | <select id="getPage" resultMap="BaseResultMap"> |
| | | SELECT |
| | | LSA.user_id, |
| | | LSA.share_option, |
| | | LSA.page_code, |
| | | LSA.page_type, |
| | | LSA.pid, |
| | | LSA.id |
| | | FROM |
| | | lmk_share_action LSA |
| | | WHERE |
| | | LSA.delete_flag = 0 |
| | | </select> |
| | | |
| | | </mapper> |
New file |
| | |
| | | package cn.lili.controller.lmk; |
| | | |
| | | |
| | | import cn.lili.base.Result; |
| | | import cn.lili.common.enums.ResultUtil; |
| | | import cn.lili.common.vo.ResultMessage; |
| | | import cn.lili.modules.lmk.domain.vo.PvUvVO; |
| | | import cn.lili.modules.lmk.enums.general.StatisticsSearchTypeEnum; |
| | | import cn.lili.modules.member.service.FootprintService; |
| | | import cn.lili.modules.order.order.service.OrderService; |
| | | import cn.lili.modules.statistics.entity.dto.StatisticsQueryParam; |
| | | import cn.lili.modules.statistics.entity.vo.PlatformViewVO; |
| | | import cn.lili.modules.statistics.service.PlatformViewService; |
| | | import io.swagger.annotations.ApiOperation; |
| | | import lombok.AllArgsConstructor; |
| | | import org.springframework.web.bind.annotation.GetMapping; |
| | | import org.springframework.web.bind.annotation.RequestMapping; |
| | | import org.springframework.web.bind.annotation.RestController; |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * lmk-shop-java |
| | | * 统计数据控制层 |
| | | * |
| | | * @author : zxl |
| | | * @date : 2025-09-16 16:36 |
| | | **/ |
| | | @RestController |
| | | @AllArgsConstructor |
| | | @RequestMapping("/manager/lmk/statistics") |
| | | public class StatisticsController { |
| | | private final OrderService orderService; |
| | | |
| | | private final FootprintService footprintService; |
| | | |
| | | @ApiOperation(value = "获取pv、uv流量数据 表单获取") |
| | | @GetMapping("/pvUv") |
| | | public Result getPVUVData(StatisticsQueryParam queryParam) { |
| | | //TODO 获得 pv/uv数据 |
| | | PvUvVO pvUvVO = new PvUvVO(); |
| | | List<Long> pvData = new ArrayList<>(); |
| | | List<Long> uvData = new ArrayList<>(); |
| | | switch (queryParam.getSearchType()) { |
| | | case "TODAY": |
| | | // 今天的数据:添加1 |
| | | pvData.add(1L); |
| | | uvData.add(9L); |
| | | break; |
| | | |
| | | case "YESTERDAY": |
| | | // 明天的数据:添加1 |
| | | pvData.add(1L); |
| | | uvData.add(10L); |
| | | break; |
| | | |
| | | case "LAST_SEVEN": |
| | | // 过去七天的数据:添加1, 2, 3 |
| | | for(int i =1;i<=7;i++){ |
| | | pvData.add((long) i); |
| | | uvData.add((long) i+7); |
| | | } |
| | | |
| | | break; |
| | | |
| | | case "LAST_THIRTY": |
| | | // 过去一个月的数据:可以根据需要自定义,这里示例添加1到5 |
| | | for(int i =1;i<=30;i++){ |
| | | pvData.add((long) i); |
| | | uvData.add((long) i+7); |
| | | } |
| | | break; |
| | | |
| | | } |
| | | pvUvVO.setPvData(pvData); |
| | | pvUvVO.setUvData(uvData); |
| | | return Result.ok().data(pvUvVO); |
| | | } |
| | | |
| | | @GetMapping("/orderCount") |
| | | public Result getOrderCount(StatisticsQueryParam queryParam) { |
| | | return orderService.getOrderCount(queryParam); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 视频/商品 完播率和浏览量统计 |
| | | * @param queryParam |
| | | * @return |
| | | */ |
| | | @GetMapping("/viewAndCompletionRateCount") |
| | | public Result getViewAndCompletionRateCount(StatisticsQueryParam queryParam) { |
| | | return footprintService.getViewAndCompletionRateCount(queryParam); |
| | | } |
| | | |
| | | |
| | | @GetMapping("/orderTimePeriod") |
| | | public Result getOrderTimePeriod(StatisticsQueryParam queryParam) { |
| | | return orderService.getOrderTimePeriod(queryParam); |
| | | |
| | | } |
| | | } |
| | |
| | | |
| | | import cn.hutool.core.convert.Convert; |
| | | import cn.hutool.core.util.NumberUtil; |
| | | import cn.lili.base.Result; |
| | | import cn.lili.common.aop.annotation.PreventDuplicateSubmissions; |
| | | import cn.lili.common.context.ThreadContextHolder; |
| | | import cn.lili.common.enums.ResultCode; |
| | |
| | | import cn.lili.common.utils.StringUtils; |
| | | import cn.lili.common.vo.ResultMessage; |
| | | import cn.lili.modules.lmk.domain.vo.OrderCountVO; |
| | | import cn.lili.modules.lmk.domain.vo.SelectVO; |
| | | import cn.lili.modules.member.entity.dto.MemberAddressDTO; |
| | | import cn.lili.modules.order.order.entity.dos.Order; |
| | | import cn.lili.modules.order.order.entity.dto.OrderExportDTO; |
| | |
| | | import cn.lili.modules.order.order.service.OrderPackageService; |
| | | import cn.lili.modules.order.order.service.OrderPriceService; |
| | | import cn.lili.modules.order.order.service.OrderService; |
| | | import cn.lili.modules.store.entity.dos.Store; |
| | | import cn.lili.modules.store.entity.enums.StoreStatusEnum; |
| | | import cn.lili.modules.store.mapper.StoreMapper; |
| | | import cn.lili.utils.COSUtil; |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | | import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper; |
| | | import io.swagger.annotations.*; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.web.bind.annotation.*; |
| | |
| | | import javax.validation.Valid; |
| | | import javax.validation.constraints.NotBlank; |
| | | import javax.validation.constraints.NotNull; |
| | | import java.util.ArrayList; |
| | | import java.util.List; |
| | | |
| | | /** |
| | |
| | | @RequestMapping("/manager/order/order") |
| | | @Api(tags = "管理端,订单API") |
| | | public class OrderManagerController { |
| | | @Autowired |
| | | private StoreMapper storeMapper; |
| | | |
| | | /** |
| | | * 订单 |
| | |
| | | @Autowired |
| | | private COSUtil cosUtil; |
| | | |
| | | @ApiModelProperty(value = "店铺下拉") |
| | | @GetMapping("/storeSelect") |
| | | public ResultMessage<List<SelectVO>> getStoreSelect(){ |
| | | List<Store> storeList = |
| | | new LambdaQueryChainWrapper<>(storeMapper) |
| | | .eq(Store::getDeleteFlag,Boolean.FALSE) |
| | | .eq(Store::getStoreDisable, StoreStatusEnum.OPEN.name()) |
| | | .list(); |
| | | List<SelectVO> selectVOS = new ArrayList<>(); |
| | | for (Store store : storeList){ |
| | | SelectVO vo = new SelectVO(); |
| | | vo.setId(store.getId()); |
| | | vo.setLabel(store.getStoreName()); |
| | | selectVOS.add(vo); |
| | | } |
| | | return ResultUtil.data(selectVOS); |
| | | |
| | | } |
| | | |
| | | @ApiOperation(value = "查询订单列表分页") |
| | | @GetMapping |
| | | public ResultMessage<IPage<OrderSimpleVO>> queryMineOrder(OrderSearchParams orderSearchParams) { |