package com.doumee.api.web; import com.doumee.core.annotation.LoginRequired; import com.doumee.core.constants.ResponseStatus; import com.doumee.core.exception.BusinessException; import com.doumee.core.model.ApiResponse; import com.doumee.core.model.PageData; import com.doumee.core.model.PageWrap; import com.doumee.dao.business.vo.BikeIncomeStatVO; import com.doumee.dao.business.vo.IncomeStatVO; import com.doumee.dao.business.vo.OperationCenterVO; import com.doumee.dao.business.vo.OperationOrderVO; import com.doumee.dao.business.vo.OrderRidesDetailVO; import com.doumee.dao.business.vo.OverviewStatVO; import com.doumee.dao.business.web.request.BikeIncomeQueryDTO; import com.doumee.dao.business.web.request.OperationOrderQueryDTO; import com.doumee.dao.business.web.response.UserResponse; import com.doumee.dao.system.model.SystemUser; import com.doumee.service.business.ReportService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import java.util.List; /** * 数据报表(web 端运营中心:概览统计 / 收入车型分析 / 收入统计)。 *

鉴权走 web 端 JWT(@LoginRequired),且每个接口校验当前登录会员已绑定系统管理员(sysuser != null), * 与 {@link ManagerApi}(/web/manger)同属 web 端运营中心场景,非绑定管理员的会员无权访问。 *

Service 实现复用 services 模块的 {@link ReportService},本次仅涉及 Controller 与鉴权方式。 * * @author rk * @date 2026/06/26 */ @Api(tags = "数据报表") @RestController @RequestMapping("/web/report") public class ReportController extends ApiController { /** 报表统计服务(services 模块,web 端直接复用) */ @Autowired private ReportService reportService; @LoginRequired @ApiOperation("概览统计:总注册用户/今日新增/自行车/电动车数量") @GetMapping("/overview") public ApiResponse overview() { checkManager(); return ApiResponse.success(reportService.overview()); } @LoginRequired @ApiOperation("收入车型分析:按车型型号汇总收入,支持近7/15/30天及自定义时段") @PostMapping("/bikeIncome") public ApiResponse> bikeIncome(@RequestBody BikeIncomeQueryDTO query) { checkManager(); return ApiResponse.success(reportService.bikeIncome(query)); } @LoginRequired @ApiOperation("收入统计:按日收入(柱状图)+累计收入+环比/同比,支持近7/15/30天及自定义时段") @PostMapping("/incomeStat") public ApiResponse incomeStat(@RequestBody BikeIncomeQueryDTO query) { checkManager(); return ApiResponse.success(reportService.incomeStat(query)); } @LoginRequired @ApiOperation("运营中心数据:今日订单/进行中/今日套餐收入/今日总收入 + 登录人/日期/星期") @GetMapping("/operationCenter") public ApiResponse operationCenter() { // 登录人姓名取绑定的系统管理员真实姓名(与 ManagerApi 同口径,非绑定管理员抛权限异常) SystemUser sysuser = checkManager(); OperationCenterVO vo = reportService.operationCenter(); vo.setRealName(sysuser == null ? null : sysuser.getRealname()); return ApiResponse.success(vo); } @LoginRequired @ApiOperation("运营中心订单查询:按订单类型(骑行记录类型)/手机号/状态分页查询押金订单") @PostMapping("/operationOrderPage") public ApiResponse> operationOrderPage( @RequestBody PageWrap pageWrap) { checkManager(); return ApiResponse.success(reportService.operationOrderPage(pageWrap)); } @LoginRequired @ApiOperation("订单骑行记录+轨迹:按订单查询其下全部骑行记录及轨迹点(自行车无轨迹)") @GetMapping("/orderRides") public ApiResponse orderRides(@RequestParam("orderId") String orderId) { checkManager(); return ApiResponse.success(reportService.orderRidesDetail(orderId)); } /** * 校验当前登录会员已绑定系统管理员;返回该管理员(供调用方取姓名等)。 *

报表为运营数据,仅绑定后台管理员的会员可访问(对齐 {@link ManagerApi} 的 sysuser 校验)。 * * @return 当前会员绑定的系统管理员;理论上已保证非空(为空已在方法内抛 NOT_ALLOWED) */ private SystemUser checkManager() { UserResponse user = getUserResponse(); SystemUser sysuser = user == null ? null : user.getSysuser(); if (sysuser == null) { throw new BusinessException(ResponseStatus.NOT_ALLOWED); } return sysuser; } }