首页统计

This commit is contained in:
2025-08-08 16:10:13 +08:00
parent 5b8d18d913
commit fcde865a2d
5 changed files with 277 additions and 162 deletions

View File

@@ -0,0 +1,32 @@
package com.ycwl.basic.controller.pc;
import com.ycwl.basic.model.mobile.statistic.req.CommonQueryReq;
import com.ycwl.basic.service.pc.StatisticsService;
import com.ycwl.basic.utils.ApiResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.HashMap;
import java.util.List;
/**
* @Author:longbinbin
* @Date:2024/12/12 14:30
*/
@RestController
@RequestMapping("/api/statistics/v1")
public class StatisticsController {
@Autowired
private StatisticsService statisticsService;
/**
* 智能获取扫码访问人数统计数据(自动选择粒度)
* @param query 查询参数(包含景区ID、开始时间、结束时间)
* @return 统计数据(超过7天返回日期级别,否则返回小时级别)
*/
@PostMapping("/scanCodeMemberChart")
public ApiResponse<List<HashMap<String, String>>> getScanCodeMemberChart(@RequestBody CommonQueryReq query) {
return ApiResponse.success(statisticsService.getScanCodeMemberChartAuto(query));
}
}

View File

@@ -102,4 +102,8 @@ public interface StatisticsMapper {
List<HashMap<String, String>> orderChartByDate(CommonQueryReq query); List<HashMap<String, String>> orderChartByDate(CommonQueryReq query);
List<HashMap<String, String>> orderChartByHour(CommonQueryReq query); List<HashMap<String, String>> orderChartByHour(CommonQueryReq query);
List<HashMap<String, String>> scanCodeMemberChartByHour(CommonQueryReq query);
List<HashMap<String, String>> scanCodeMemberChartByDate(CommonQueryReq query);
} }

View File

@@ -0,0 +1,20 @@
package com.ycwl.basic.service.pc;
import com.ycwl.basic.model.mobile.statistic.req.CommonQueryReq;
import java.util.HashMap;
import java.util.List;
/**
* @Author:longbinbin
* @Date:2024/12/12 14:32
*/
public interface StatisticsService {
/**
* 智能获取扫码访问人数统计数据(自动选择小时级别或日期级别)
* @param query 查询参数(包含景区ID、开始时间、结束时间)
* @return 统计数据(超过7天返回日期级别,否则返回小时级别)
*/
List<HashMap<String, String>> getScanCodeMemberChartAuto(CommonQueryReq query);
}

View File

@@ -0,0 +1,77 @@
package com.ycwl.basic.service.pc.impl;
import com.ycwl.basic.mapper.StatisticsMapper;
import com.ycwl.basic.model.mobile.statistic.req.CommonQueryReq;
import com.ycwl.basic.service.pc.StatisticsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.temporal.ChronoUnit;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
/**
* @Author:longbinbin
* @Date:2024/12/12 14:34
*/
@Service
public class StatisticsServiceImpl implements StatisticsService {
@Autowired
private StatisticsMapper statisticsMapper;
List<HashMap<String, String>> getScanCodeMemberChartByHour(CommonQueryReq query) {
return statisticsMapper.scanCodeMemberChartByHour(query);
}
List<HashMap<String, String>> getScanCodeMemberChartByDate(CommonQueryReq query) {
return statisticsMapper.scanCodeMemberChartByDate(query);
}
@Override
public List<HashMap<String, String>> getScanCodeMemberChartAuto(CommonQueryReq query) {
// 检查时间范围
if (query.getStartTime() == null || query.getEndTime() == null) {
// 根据需求处理时间范围:
// 如果开始和结束时间均为空,则默认为当天0点到23时59分59秒
// 如果只有一个为空,则往前或往后推24小时
LocalDateTime now = LocalDateTime.now();
if (query.getStartTime() == null && query.getEndTime() == null) {
// 都为空,设置为当天0点到23:59:59
LocalDateTime startOfDay = now.withHour(0).withMinute(0).withSecond(0).withNano(0);
LocalDateTime endOfDay = now.withHour(23).withMinute(59).withSecond(59).withNano(0);
query.setStartTime(Date.from(startOfDay.atZone(ZoneId.systemDefault()).toInstant()));
query.setEndTime(Date.from(endOfDay.atZone(ZoneId.systemDefault()).toInstant()));
} else if (query.getStartTime() == null) {
// 开始时间为空,结束时间不为空,往前推24小时
LocalDateTime endDateTime = query.getEndTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
LocalDateTime startDateTime = endDateTime.minusHours(24);
query.setStartTime(Date.from(startDateTime.atZone(ZoneId.systemDefault()).toInstant()));
} else {
// 结束时间为空,开始时间不为空,往后推24小时
LocalDateTime startDateTime = query.getStartTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
LocalDateTime endDateTime = startDateTime.plusHours(24);
query.setEndTime(Date.from(endDateTime.atZone(ZoneId.systemDefault()).toInstant()));
}
}
// 计算时间差(天数)
LocalDateTime startDateTime = query.getStartTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
LocalDateTime endDateTime = query.getEndTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
long daysBetween = ChronoUnit.DAYS.between(startDateTime, endDateTime);
// 超过7天使用日期级别,否则使用小时级别
if (daysBetween > 7) {
return getScanCodeMemberChartByDate(query);
} else {
return getScanCodeMemberChartByHour(query);
}
}
}

View File

@@ -319,176 +319,158 @@
AND date BETWEEN #{startTime} AND #{endTime} AND date BETWEEN #{startTime} AND #{endTime}
</select> </select>
<select id="orderChartByDate" resultType="java.util.HashMap"> <select id="orderChartByDate" resultType="java.util.HashMap">
WITH RECURSIVE date_series AS (
SELECT SELECT
DATE(date_series.DATE) as t, DATE(#{startTime}) AS date_value
COALESCE ( count( `order`.id ), 0 ) AS count, UNION ALL
COALESCE ( sum( `order`.pay_price ), 0 ) AS price
FROM
(
SELECT SELECT
DATE_ADD( #{startTime}, INTERVAL ( units.i + tens.i * 10 + hundreds.i * 100 ) DAY ) AS DATE DATE_ADD(date_value, INTERVAL 1 DAY) AS date_value
FROM FROM date_series
( WHERE DATE_ADD(date_value, INTERVAL 1 DAY) &lt;= DATE(#{endTime})
)
SELECT SELECT
0 AS i UNION ALL DATE(date_series.date_value) as t,
SELECT COALESCE(COUNT(`order`.id), 0) AS count,
1 UNION ALL COALESCE(SUM(`order`.pay_price), 0) AS price
SELECT FROM date_series
2 UNION ALL LEFT JOIN `order` ON DATE(`order`.create_at) = date_series.date_value
SELECT <if test="scenicId != null">
3 UNION ALL AND `order`.scenic_id = #{scenicId}
SELECT </if>
4 UNION ALL AND (`order`.STATUS = 1 OR `order`.STATUS = 2)
SELECT GROUP BY date_series.date_value
5 UNION ALL ORDER BY date_series.date_value
SELECT
6 UNION ALL
SELECT
7 UNION ALL
SELECT
8 UNION ALL
SELECT
9
) units
CROSS JOIN (
SELECT
0 AS i UNION ALL
SELECT
1 UNION ALL
SELECT
2 UNION ALL
SELECT
3 UNION ALL
SELECT
4 UNION ALL
SELECT
5 UNION ALL
SELECT
6 UNION ALL
SELECT
7 UNION ALL
SELECT
8 UNION ALL
SELECT
9
) tens
CROSS JOIN (
SELECT
0 AS i UNION ALL
SELECT
1 UNION ALL
SELECT
2 UNION ALL
SELECT
3 UNION ALL
SELECT
4 UNION ALL
SELECT
5 UNION ALL
SELECT
6 UNION ALL
SELECT
7 UNION ALL
SELECT
8 UNION ALL
SELECT
9
) hundreds
WHERE
DATE_ADD( #{startTime}, INTERVAL ( units.i + tens.i * 10 + hundreds.i * 100 ) DAY ) &lt;= #{endTime}
) date_series
LEFT JOIN `order` ON DATE ( `order`.create_at ) = date_series.DATE AND `order`.scenic_id = #{scenicId} AND ( `order`.STATUS = 1 OR `order`.STATUS = 2 )
GROUP BY
date_series.DATE
ORDER BY date_series.DATE
</select> </select>
<select id="orderChartByHour" resultType="java.util.HashMap"> <select id="orderChartByHour" resultType="java.util.HashMap">
WITH RECURSIVE hour_series AS (
SELECT SELECT
date_series.HOUR as t, #{startTime} AS hour_time,
COALESCE ( count( `order`.id ), 0 ) AS count, DATE_FORMAT(#{startTime}, '%m-%d %H') AS HOUR
COALESCE ( sum( `order`.pay_price ), 0 ) AS price UNION ALL
FROM
(
SELECT SELECT
DATE_FORMAT( DATE_ADD( #{startTime}, INTERVAL ( units.i + tens.i * 10 + hundreds.i * 100 ) HOUR ), '%m-%d %H') AS HOUR DATE_ADD(hour_time, INTERVAL 1 HOUR) AS hour_time,
FROM DATE_FORMAT(DATE_ADD(hour_time, INTERVAL 1 HOUR), '%m-%d %H') AS HOUR
( FROM hour_series
WHERE DATE_ADD(hour_time, INTERVAL 1 HOUR) &lt;= #{endTime}
)
SELECT SELECT
0 AS i UNION ALL hour_series.HOUR as t,
SELECT COALESCE(COUNT(`order`.id), 0) AS count,
1 UNION ALL COALESCE(SUM(`order`.pay_price), 0) AS price
SELECT FROM hour_series
2 UNION ALL LEFT JOIN `order` ON DATE_FORMAT(`order`.create_at, '%m-%d %H') = hour_series.HOUR
SELECT <if test="scenicId != null">
3 UNION ALL AND `order`.scenic_id = #{scenicId}
SELECT </if>
4 UNION ALL AND (`order`.STATUS = 1 OR `order`.STATUS = 2)
SELECT GROUP BY hour_series.HOUR, hour_series.hour_time
5 UNION ALL ORDER BY hour_series.hour_time
SELECT
6 UNION ALL
SELECT
7 UNION ALL
SELECT
8 UNION ALL
SELECT
9
) units
CROSS JOIN (
SELECT
0 AS i UNION ALL
SELECT
1 UNION ALL
SELECT
2 UNION ALL
SELECT
3 UNION ALL
SELECT
4 UNION ALL
SELECT
5 UNION ALL
SELECT
6 UNION ALL
SELECT
7 UNION ALL
SELECT
8 UNION ALL
SELECT
9
) tens
CROSS JOIN (
SELECT
0 AS i UNION ALL
SELECT
1 UNION ALL
SELECT
2 UNION ALL
SELECT
3 UNION ALL
SELECT
4 UNION ALL
SELECT
5 UNION ALL
SELECT
6 UNION ALL
SELECT
7 UNION ALL
SELECT
8 UNION ALL
SELECT
9
) hundreds
WHERE
DATE_ADD( #{startTime}, INTERVAL ( units.i + tens.i * 10 + hundreds.i * 100 ) HOUR ) &lt;= #{endTime}
) date_series
LEFT JOIN `order` ON DATE_FORMAT( `order`.create_at, '%m-%d %H' ) = date_series.HOUR AND `order`.scenic_id = #{scenicId} AND ( `order`.STATUS = 1 OR `order`.STATUS = 2 )
GROUP BY
date_series.HOUR
ORDER BY date_series.HOUR
</select> </select>
<insert id="insertStat"> <insert id="insertStat">
REPLACE INTO scenic_stats (scenic_id, date, cs1, v1, sv1, u1, m1, gv1, gv2, pv1, pv2, cp1, o1, o2, o3, ro2, ro3) REPLACE INTO scenic_stats (scenic_id, date, cs1, v1, sv1, u1, m1, gv1, gv2, pv1, pv2, cp1, o1, o2, o3, ro2, ro3)
VALUES (#{scenicId}, #{date}, #{data.cameraShotOfMemberNum}, #{data.totalVisitorOfMemberNum}, #{data.scanCodeVisitorOfMemberNum}, #{data.uploadFaceOfMemberNum}, #{data.pushOfMemberNum}, #{data.completeVideoOfMemberNum}, #{data.completeOfVideoNum}, #{data.previewVideoOfMemberNum}, #{data.previewOfVideoNum}, #{data.clickOnPayOfMemberNum}, #{data.payOfMemberNum}, #{data.payOfOrderNum}, #{data.payOfOrderAmount}, #{data.refundOfOrderNum}, #{data.refundOfOrderAmount}) VALUES (#{scenicId}, #{date}, #{data.cameraShotOfMemberNum}, #{data.totalVisitorOfMemberNum}, #{data.scanCodeVisitorOfMemberNum}, #{data.uploadFaceOfMemberNum}, #{data.pushOfMemberNum}, #{data.completeVideoOfMemberNum}, #{data.completeOfVideoNum}, #{data.previewVideoOfMemberNum}, #{data.previewOfVideoNum}, #{data.clickOnPayOfMemberNum}, #{data.payOfMemberNum}, #{data.payOfOrderNum}, #{data.payOfOrderAmount}, #{data.refundOfOrderNum}, #{data.refundOfOrderAmount})
</insert> </insert>
<select id="scanCodeMemberChartByHour" resultType="java.util.HashMap">
WITH RECURSIVE hour_series AS (
SELECT
#{startTime} AS hour_time,
DATE_FORMAT(#{startTime}, '%m-%d %H') AS HOUR
UNION ALL
SELECT
DATE_ADD(hour_time, INTERVAL 1 HOUR) AS hour_time,
DATE_FORMAT(DATE_ADD(hour_time, INTERVAL 1 HOUR), '%m-%d %H') AS HOUR
FROM hour_series
WHERE DATE_ADD(hour_time, INTERVAL 1 HOUR) &lt;= #{endTime}
)
SELECT
hour_series.HOUR as t,
COALESCE(scan_data.member_count, 0) AS count,
COALESCE(order_data.order_count, 0) AS orderCount,
COALESCE(order_data.order_amount, 0) AS orderAmount
FROM hour_series
LEFT JOIN (
SELECT
DATE_FORMAT(s.create_time, '%m-%d %H') AS hour_key,
COUNT(DISTINCT s.member_id) AS member_count
FROM `t_stats_record` r
LEFT JOIN `t_stats` s ON r.trace_id = s.trace_id
WHERE r.trace_id IN (
SELECT trace_id FROM `t_stats_record`
WHERE action = 'ENTER_SCENIC'
<if test="scenicId != null">
AND `identifier` = #{scenicId}
</if>
)
AND r.action = 'LAUNCH'
AND JSON_EXTRACT(`params`, '$.scene') IN (1047, 1048, 1049)
AND s.create_time BETWEEN #{startTime} AND #{endTime}
GROUP BY DATE_FORMAT(s.create_time, '%m-%d %H')
) scan_data ON scan_data.hour_key = hour_series.HOUR
LEFT JOIN (
SELECT
DATE_FORMAT(create_at, '%m-%d %H') AS hour_key,
COUNT(id) AS order_count,
SUM(pay_price) AS order_amount
FROM `order`
WHERE (status = 1 OR status = 2)
<if test="scenicId != null">
AND scenic_id = #{scenicId}
</if>
AND create_at BETWEEN #{startTime} AND #{endTime}
GROUP BY DATE_FORMAT(create_at, '%m-%d %H')
) order_data ON order_data.hour_key = hour_series.HOUR
ORDER BY hour_series.hour_time
</select>
<select id="scanCodeMemberChartByDate" resultType="java.util.HashMap">
WITH RECURSIVE date_series AS (
SELECT
DATE(#{startTime}) AS date_value,
DATE_FORMAT(#{startTime}, '%m-%d') AS DATE_KEY
UNION ALL
SELECT
DATE_ADD(date_value, INTERVAL 1 DAY) AS date_value,
DATE_FORMAT(DATE_ADD(date_value, INTERVAL 1 DAY), '%m-%d') AS DATE_KEY
FROM date_series
WHERE DATE_ADD(date_value, INTERVAL 1 DAY) &lt;= DATE(#{endTime})
)
SELECT
date_series.DATE_KEY as t,
COALESCE(scan_data.member_count, 0) AS count,
COALESCE(order_data.order_count, 0) AS orderCount,
COALESCE(order_data.order_amount, 0) AS orderAmount
FROM date_series
LEFT JOIN (
SELECT
DATE_FORMAT(s.create_time, '%m-%d') AS date_key,
COUNT(DISTINCT s.member_id) AS member_count
FROM `t_stats_record` r
LEFT JOIN `t_stats` s ON r.trace_id = s.trace_id
WHERE r.trace_id IN (
SELECT trace_id FROM `t_stats_record`
WHERE action = 'ENTER_SCENIC'
<if test="scenicId != null">
AND `identifier` = #{scenicId}
</if>
)
AND r.action = 'LAUNCH'
AND JSON_EXTRACT(`params`, '$.scene') IN (1047, 1048, 1049)
AND s.create_time BETWEEN #{startTime} AND #{endTime}
GROUP BY DATE_FORMAT(s.create_time, '%m-%d')
) scan_data ON scan_data.date_key = date_series.DATE_KEY
LEFT JOIN (
SELECT
DATE_FORMAT(create_at, '%m-%d') AS date_key,
COUNT(id) AS order_count,
SUM(pay_price) AS order_amount
FROM `order`
WHERE (status = 1 OR status = 2)
<if test="scenicId != null">
AND scenic_id = #{scenicId}
</if>
AND create_at BETWEEN #{startTime} AND #{endTime}
GROUP BY DATE_FORMAT(create_at, '%m-%d')
) order_data ON order_data.date_key = date_series.DATE_KEY
ORDER BY date_series.date_value
</select>
</mapper> </mapper>