用户 / 订单 / 商品 管理
This commit is contained in:
@@ -0,0 +1,36 @@
|
|||||||
|
package org.jiayunet.admin.controller;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import org.jiayunet.admin.pojo.dto.order.OrderListDto;
|
||||||
|
import org.jiayunet.admin.pojo.dto.order.OrderStatsDto;
|
||||||
|
import org.jiayunet.admin.pojo.param.order.OrderPageParam;
|
||||||
|
import org.jiayunet.admin.service.AdminOrderService;
|
||||||
|
import org.jiayunet.pojo.PageResult;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 管理后台-订单管理控制类
|
||||||
|
*
|
||||||
|
* @author zk
|
||||||
|
*/
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/order")
|
||||||
|
@AllArgsConstructor
|
||||||
|
@Validated
|
||||||
|
public class AdminOrderController {
|
||||||
|
|
||||||
|
private AdminOrderService adminOrderService;
|
||||||
|
|
||||||
|
/** 订单分页列表 */
|
||||||
|
@PostMapping("/list")
|
||||||
|
public PageResult<OrderListDto> list(@Validated @RequestBody OrderPageParam param) {
|
||||||
|
return adminOrderService.pageList(param);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 订单统计 */
|
||||||
|
@GetMapping("/stats")
|
||||||
|
public OrderStatsDto stats() {
|
||||||
|
return adminOrderService.stats();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
package org.jiayunet.admin.controller;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import org.jiayunet.admin.pojo.param.product.ProductPageParam;
|
||||||
|
import org.jiayunet.admin.pojo.param.product.ProductSaveParam;
|
||||||
|
import org.jiayunet.admin.service.AdminProductService;
|
||||||
|
import org.jiayunet.pojo.PageResult;
|
||||||
|
import org.jiayunet.pojo.po.MemberProduct;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 管理后台-商品管理控制类
|
||||||
|
*
|
||||||
|
* @author zk
|
||||||
|
*/
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/product")
|
||||||
|
@AllArgsConstructor
|
||||||
|
@Validated
|
||||||
|
public class AdminProductController {
|
||||||
|
|
||||||
|
private AdminProductService adminProductService;
|
||||||
|
|
||||||
|
/** 商品分页列表 */
|
||||||
|
@PostMapping("/list")
|
||||||
|
public PageResult<MemberProduct> list(@Validated @RequestBody ProductPageParam param) {
|
||||||
|
return adminProductService.pageList(param);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 新增/编辑商品 */
|
||||||
|
@PostMapping("/save")
|
||||||
|
public void save(@Validated @RequestBody ProductSaveParam param) {
|
||||||
|
adminProductService.save(param);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 上架/下架 */
|
||||||
|
@PostMapping("/updateStatus")
|
||||||
|
public void updateStatus(@RequestParam Long id, @RequestParam Integer status) {
|
||||||
|
adminProductService.updateStatus(id, status);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 删除商品 */
|
||||||
|
@PostMapping("/delete")
|
||||||
|
public void delete(@RequestParam Long id) {
|
||||||
|
adminProductService.delete(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
package org.jiayunet.admin.controller;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import org.jiayunet.admin.pojo.dto.user.UserListDto;
|
||||||
|
import org.jiayunet.admin.pojo.dto.user.UserStatsDto;
|
||||||
|
import org.jiayunet.admin.pojo.param.user.UserPageParam;
|
||||||
|
import org.jiayunet.admin.service.AdminUserService;
|
||||||
|
import org.jiayunet.pojo.PageResult;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 管理后台-用户管理控制类
|
||||||
|
*
|
||||||
|
* @author zk
|
||||||
|
*/
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/user")
|
||||||
|
@AllArgsConstructor
|
||||||
|
@Validated
|
||||||
|
public class AdminUserController {
|
||||||
|
|
||||||
|
private AdminUserService adminUserService;
|
||||||
|
|
||||||
|
/** 用户分页列表 */
|
||||||
|
@PostMapping("/list")
|
||||||
|
public PageResult<UserListDto> list(@Validated @RequestBody UserPageParam param) {
|
||||||
|
return adminUserService.pageList(param);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 用户统计(总数/今日/本周/本月) */
|
||||||
|
@GetMapping("/stats")
|
||||||
|
public UserStatsDto stats() {
|
||||||
|
return adminUserService.stats();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 禁用/启用用户 */
|
||||||
|
@PostMapping("/updateStatus")
|
||||||
|
public void updateStatus(@RequestParam Long userId, @RequestParam Integer status) {
|
||||||
|
adminUserService.updateStatus(userId, status);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
package org.jiayunet.admin.pojo.dto.order;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 订单列表出参
|
||||||
|
*
|
||||||
|
* @author zk
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class OrderListDto {
|
||||||
|
|
||||||
|
/** 订单ID */
|
||||||
|
private Long id;
|
||||||
|
/** 订单编号 */
|
||||||
|
private String orderNo;
|
||||||
|
/** 用户昵称 */
|
||||||
|
private String userNick;
|
||||||
|
/** 用户手机号 */
|
||||||
|
private String mobileNumber;
|
||||||
|
/** 商品名称 */
|
||||||
|
private String productName;
|
||||||
|
/** 实付金额(分) */
|
||||||
|
private Integer payAmount;
|
||||||
|
/** 支付渠道 1=微信 2=支付宝 */
|
||||||
|
private Integer payChannel;
|
||||||
|
/** 订单状态 0=待支付 1=已支付 2=已退款 3=已关闭 */
|
||||||
|
private Integer status;
|
||||||
|
/** 下单时间 */
|
||||||
|
private Instant createTime;
|
||||||
|
/** 支付时间 */
|
||||||
|
private Instant payTime;
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
package org.jiayunet.admin.pojo.dto.order;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 订单统计出参
|
||||||
|
*
|
||||||
|
* @author zk
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class OrderStatsDto {
|
||||||
|
|
||||||
|
/** 总订单数 */
|
||||||
|
private Long totalCount;
|
||||||
|
/** 已支付订单数 */
|
||||||
|
private Long paidCount;
|
||||||
|
/** 今日已支付 */
|
||||||
|
private Long todayPaid;
|
||||||
|
/** 本周已支付 */
|
||||||
|
private Long weekPaid;
|
||||||
|
/** 本月已支付 */
|
||||||
|
private Long monthPaid;
|
||||||
|
/** 今日收入(分) */
|
||||||
|
private Long todayIncome;
|
||||||
|
/** 本周收入(分) */
|
||||||
|
private Long weekIncome;
|
||||||
|
/** 本月收入(分) */
|
||||||
|
private Long monthIncome;
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
package org.jiayunet.admin.pojo.dto.user;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户列表出参
|
||||||
|
*
|
||||||
|
* @author zk
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class UserListDto {
|
||||||
|
|
||||||
|
/** 用户ID */
|
||||||
|
private Long id;
|
||||||
|
/** 昵称 */
|
||||||
|
private String nick;
|
||||||
|
/** 真实姓名 */
|
||||||
|
private String realName;
|
||||||
|
/** 手机号 */
|
||||||
|
private String mobileNumber;
|
||||||
|
/** 状态 0=正常 1=禁用 */
|
||||||
|
private Integer status;
|
||||||
|
/** 简历数量 */
|
||||||
|
private Integer resumeCount;
|
||||||
|
/** 注册时间 */
|
||||||
|
private Instant createTime;
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package org.jiayunet.admin.pojo.dto.user;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户统计出参
|
||||||
|
*
|
||||||
|
* @author zk
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class UserStatsDto {
|
||||||
|
|
||||||
|
/** 用户总数 */
|
||||||
|
private Long total;
|
||||||
|
/** 今日新增 */
|
||||||
|
private Long today;
|
||||||
|
/** 本周新增 */
|
||||||
|
private Long thisWeek;
|
||||||
|
/** 本月新增 */
|
||||||
|
private Long thisMonth;
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
package org.jiayunet.admin.pojo.param.order;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import org.jiayunet.pojo.PageParam;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 订单分页查询入参
|
||||||
|
*
|
||||||
|
* @author zk
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
public class OrderPageParam extends PageParam {
|
||||||
|
|
||||||
|
/** 订单状态 0=待支付 1=已支付 2=已退款 3=已关闭 */
|
||||||
|
private Integer status;
|
||||||
|
/** 支付渠道 1=微信 2=支付宝 */
|
||||||
|
private Integer payChannel;
|
||||||
|
/** 用户手机号(模糊) */
|
||||||
|
private String mobileNumber;
|
||||||
|
/** 下单时间-起 */
|
||||||
|
private Instant startTime;
|
||||||
|
/** 下单时间-止 */
|
||||||
|
private Instant endTime;
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package org.jiayunet.admin.pojo.param.product;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import org.jiayunet.pojo.PageParam;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 商品分页查询入参
|
||||||
|
*
|
||||||
|
* @author zk
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
public class ProductPageParam extends PageParam {
|
||||||
|
|
||||||
|
/** 状态筛选 0=下架 1=上架 */
|
||||||
|
private Integer status;
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
package org.jiayunet.admin.pojo.param.product;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import javax.validation.constraints.Min;
|
||||||
|
import javax.validation.constraints.NotBlank;
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 商品新增/编辑入参
|
||||||
|
*
|
||||||
|
* @author zk
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class ProductSaveParam {
|
||||||
|
|
||||||
|
/** 商品ID(编辑时必传,新增时不传) */
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@NotBlank(message = "商品名称不能为空")
|
||||||
|
private String productName;
|
||||||
|
|
||||||
|
/** 标签,如"限时优惠" */
|
||||||
|
private String tag;
|
||||||
|
|
||||||
|
/** 主推标识 0=否 1=是 */
|
||||||
|
private Integer isFeatured;
|
||||||
|
|
||||||
|
/** 购买按钮文字 */
|
||||||
|
private String buyButtonText;
|
||||||
|
|
||||||
|
@NotNull(message = "价格不能为空")
|
||||||
|
@Min(value = 1, message = "价格必须大于0")
|
||||||
|
private Integer price;
|
||||||
|
|
||||||
|
/** 划线价(分) */
|
||||||
|
private Integer originalPrice;
|
||||||
|
|
||||||
|
/** 折算月价(分) */
|
||||||
|
private Integer monthlyPrice;
|
||||||
|
|
||||||
|
@NotNull(message = "有效天数不能为空")
|
||||||
|
@Min(value = 1, message = "有效天数必须大于0")
|
||||||
|
private Integer durationDays;
|
||||||
|
|
||||||
|
/** 排序 */
|
||||||
|
private Integer sortOrder;
|
||||||
|
|
||||||
|
/** 状态 0=下架 1=上架 */
|
||||||
|
private Integer status;
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package org.jiayunet.admin.pojo.param.user;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import org.jiayunet.pojo.PageParam;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户分页查询入参
|
||||||
|
*
|
||||||
|
* @author zk
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
public class UserPageParam extends PageParam {
|
||||||
|
|
||||||
|
/** 手机号(模糊搜索) */
|
||||||
|
private String mobileNumber;
|
||||||
|
|
||||||
|
/** 状态筛选 0=正常 1=禁用 */
|
||||||
|
private Integer status;
|
||||||
|
}
|
||||||
@@ -0,0 +1,119 @@
|
|||||||
|
package org.jiayunet.admin.service;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.jiayunet.admin.pojo.dto.order.OrderListDto;
|
||||||
|
import org.jiayunet.admin.pojo.dto.order.OrderStatsDto;
|
||||||
|
import org.jiayunet.admin.pojo.param.order.OrderPageParam;
|
||||||
|
import org.jiayunet.mapper.MemberOrderMapper;
|
||||||
|
import org.jiayunet.mapper.MemberProductMapper;
|
||||||
|
import org.jiayunet.mapper.UserMapper;
|
||||||
|
import org.jiayunet.pojo.PageResult;
|
||||||
|
import org.jiayunet.pojo.po.MemberOrder;
|
||||||
|
import org.jiayunet.pojo.po.MemberProduct;
|
||||||
|
import org.jiayunet.pojo.po.User;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
import java.time.*;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 管理后台-订单管理服务
|
||||||
|
* <p>依赖:MemberOrderMapper、UserMapper、MemberProductMapper</p>
|
||||||
|
* <p>使用表:bg_member_order(订单列表/统计)、bg_user(关联用户信息)、bg_member_product(关联商品名)</p>
|
||||||
|
*
|
||||||
|
* @author zk
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
@Slf4j
|
||||||
|
public class AdminOrderService {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private MemberOrderMapper memberOrderMapper;
|
||||||
|
@Autowired
|
||||||
|
private UserMapper userMapper;
|
||||||
|
@Autowired
|
||||||
|
private MemberProductMapper memberProductMapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 订单分页列表
|
||||||
|
* <p>1. 如果按手机号筛选,先查用户ID集合 2. 分页查订单 3. 批量关联用户和商品信息 4. 组装DTO</p>
|
||||||
|
*/
|
||||||
|
public PageResult<OrderListDto> pageList(OrderPageParam param) {
|
||||||
|
// 如果传了手机号,先查对应用户ID
|
||||||
|
Set<Long> userIdFilter = null;
|
||||||
|
if (StringUtils.hasText(param.getMobileNumber())) {
|
||||||
|
List<User> users = userMapper.selectList(new LambdaQueryWrapper<User>().like(User::getMobileNumber, param.getMobileNumber()).select(User::getId));
|
||||||
|
userIdFilter = users.stream().map(User::getId).collect(Collectors.toSet());
|
||||||
|
if (userIdFilter.isEmpty()) return new PageResult<>(param.getPageNum().longValue(), param.getPageSize().longValue(), 0L, List.of());
|
||||||
|
}
|
||||||
|
|
||||||
|
LambdaQueryWrapper<MemberOrder> wrapper = new LambdaQueryWrapper<MemberOrder>()
|
||||||
|
.eq(param.getStatus() != null, MemberOrder::getStatus, param.getStatus())
|
||||||
|
.eq(param.getPayChannel() != null, MemberOrder::getPayChannel, param.getPayChannel())
|
||||||
|
.ge(param.getStartTime() != null, MemberOrder::getCreateTime, param.getStartTime())
|
||||||
|
.le(param.getEndTime() != null, MemberOrder::getCreateTime, param.getEndTime())
|
||||||
|
.in(userIdFilter != null, MemberOrder::getUserId, userIdFilter)
|
||||||
|
.orderByDesc(MemberOrder::getCreateTime);
|
||||||
|
|
||||||
|
Page<MemberOrder> page = memberOrderMapper.selectPage(param.toPage(), wrapper);
|
||||||
|
if (page.getRecords().isEmpty()) return PageResult.from((Page<OrderListDto>) page.convert(o -> new OrderListDto()));
|
||||||
|
|
||||||
|
// 批量查用户和商品
|
||||||
|
Set<Long> userIds = page.getRecords().stream().map(MemberOrder::getUserId).collect(Collectors.toSet());
|
||||||
|
Set<Long> productIds = page.getRecords().stream().map(MemberOrder::getProductId).collect(Collectors.toSet());
|
||||||
|
Map<Long, User> userMap = userMapper.selectBatchIds(userIds).stream().collect(Collectors.toMap(User::getId, u -> u));
|
||||||
|
Map<Long, MemberProduct> productMap = memberProductMapper.selectBatchIds(productIds).stream().collect(Collectors.toMap(MemberProduct::getId, p -> p));
|
||||||
|
|
||||||
|
Page<OrderListDto> dtoPage = (Page<OrderListDto>) page.convert(order -> {
|
||||||
|
OrderListDto dto = new OrderListDto();
|
||||||
|
dto.setId(order.getId());
|
||||||
|
dto.setOrderNo(order.getOrderNo());
|
||||||
|
dto.setPayAmount(order.getPayAmount());
|
||||||
|
dto.setPayChannel(order.getPayChannel());
|
||||||
|
dto.setStatus(order.getStatus());
|
||||||
|
dto.setCreateTime(order.getCreateTime());
|
||||||
|
dto.setPayTime(order.getPayTime());
|
||||||
|
User user = userMap.get(order.getUserId());
|
||||||
|
if (user != null) { dto.setUserNick(user.getNick()); dto.setMobileNumber(user.getMobileNumber()); }
|
||||||
|
MemberProduct product = productMap.get(order.getProductId());
|
||||||
|
if (product != null) { dto.setProductName(product.getProductName()); }
|
||||||
|
return dto;
|
||||||
|
});
|
||||||
|
return PageResult.from(dtoPage);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 订单统计:总数/已支付数/今日本周本月已支付数和收入
|
||||||
|
*/
|
||||||
|
public OrderStatsDto stats() {
|
||||||
|
OrderStatsDto dto = new OrderStatsDto();
|
||||||
|
ZoneId zone = ZoneId.of("Asia/Shanghai");
|
||||||
|
LocalDate now = LocalDate.now(zone);
|
||||||
|
Instant todayStart = now.atStartOfDay(zone).toInstant();
|
||||||
|
Instant weekStart = now.with(DayOfWeek.MONDAY).atStartOfDay(zone).toInstant();
|
||||||
|
Instant monthStart = now.withDayOfMonth(1).atStartOfDay(zone).toInstant();
|
||||||
|
|
||||||
|
dto.setTotalCount(memberOrderMapper.selectCount(new LambdaQueryWrapper<MemberOrder>()));
|
||||||
|
dto.setPaidCount(memberOrderMapper.selectCount(new LambdaQueryWrapper<MemberOrder>().eq(MemberOrder::getStatus, 1)));
|
||||||
|
|
||||||
|
// 今日/本周/本月已支付订单
|
||||||
|
List<MemberOrder> todayOrders = memberOrderMapper.selectList(new LambdaQueryWrapper<MemberOrder>().eq(MemberOrder::getStatus, 1).ge(MemberOrder::getPayTime, todayStart));
|
||||||
|
List<MemberOrder> weekOrders = memberOrderMapper.selectList(new LambdaQueryWrapper<MemberOrder>().eq(MemberOrder::getStatus, 1).ge(MemberOrder::getPayTime, weekStart));
|
||||||
|
List<MemberOrder> monthOrders = memberOrderMapper.selectList(new LambdaQueryWrapper<MemberOrder>().eq(MemberOrder::getStatus, 1).ge(MemberOrder::getPayTime, monthStart));
|
||||||
|
|
||||||
|
dto.setTodayPaid((long) todayOrders.size());
|
||||||
|
dto.setWeekPaid((long) weekOrders.size());
|
||||||
|
dto.setMonthPaid((long) monthOrders.size());
|
||||||
|
dto.setTodayIncome(todayOrders.stream().mapToLong(o -> o.getPayAmount() == null ? 0 : o.getPayAmount()).sum());
|
||||||
|
dto.setWeekIncome(weekOrders.stream().mapToLong(o -> o.getPayAmount() == null ? 0 : o.getPayAmount()).sum());
|
||||||
|
dto.setMonthIncome(monthOrders.stream().mapToLong(o -> o.getPayAmount() == null ? 0 : o.getPayAmount()).sum());
|
||||||
|
return dto;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,67 @@
|
|||||||
|
package org.jiayunet.admin.service;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||||
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.jiayunet.admin.pojo.param.product.ProductPageParam;
|
||||||
|
import org.jiayunet.admin.pojo.param.product.ProductSaveParam;
|
||||||
|
import org.jiayunet.mapper.MemberProductMapper;
|
||||||
|
import org.jiayunet.pojo.PageResult;
|
||||||
|
import org.jiayunet.pojo.po.MemberProduct;
|
||||||
|
import org.springframework.beans.BeanUtils;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 管理后台-商品管理服务
|
||||||
|
* <p>依赖:MemberProductMapper</p>
|
||||||
|
* <p>使用表:bg_member_product(CRUD)</p>
|
||||||
|
*
|
||||||
|
* @author zk
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
@Slf4j
|
||||||
|
public class AdminProductService {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private MemberProductMapper memberProductMapper;
|
||||||
|
|
||||||
|
/** 商品分页列表 */
|
||||||
|
public PageResult<MemberProduct> pageList(ProductPageParam param) {
|
||||||
|
LambdaQueryWrapper<MemberProduct> wrapper = new LambdaQueryWrapper<MemberProduct>()
|
||||||
|
.eq(param.getStatus() != null, MemberProduct::getStatus, param.getStatus())
|
||||||
|
.orderByAsc(MemberProduct::getSortOrder);
|
||||||
|
Page<MemberProduct> page = memberProductMapper.selectPage(param.toPage(), wrapper);
|
||||||
|
return PageResult.from(page);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 新增/编辑商品 */
|
||||||
|
public void save(ProductSaveParam param) {
|
||||||
|
MemberProduct product = new MemberProduct();
|
||||||
|
BeanUtils.copyProperties(param, product);
|
||||||
|
if (param.getId() == null) {
|
||||||
|
if (product.getStatus() == null) product.setStatus(0);
|
||||||
|
if (product.getSortOrder() == null) product.setSortOrder(0);
|
||||||
|
if (product.getIsFeatured() == null) product.setIsFeatured(0);
|
||||||
|
memberProductMapper.insert(product);
|
||||||
|
} else {
|
||||||
|
product.setId(param.getId());
|
||||||
|
memberProductMapper.updateById(product);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 上架/下架商品 */
|
||||||
|
public void updateStatus(Long id, Integer status) {
|
||||||
|
Assert.notNull(id, "商品ID不能为空");
|
||||||
|
Assert.isTrue(status == 0 || status == 1, "状态值非法");
|
||||||
|
memberProductMapper.update(null, new LambdaUpdateWrapper<MemberProduct>().eq(MemberProduct::getId, id).set(MemberProduct::getStatus, status));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 删除商品(逻辑删除) */
|
||||||
|
public void delete(Long id) {
|
||||||
|
Assert.notNull(id, "商品ID不能为空");
|
||||||
|
memberProductMapper.deleteById(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,102 @@
|
|||||||
|
package org.jiayunet.admin.service;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||||
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.jiayunet.admin.pojo.dto.user.UserListDto;
|
||||||
|
import org.jiayunet.admin.pojo.dto.user.UserStatsDto;
|
||||||
|
import org.jiayunet.admin.pojo.param.user.UserPageParam;
|
||||||
|
import org.jiayunet.mapper.UserMapper;
|
||||||
|
import org.jiayunet.mapper.UserResumeMapper;
|
||||||
|
import org.jiayunet.pojo.PageResult;
|
||||||
|
import org.jiayunet.pojo.po.User;
|
||||||
|
import org.jiayunet.pojo.po.UserResume;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
import java.time.*;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 管理后台-用户管理服务
|
||||||
|
* <p>依赖:UserMapper(用户查询/更新)、UserResumeMapper(简历数量统计)</p>
|
||||||
|
* <p>使用表:bg_user(用户列表/统计/禁用)、bg_user_resume(简历数量)</p>
|
||||||
|
*
|
||||||
|
* @author zk
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
@Slf4j
|
||||||
|
public class AdminUserService {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private UserMapper userMapper;
|
||||||
|
@Autowired
|
||||||
|
private UserResumeMapper userResumeMapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户分页列表
|
||||||
|
* <p>1. 分页查询用户 2. 批量查询每个用户的简历数量 3. 组装返回</p>
|
||||||
|
*/
|
||||||
|
public PageResult<UserListDto> pageList(UserPageParam param) {
|
||||||
|
LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<User>()
|
||||||
|
.like(StringUtils.hasText(param.getMobileNumber()), User::getMobileNumber, param.getMobileNumber())
|
||||||
|
.like(StringUtils.hasText(param.getKeyword()), User::getNick, param.getKeyword())
|
||||||
|
.eq(param.getStatus() != null, User::getStatus, param.getStatus())
|
||||||
|
.orderByDesc(User::getCreateTime);
|
||||||
|
|
||||||
|
Page<User> page = userMapper.selectPage(param.toPage(), wrapper);
|
||||||
|
if (page.getRecords().isEmpty()) return PageResult.from((Page<UserListDto>) page.convert(u -> new UserListDto()));
|
||||||
|
|
||||||
|
// 批量查询简历数量
|
||||||
|
List<Long> userIds = page.getRecords().stream().map(User::getId).collect(Collectors.toList());
|
||||||
|
List<UserResume> resumes = userResumeMapper.selectList(new LambdaQueryWrapper<UserResume>().in(UserResume::getUserId, userIds).select(UserResume::getUserId));
|
||||||
|
Map<Long, Long> resumeCountMap = resumes.stream().collect(Collectors.groupingBy(UserResume::getUserId, Collectors.counting()));
|
||||||
|
|
||||||
|
// 组装DTO
|
||||||
|
Page<UserListDto> dtoPage = (Page<UserListDto>) page.convert(user -> {
|
||||||
|
UserListDto dto = new UserListDto();
|
||||||
|
dto.setId(user.getId());
|
||||||
|
dto.setNick(user.getNick());
|
||||||
|
dto.setRealName(user.getRealName());
|
||||||
|
dto.setMobileNumber(user.getMobileNumber());
|
||||||
|
dto.setStatus(user.getStatus());
|
||||||
|
dto.setResumeCount(resumeCountMap.getOrDefault(user.getId(), 0L).intValue());
|
||||||
|
dto.setCreateTime(user.getCreateTime());
|
||||||
|
return dto;
|
||||||
|
});
|
||||||
|
return PageResult.from(dtoPage);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户统计:总数 / 今日 / 本周 / 本月 新增
|
||||||
|
*/
|
||||||
|
public UserStatsDto stats() {
|
||||||
|
UserStatsDto dto = new UserStatsDto();
|
||||||
|
ZoneId zone = ZoneId.of("Asia/Shanghai");
|
||||||
|
LocalDate now = LocalDate.now(zone);
|
||||||
|
|
||||||
|
Instant todayStart = now.atStartOfDay(zone).toInstant();
|
||||||
|
Instant weekStart = now.with(DayOfWeek.MONDAY).atStartOfDay(zone).toInstant();
|
||||||
|
Instant monthStart = now.withDayOfMonth(1).atStartOfDay(zone).toInstant();
|
||||||
|
|
||||||
|
dto.setTotal(userMapper.selectCount(new LambdaQueryWrapper<User>()));
|
||||||
|
dto.setToday(userMapper.selectCount(new LambdaQueryWrapper<User>().ge(User::getCreateTime, todayStart)));
|
||||||
|
dto.setThisWeek(userMapper.selectCount(new LambdaQueryWrapper<User>().ge(User::getCreateTime, weekStart)));
|
||||||
|
dto.setThisMonth(userMapper.selectCount(new LambdaQueryWrapper<User>().ge(User::getCreateTime, monthStart)));
|
||||||
|
return dto;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 禁用/启用用户
|
||||||
|
*/
|
||||||
|
public void updateStatus(Long userId, Integer status) {
|
||||||
|
Assert.notNull(userId, "用户ID不能为空");
|
||||||
|
Assert.isTrue(status == 0 || status == 1, "状态值非法");
|
||||||
|
userMapper.update(null, new LambdaUpdateWrapper<User>().eq(User::getId, userId).set(User::getStatus, status));
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user