feat: 新增首页统计接口
This commit is contained in:
1
pom.xml
1
pom.xml
@@ -183,7 +183,6 @@
|
|||||||
<version>${redisson.version}</version>
|
<version>${redisson.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- websocket -->
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-websocket</artifactId>
|
<artifactId>spring-boot-starter-websocket</artifactId>
|
||||||
|
|||||||
@@ -20,13 +20,14 @@ import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
|
|||||||
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;
|
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* WebSocket 配置
|
* WebSocket 自动配置类
|
||||||
*
|
*
|
||||||
* @author haoxr
|
* @author haoxr
|
||||||
* @since 2.4.0
|
* @since 2.4.0
|
||||||
*/
|
*/
|
||||||
|
// 启用WebSocket消息代理功能和配置STOMP协议,实现实时双向通信和消息传递
|
||||||
|
@EnableWebSocketMessageBroker
|
||||||
@Configuration
|
@Configuration
|
||||||
@EnableWebSocketMessageBroker // 启用WebSocket消息代理功能和配置STOMP协议,实现实时双向通信和消息传递
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
|
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
|
||||||
|
|
||||||
@@ -36,9 +37,12 @@ public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
|
|||||||
@Override
|
@Override
|
||||||
public void registerStompEndpoints(StompEndpointRegistry registry) {
|
public void registerStompEndpoints(StompEndpointRegistry registry) {
|
||||||
registry
|
registry
|
||||||
.addEndpoint("/ws") // 注册了一个 /ws 的端点
|
// 注册 /ws 的端点
|
||||||
.setAllowedOriginPatterns("*") // 允许跨域的 WebSocket 连接
|
.addEndpoint("/ws")
|
||||||
.withSockJS(); // 启用 SockJS (浏览器不支持WebSocket,SockJS 将会提供兼容性支持)
|
// 允许跨域的 WebSocket 连接
|
||||||
|
.setAllowedOriginPatterns("*")
|
||||||
|
// 启用 SockJS (浏览器不支持WebSocket,SockJS 将会提供兼容性支持)
|
||||||
|
.withSockJS();
|
||||||
registry.addEndpoint("/ws-app").setAllowedOriginPatterns("*"); // 注册了一个 /ws-app 的端点,支持 uni-app 的 ws 连接协议
|
registry.addEndpoint("/ws-app").setAllowedOriginPatterns("*"); // 注册了一个 /ws-app 的端点,支持 uni-app 的 ws 连接协议
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,44 @@
|
|||||||
|
package com.youlai.system.controller;
|
||||||
|
|
||||||
|
import com.youlai.system.common.result.Result;
|
||||||
|
import com.youlai.system.model.vo.VisitTrendVO;
|
||||||
|
import com.youlai.system.service.SysLogService;
|
||||||
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
import io.swagger.v3.oas.annotations.Parameter;
|
||||||
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import java.time.LocalDate;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 统计数据控制层
|
||||||
|
*
|
||||||
|
* @author Ray
|
||||||
|
* @since 2.10.0
|
||||||
|
*/
|
||||||
|
@Tag(name = "09.统计数据")
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/api/v1/stats")
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class StatsController {
|
||||||
|
|
||||||
|
private final SysLogService logService;
|
||||||
|
|
||||||
|
@Operation(summary = "获取访问趋势")
|
||||||
|
@GetMapping("/visit-trend")
|
||||||
|
public Result getVisitTrend(
|
||||||
|
@Parameter(description = "开始时间", example = "yyyy-MM-dd") @RequestParam String startDate,
|
||||||
|
@Parameter(description = "结束时间", example = "yyyy-MM-dd") @RequestParam String endDate
|
||||||
|
) {
|
||||||
|
LocalDate start = LocalDate.parse(startDate);
|
||||||
|
LocalDate end = LocalDate.parse(endDate);
|
||||||
|
VisitTrendVO data = logService.getVisitTrend(start, end);
|
||||||
|
return Result.success(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -2,6 +2,7 @@ package com.youlai.system.controller;
|
|||||||
|
|
||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
import com.youlai.system.common.result.PageResult;
|
import com.youlai.system.common.result.PageResult;
|
||||||
|
import com.youlai.system.model.query.LogPageQuery;
|
||||||
import com.youlai.system.model.query.RolePageQuery;
|
import com.youlai.system.model.query.RolePageQuery;
|
||||||
import com.youlai.system.model.vo.LogPageVO;
|
import com.youlai.system.model.vo.LogPageVO;
|
||||||
import com.youlai.system.service.SysLogService;
|
import com.youlai.system.service.SysLogService;
|
||||||
@@ -28,7 +29,7 @@ public class SysLogController {
|
|||||||
@Operation(summary = "日志分页列表")
|
@Operation(summary = "日志分页列表")
|
||||||
@GetMapping("/page")
|
@GetMapping("/page")
|
||||||
public PageResult<LogPageVO> listPagedLogs(
|
public PageResult<LogPageVO> listPagedLogs(
|
||||||
RolePageQuery queryParams
|
LogPageQuery queryParams
|
||||||
) {
|
) {
|
||||||
Page<LogPageVO> result = logService.listPagedLogs(queryParams);
|
Page<LogPageVO> result = logService.listPagedLogs(queryParams);
|
||||||
return PageResult.success(result);
|
return PageResult.success(result);
|
||||||
|
|||||||
@@ -1,12 +1,16 @@
|
|||||||
package com.youlai.system.mapper;
|
package com.youlai.system.mapper;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
|
import com.youlai.system.model.bo.VisitCount;
|
||||||
import com.youlai.system.model.entity.SysLog;
|
import com.youlai.system.model.entity.SysLog;
|
||||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import com.youlai.system.model.query.LogPageQuery;
|
||||||
import com.youlai.system.model.query.RolePageQuery;
|
import com.youlai.system.model.query.RolePageQuery;
|
||||||
import com.youlai.system.model.vo.LogPageVO;
|
import com.youlai.system.model.vo.LogPageVO;
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 系统日志 数据库访问层
|
* 系统日志 数据库访问层
|
||||||
@@ -17,7 +21,32 @@ import org.apache.ibatis.annotations.Mapper;
|
|||||||
@Mapper
|
@Mapper
|
||||||
public interface SysLogMapper extends BaseMapper<SysLog> {
|
public interface SysLogMapper extends BaseMapper<SysLog> {
|
||||||
|
|
||||||
Page<LogPageVO> listPagedLogs(Page page, RolePageQuery queryParams);
|
/**
|
||||||
|
* 获取日志分页列表
|
||||||
|
*
|
||||||
|
* @param page
|
||||||
|
* @param queryParams
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
Page<LogPageVO> listPagedLogs(Page page, LogPageQuery queryParams);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 统计浏览数(PV)
|
||||||
|
*
|
||||||
|
* @param startDate 开始日期 yyyy-MM-dd
|
||||||
|
* @param endDate 结束日期 yyyy-MM-dd
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
List<VisitCount> getPvCounts(String startDate, String endDate);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 统计IP数
|
||||||
|
*
|
||||||
|
* @param startDate 开始日期 yyyy-MM-dd
|
||||||
|
* @param endDate 结束日期 yyyy-MM-dd
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
List<VisitCount> getIpCounts(String startDate, String endDate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
23
src/main/java/com/youlai/system/model/bo/VisitCount.java
Normal file
23
src/main/java/com/youlai/system/model/bo/VisitCount.java
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
package com.youlai.system.model.bo;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 特定日期访问统计
|
||||||
|
*
|
||||||
|
* @author Ray
|
||||||
|
* @since 2.10.0
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class VisitCount {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 日期 yyyy-MM-dd
|
||||||
|
*/
|
||||||
|
private String date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 访问次数
|
||||||
|
*/
|
||||||
|
private Integer count;
|
||||||
|
}
|
||||||
@@ -4,6 +4,7 @@ import com.youlai.system.common.base.BasePageQuery;
|
|||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
|
import org.springframework.format.annotation.DateTimeFormat;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 日志分页查询对象
|
* 日志分页查询对象
|
||||||
@@ -18,4 +19,13 @@ public class LogPageQuery extends BasePageQuery {
|
|||||||
|
|
||||||
@Schema(description="关键字(日志内容/请求路径/请求方法/地区/浏览器/终端系统)")
|
@Schema(description="关键字(日志内容/请求路径/请求方法/地区/浏览器/终端系统)")
|
||||||
private String keywords;
|
private String keywords;
|
||||||
|
|
||||||
|
@Schema(description="开始日期")
|
||||||
|
@DateTimeFormat(pattern = "yyyy-MM-dd")
|
||||||
|
private String startDate;
|
||||||
|
|
||||||
|
@Schema(description="结束日期")
|
||||||
|
@DateTimeFormat(pattern = "yyyy-MM-dd")
|
||||||
|
private String endDate;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,13 @@
|
|||||||
package com.youlai.system.model.query;
|
package com.youlai.system.model.query;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
import com.youlai.system.common.base.BasePageQuery;
|
import com.youlai.system.common.base.BasePageQuery;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 角色分页查询对象
|
* 角色分页查询对象
|
||||||
*
|
*
|
||||||
@@ -18,4 +21,12 @@ public class RolePageQuery extends BasePageQuery {
|
|||||||
|
|
||||||
@Schema(description="关键字(角色名称/角色编码)")
|
@Schema(description="关键字(角色名称/角色编码)")
|
||||||
private String keywords;
|
private String keywords;
|
||||||
|
|
||||||
|
@Schema(description="开始日期")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd")
|
||||||
|
private LocalDateTime startDate;
|
||||||
|
|
||||||
|
@Schema(description="结束日期")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd")
|
||||||
|
private LocalDateTime endDate;
|
||||||
}
|
}
|
||||||
|
|||||||
27
src/main/java/com/youlai/system/model/vo/VisitTrendVO.java
Normal file
27
src/main/java/com/youlai/system/model/vo/VisitTrendVO.java
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
package com.youlai.system.model.vo;
|
||||||
|
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Schema(description = "访问趋势VO")
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class VisitTrendVO {
|
||||||
|
|
||||||
|
@Schema(description = "日期列表")
|
||||||
|
private List<String> dates;
|
||||||
|
|
||||||
|
@Schema(description = "浏览量(PV)")
|
||||||
|
private List<Integer> pvList;
|
||||||
|
|
||||||
|
@Schema(description = "访客数(UV)")
|
||||||
|
private List<Integer> uvList;
|
||||||
|
|
||||||
|
@Schema(description = "IP数")
|
||||||
|
private List<Integer> ipList;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -3,8 +3,12 @@ package com.youlai.system.service;
|
|||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
import com.youlai.system.model.entity.SysLog;
|
import com.youlai.system.model.entity.SysLog;
|
||||||
import com.baomidou.mybatisplus.extension.service.IService;
|
import com.baomidou.mybatisplus.extension.service.IService;
|
||||||
|
import com.youlai.system.model.query.LogPageQuery;
|
||||||
import com.youlai.system.model.query.RolePageQuery;
|
import com.youlai.system.model.query.RolePageQuery;
|
||||||
import com.youlai.system.model.vo.LogPageVO;
|
import com.youlai.system.model.vo.LogPageVO;
|
||||||
|
import com.youlai.system.model.vo.VisitTrendVO;
|
||||||
|
|
||||||
|
import java.time.LocalDate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 系统日志 服务接口
|
* 系统日志 服务接口
|
||||||
@@ -14,5 +18,21 @@ import com.youlai.system.model.vo.LogPageVO;
|
|||||||
*/
|
*/
|
||||||
public interface SysLogService extends IService<SysLog> {
|
public interface SysLogService extends IService<SysLog> {
|
||||||
|
|
||||||
Page<LogPageVO> listPagedLogs(RolePageQuery queryParams);
|
/**
|
||||||
|
* 获取日志分页列表
|
||||||
|
*
|
||||||
|
* @param queryParams 查询参数
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
Page<LogPageVO> listPagedLogs(LogPageQuery queryParams);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取访问趋势
|
||||||
|
*
|
||||||
|
* @param startDate 开始时间
|
||||||
|
* @param endDate 结束时间
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
VisitTrendVO getVisitTrend(LocalDate startDate, LocalDate endDate);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,13 +2,22 @@ package com.youlai.system.service.impl;
|
|||||||
|
|
||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
|
import com.youlai.system.common.util.DateUtils;
|
||||||
|
import com.youlai.system.model.bo.VisitCount;
|
||||||
import com.youlai.system.model.entity.SysLog;
|
import com.youlai.system.model.entity.SysLog;
|
||||||
import com.youlai.system.model.query.RolePageQuery;
|
import com.youlai.system.model.query.LogPageQuery;
|
||||||
import com.youlai.system.model.vo.LogPageVO;
|
import com.youlai.system.model.vo.LogPageVO;
|
||||||
|
import com.youlai.system.model.vo.VisitTrendVO;
|
||||||
import com.youlai.system.service.SysLogService;
|
import com.youlai.system.service.SysLogService;
|
||||||
import com.youlai.system.mapper.SysLogMapper;
|
import com.youlai.system.mapper.SysLogMapper;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 系统日志 服务实现类
|
* 系统日志 服务实现类
|
||||||
*
|
*
|
||||||
@@ -26,10 +35,55 @@ public class SysLogServiceImpl extends ServiceImpl<SysLogMapper, SysLog>
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Page<LogPageVO> listPagedLogs(RolePageQuery queryParams) {
|
public Page<LogPageVO> listPagedLogs(LogPageQuery queryParams) {
|
||||||
|
// 格式化为数据库日期格式,避免日期比较使用格式化函数导致索引失效
|
||||||
|
DateUtils.toDatabaseFormat(queryParams, "startDate", "endDate");
|
||||||
|
|
||||||
return this.baseMapper.listPagedLogs(new Page(queryParams.getPageNum(), queryParams.getPageSize()),
|
return this.baseMapper.listPagedLogs(new Page(queryParams.getPageNum(), queryParams.getPageSize()),
|
||||||
queryParams);
|
queryParams);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取访问趋势
|
||||||
|
*
|
||||||
|
* @param startDate 开始时间
|
||||||
|
* @param endDate 结束时间
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public VisitTrendVO getVisitTrend(LocalDate startDate, LocalDate endDate) {
|
||||||
|
VisitTrendVO visitTrend= new VisitTrendVO();
|
||||||
|
List<String> dates = new ArrayList<>();
|
||||||
|
|
||||||
|
// 获取日期范围内的日期
|
||||||
|
while (!startDate.isAfter(endDate)) {
|
||||||
|
dates.add(startDate.toString());
|
||||||
|
startDate = startDate.plusDays(1);
|
||||||
|
}
|
||||||
|
visitTrend.setDates(dates);
|
||||||
|
|
||||||
|
// 获取访问量和访问 IP 数的统计数据
|
||||||
|
List<VisitCount> pvCounts = this.baseMapper.getPvCounts(dates.get(0) + " 00:00:00", dates.get(dates.size() - 1) + " 23:59:59");
|
||||||
|
List<VisitCount> ipCounts = this.baseMapper.getIpCounts(dates.get(0) + " 00:00:00", dates.get(dates.size() - 1) + " 23:59:59");
|
||||||
|
|
||||||
|
// 将统计数据转换为 Map
|
||||||
|
Map<String, Integer> pvMap = pvCounts.stream().collect(Collectors.toMap(VisitCount::getDate, VisitCount::getCount));
|
||||||
|
Map<String, Integer> ipMap = ipCounts.stream().collect(Collectors.toMap(VisitCount::getDate, VisitCount::getCount));
|
||||||
|
|
||||||
|
// 匹配日期和访问量/访问 IP 数
|
||||||
|
List<Integer> pvList = new ArrayList<>();
|
||||||
|
List<Integer> ipList = new ArrayList<>();
|
||||||
|
|
||||||
|
for (String date : dates) {
|
||||||
|
pvList.add(pvMap.getOrDefault(date, 0));
|
||||||
|
ipList.add(ipMap.getOrDefault(date, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
visitTrend.setPvList(pvList);
|
||||||
|
visitTrend.setIpList(ipList);
|
||||||
|
|
||||||
|
return visitTrend;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -33,8 +33,40 @@
|
|||||||
t2.nickname LIKE concat('%',#{queryParams.keywords},'%')
|
t2.nickname LIKE concat('%',#{queryParams.keywords},'%')
|
||||||
)
|
)
|
||||||
</if>
|
</if>
|
||||||
|
<if test="queryParams.startDate != null">
|
||||||
|
AND t1.create_time >= #{queryParams.startDate}
|
||||||
|
</if>
|
||||||
|
<if test="queryParams.endDate != null">
|
||||||
|
AND t1.create_time <= #{queryParams.endDate}
|
||||||
|
</if>
|
||||||
</where>
|
</where>
|
||||||
ORDER BY
|
ORDER BY
|
||||||
t1.create_time DESC
|
t1.create_time DESC
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
<!-- 获取PV访问量统计数据 -->
|
||||||
|
<select id="getPvCounts" resultType="com.youlai.system.model.bo.VisitCount">
|
||||||
|
SELECT
|
||||||
|
COUNT(1) AS count,
|
||||||
|
DATE_FORMAT(create_time,'%Y-%m-%d') AS date
|
||||||
|
FROM
|
||||||
|
sys_log
|
||||||
|
WHERE
|
||||||
|
is_deleted = 0
|
||||||
|
GROUP BY
|
||||||
|
DATE_FORMAT(create_time, '%Y-%m-%d')
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<!-- 获取IP访问统计数据 -->
|
||||||
|
<select id="getIpCounts" resultType="com.youlai.system.model.bo.VisitCount">
|
||||||
|
SELECT
|
||||||
|
COUNT(DISTINCT ip) AS count,
|
||||||
|
DATE_FORMAT(create_time, '%Y-%m-%d') AS date
|
||||||
|
FROM
|
||||||
|
sys_log
|
||||||
|
WHERE
|
||||||
|
is_deleted = 0
|
||||||
|
GROUP BY
|
||||||
|
DATE_FORMAT(create_time, '%Y-%m-%d')
|
||||||
|
</select>
|
||||||
</mapper>
|
</mapper>
|
||||||
|
|||||||
Reference in New Issue
Block a user