From 15c200aa7e0ced518364a68769503472b542c9f4 Mon Sep 17 00:00:00 2001
From: Administrator <15274802129@163.com>
Date: Tue, 08 Jul 2025 14:03:57 +0800
Subject: [PATCH] feat(mall): 添加会员数据统计功能
---
src/main/java/cc/mrbird/febs/mall/controller/member/AdminMallMemberController.java | 12 ++
src/main/resources/templates/febs/views/modules/mallMember/dataInfo.html | 222 +++++++++++++++++++++++++++++++++++++
src/main/java/cc/mrbird/febs/mall/controller/member/ViewMallMemberController.java | 10 +
src/main/java/cc/mrbird/febs/mall/vo/AdminDataInfoVo.java | 20 +++
src/main/java/cc/mrbird/febs/mall/service/IAdminMallMemberService.java | 2
src/main/java/cc/mrbird/febs/mall/service/impl/AdminMallMemberServiceImpl.java | 41 ++++++
src/main/java/cc/mrbird/febs/mall/service/impl/ApiMallMemberServiceImpl.java | 9 +
7 files changed, 316 insertions(+), 0 deletions(-)
diff --git a/src/main/java/cc/mrbird/febs/mall/controller/member/AdminMallMemberController.java b/src/main/java/cc/mrbird/febs/mall/controller/member/AdminMallMemberController.java
index d6d33f8..6c75d69 100644
--- a/src/main/java/cc/mrbird/febs/mall/controller/member/AdminMallMemberController.java
+++ b/src/main/java/cc/mrbird/febs/mall/controller/member/AdminMallMemberController.java
@@ -4,25 +4,31 @@
import cc.mrbird.febs.common.controller.BaseController;
import cc.mrbird.febs.common.entity.FebsResponse;
import cc.mrbird.febs.common.entity.QueryRequest;
+import cc.mrbird.febs.common.enumerates.OrderPayMethodEnum;
+import cc.mrbird.febs.common.enumerates.OrderStatusEnum;
import cc.mrbird.febs.mall.dto.*;
import cc.mrbird.febs.mall.entity.*;
import cc.mrbird.febs.mall.service.IAdminMallMemberService;
import cc.mrbird.febs.mall.service.IApiMallMemberService;
import cc.mrbird.febs.mall.vo.*;
+import cc.mrbird.febs.system.entity.User;
import cc.mrbird.febs.vip.entity.MallVipBenefitsRecord;
import cc.mrbird.febs.vip.mapper.MallVipBenefitsRecordMapper;
import cc.mrbird.febs.vip.service.IMallVipBenefitsService;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
+import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.util.Date;
+import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -38,6 +44,12 @@
private final IMallVipBenefitsService mallVipBenefitsService;
private final MallVipBenefitsRecordMapper mallVipBenefitsRecordMapper;
+ @GetMapping("dataInfo")
+ public FebsResponse dataInfo() {
+
+ return mallMemberService.dataInfo();
+ }
+
/**
* 平台账单
*
diff --git a/src/main/java/cc/mrbird/febs/mall/controller/member/ViewMallMemberController.java b/src/main/java/cc/mrbird/febs/mall/controller/member/ViewMallMemberController.java
index 345f802..614e08d 100644
--- a/src/main/java/cc/mrbird/febs/mall/controller/member/ViewMallMemberController.java
+++ b/src/main/java/cc/mrbird/febs/mall/controller/member/ViewMallMemberController.java
@@ -40,6 +40,16 @@
* 平台账单
* @return
*/
+ @GetMapping("dataInfo")
+ @RequiresPermissions("dataInfo:view")
+ public String dataInfo() {
+ return FebsUtil.view("modules/mallMember/dataInfo");
+ }
+
+ /**
+ * 平台账单
+ * @return
+ */
@GetMapping("mallDataList")
@RequiresPermissions("mallDataList:view")
public String mallDataList() {
diff --git a/src/main/java/cc/mrbird/febs/mall/service/IAdminMallMemberService.java b/src/main/java/cc/mrbird/febs/mall/service/IAdminMallMemberService.java
index c762a22..89b6b37 100644
--- a/src/main/java/cc/mrbird/febs/mall/service/IAdminMallMemberService.java
+++ b/src/main/java/cc/mrbird/febs/mall/service/IAdminMallMemberService.java
@@ -145,4 +145,6 @@
FebsResponse checkOrder(Long id);
FebsResponse checkLeader(Long id);
+
+ FebsResponse dataInfo();
}
diff --git a/src/main/java/cc/mrbird/febs/mall/service/impl/AdminMallMemberServiceImpl.java b/src/main/java/cc/mrbird/febs/mall/service/impl/AdminMallMemberServiceImpl.java
index 254e019..fee552f 100644
--- a/src/main/java/cc/mrbird/febs/mall/service/impl/AdminMallMemberServiceImpl.java
+++ b/src/main/java/cc/mrbird/febs/mall/service/impl/AdminMallMemberServiceImpl.java
@@ -18,6 +18,7 @@
import cc.mrbird.febs.pay.model.MemberWithdrawalDto;
import cc.mrbird.febs.pay.service.IXcxPayService;
import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
@@ -27,6 +28,7 @@
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
@@ -35,6 +37,7 @@
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
+import java.util.Arrays;
import java.util.Date;
import java.util.List;
@@ -995,4 +998,42 @@
return new FebsResponse().success().message("操作成功");
}
+
+ @Override
+ public FebsResponse dataInfo() {
+ AdminDataInfoVo adminDataInfoVo = new AdminDataInfoVo();
+
+ List<MallMember> mallMembers = this.baseMapper.selectList(null);
+ if(CollUtil.isNotEmpty(mallMembers)){
+ adminDataInfoVo.setTotalMember(mallMembers.size());
+
+ adminDataInfoVo.setTotalDayMember(
+ Math.toIntExact(mallMembers.stream().filter(mallMember -> DateUtil.compare(mallMember.getCreatedTime(), DateUtil.beginOfDay(new Date())) >= 0).count()));
+ adminDataInfoVo.setTotalWeekMember(
+ Math.toIntExact(mallMembers.stream().filter(mallMember -> DateUtil.compare(mallMember.getCreatedTime(), DateUtil.beginOfWeek(new Date())) >= 0).count()));
+ adminDataInfoVo.setTotalMonthMember(
+ Math.toIntExact(mallMembers.stream().filter(mallMember -> DateUtil.compare(mallMember.getCreatedTime(), DateUtil.beginOfMonth(new Date())) >= 0).count()));
+ }
+
+ List<Integer> typeList = Arrays.asList(ScoreFlowTypeEnum.WECHAT_PAY.getValue(), ScoreFlowTypeEnum.PAY_BALANCE.getValue());
+ List<MallMoneyFlow> mallMoneyFlows = mallMoneyFlowMapper.selectList(
+ Wrappers.lambdaQuery(MallMoneyFlow.class)
+ .in(MallMoneyFlow::getType, typeList)
+ );
+ if(CollUtil.isNotEmpty(mallMoneyFlows)){
+ adminDataInfoVo.setTotalAmount(mallMoneyFlows.stream().map(MallMoneyFlow::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add).negate());
+ adminDataInfoVo.setTotalDayAmount(
+ mallMoneyFlows.stream().filter(mallMoneyFlow -> DateUtil.compare(mallMoneyFlow.getCreatedTime(), DateUtil.beginOfDay(new Date())) >= 0)
+ .map(MallMoneyFlow::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add).negate());
+ adminDataInfoVo.setTotalWeekAmount(
+ mallMoneyFlows.stream().filter(mallMoneyFlow -> DateUtil.compare(mallMoneyFlow.getCreatedTime(), DateUtil.beginOfWeek(new Date())) >= 0)
+ .map(MallMoneyFlow::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add).negate());
+ adminDataInfoVo.setTotalMonthAmount(
+ mallMoneyFlows.stream().filter(mallMoneyFlow -> DateUtil.compare(mallMoneyFlow.getCreatedTime(), DateUtil.beginOfMonth(new Date())) >= 0)
+ .map(MallMoneyFlow::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add).negate());
+
+ }
+
+ return new FebsResponse().success().data(adminDataInfoVo);
+ }
}
diff --git a/src/main/java/cc/mrbird/febs/mall/service/impl/ApiMallMemberServiceImpl.java b/src/main/java/cc/mrbird/febs/mall/service/impl/ApiMallMemberServiceImpl.java
index f127194..2f722a6 100644
--- a/src/main/java/cc/mrbird/febs/mall/service/impl/ApiMallMemberServiceImpl.java
+++ b/src/main/java/cc/mrbird/febs/mall/service/impl/ApiMallMemberServiceImpl.java
@@ -808,6 +808,15 @@
}
String phone = apiXcxSaveInfoDto.getPhone();
if(StrUtil.isNotEmpty(phone)){
+
+ MallMember entity = this.baseMapper.selectOne(
+ Wrappers.lambdaQuery(MallMember.class)
+ .eq(MallMember::getPhone, phone)
+ .last("LIMIT 1")
+ );
+ if(ObjectUtil.isNotNull( entity) && !entity.getId().equals(memberId)){
+ throw new FebsException("手机号码已使用");
+ }
mallMember.setPhone(phone);
}
String avatarUrl = apiXcxSaveInfoDto.getAvatarUrl();
diff --git a/src/main/java/cc/mrbird/febs/mall/vo/AdminDataInfoVo.java b/src/main/java/cc/mrbird/febs/mall/vo/AdminDataInfoVo.java
new file mode 100644
index 0000000..0eb84b5
--- /dev/null
+++ b/src/main/java/cc/mrbird/febs/mall/vo/AdminDataInfoVo.java
@@ -0,0 +1,20 @@
+package cc.mrbird.febs.mall.vo;
+
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+@Data
+public class AdminDataInfoVo {
+
+ private Integer totalMember = 0;//总数
+ private Integer totalDayMember = 0;//昨日新增
+ private Integer totalWeekMember = 0;//七日内新增
+ private Integer totalMonthMember = 0;//30天内新增
+
+ private BigDecimal totalAmount = BigDecimal.ZERO;//总数
+ private BigDecimal totalDayAmount = BigDecimal.ZERO;//新增
+ private BigDecimal totalWeekAmount = BigDecimal.ZERO;//本周新增
+ private BigDecimal totalMonthAmount = BigDecimal.ZERO;//本月新增
+
+}
diff --git a/src/main/resources/templates/febs/views/modules/mallMember/dataInfo.html b/src/main/resources/templates/febs/views/modules/mallMember/dataInfo.html
new file mode 100644
index 0000000..cf36f4b
--- /dev/null
+++ b/src/main/resources/templates/febs/views/modules/mallMember/dataInfo.html
@@ -0,0 +1,222 @@
+<style>
+ #data-info .welcome-info {
+ border: 1px solid #f1f1f1;
+ margin-bottom: .5rem;
+ padding: .5rem;
+ background: #FFFFFF;
+ }
+
+ #data-info .welcome-info-wrapper {
+ padding: .2rem;
+ display: inline-block
+ }
+
+ #data-info .welcome-info-wrapper .user-header {
+ display: inline-block;
+ vertical-align: middle
+ }
+
+ #data-info .welcome-info-wrapper .user-header img {
+ width: 5rem;
+ margin: .5rem 1rem;
+ border-radius: 50%
+ }
+
+ #data-info .welcome-info-wrapper .user-info {
+ display: inline-block;
+ vertical-align: middle
+ }
+
+ #data-info .welcome-info-wrapper .user-info .random-message {
+ font-size: 1rem;
+ margin-bottom: .2rem;
+ max-width: 21rem
+ }
+
+ #data-info .welcome-info-wrapper .user-info .user-dept, #data-info .welcome-info-wrapper .user-info .user-login-info {
+ color: rgba(0, 0, 0, 0.45);
+ }
+
+ #data-info .login-count-table {
+ width: 100%;
+ margin: 1rem;
+ }
+
+ #data-info .login-count-table .count {
+ padding-top: .8rem;
+ font-size: 1rem;
+ font-weight: 600;
+ color: #1890ff
+ }
+
+ #data-info .project-table {
+ padding: .5rem;
+ border: 1px solid #f1f1f1;
+ width: 100%
+ }
+
+ #data-info .project-table-td {
+ padding: .5rem 0.7rem;
+ border: 1px solid #f1f1f1;
+ }
+
+ #data-info .project-table-td a {
+ color: #42b983;
+ font-size: .9rem;
+ font-weight: 600;
+ }
+
+ #data-info .project-desc {
+ color: rgba(0, 0, 0, 0.45);
+ }
+ /*.layui-card:last-child{*/
+ /* background: #F8F8F8;*/
+ /*}*/
+ .box{
+ background: #FFFFFF;
+ padding: 30px 30px;
+ border-radius: 4px;
+ }
+ .box .name{
+ font-size: 14px;
+ color: #333333;
+ }
+ .box .num{
+ font-size: 24px;
+ color: #1890ff;
+ font-weight: bold;
+ margin-top: 10px;
+ }
+ .m-title{
+ position: relative;
+ font-size: 16px;
+ font-weight: bold;
+ color: #000000;
+ padding-left: 20px;
+ margin: 0 0 10px;
+ }
+ .m-title::before{
+ content: '';
+ position: absolute;
+ left: 0;
+ width: 4px;
+ height: 20px;
+ background: #1890ff;
+ }
+</style>
+<div class="layui-fluid layui-anim febs-anim-up" id="data-info" lay-title="数据看板">
+ <div class="layui-row layui-col-space8 febs-container">
+ <div class="layui-col-md12 layui-col-sm12 layui-col-xs12">
+ <div class="layui-card" style="background: #F8F8F8;">
+ <div class="layui-card-body layui-anim layui-anim-fadein">
+ </div>
+
+ <div class="layui-card-body layui-anim layui-anim-fadein">
+ <div class="layui-row">
+ <div class="m-title">会员注册</div>
+ <div class="layui-row layui-col-space15">
+ <div class="layui-col-md3">
+ <div class="layui-panel">
+ <div class="box">
+ <p class="name">总计</p>
+ <p class="num"><span id="totalMember"></span></p>
+ </div>
+ </div>
+ </div>
+ <div class="layui-col-md3">
+ <div class="layui-panel">
+ <div class="box">
+ <p class="name">今日新增</p>
+ <p class="num"><span id="totalDayMember"></span></p>
+ </div>
+ </div>
+ </div>
+ <div class="layui-col-md3">
+ <div class="layui-panel">
+ <div class="box">
+ <p class="name">本周新增</p>
+ <p class="num"><span id="totalWeekMember"></span></p>
+ </div>
+ </div>
+ </div>
+ <div class="layui-col-md3">
+ <div class="layui-panel">
+ <div class="box">
+ <p class="name">本月新增</p>
+ <p class="num"><span id="totalMonthMember"></span></p>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+
+ <div class="layui-card-body layui-anim layui-anim-fadein">
+ <div class="layui-row">
+ <div class="m-title">交易数据</div>
+ <div class="layui-row layui-col-space15">
+ <div class="layui-col-md3">
+ <div class="layui-panel">
+ <div class="box">
+ <p class="name">累计</p>
+ <p class="num"><span id="totalAmount"></span></p>
+ </div>
+ </div>
+ </div>
+ <div class="layui-col-md3">
+ <div class="layui-panel">
+ <div class="box">
+ <p class="name">今日新增</p>
+ <p class="num"><span id="totalDayAmount"></span></p>
+ </div>
+ </div>
+ </div>
+ <div class="layui-col-md3">
+ <div class="layui-panel">
+ <div class="box">
+ <p class="name">本周新增</p>
+ <p class="num"><span id="totalWeekAmount"></span></p>
+ </div>
+ </div>
+ </div>
+ <div class="layui-col-md3">
+ <div class="layui-panel">
+ <div class="box">
+ <p class="name">本月新增</p>
+ <p class="num"><span id="totalMonthAmount"></span></p>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+
+
+
+ </div>
+ </div>
+ </div>
+</div>
+<script data-th-inline="javascript" type="text/javascript">
+ layui.use(['apexcharts', 'febs', 'jquery', 'util'], function () {
+ var $ = layui.jquery,
+ util = layui.util,
+ $view = $('#data-info'),
+ febs = layui.febs;
+
+ febs.get(ctx + 'admin/mallMember/dataInfo', null, function (r) {
+ handleSuccess(r.data);
+ });
+
+ function handleSuccess(data) {
+ $view.find('#totalMember').text(data.totalMember).end()
+ .find('#totalDayMember').text(data.totalDayMember).end()
+ .find('#totalWeekMember').text(data.totalWeekMember).end()
+ .find('#totalMonthMember').text(data.totalMonthMember).end()
+ .find('#totalAmount').text(data.totalAmount).end()
+ .find('#totalDayAmount').text(data.totalDayAmount).end()
+ .find('#totalWeekAmount').text(data.totalWeekAmount).end()
+ .find('#totalMonthAmount').text(data.totalMonthAmount).end();
+ }
+ });
+</script>
--
Gitblit v1.9.1