支付订单excel文件导出

master
chenyuepan 3 weeks ago
parent 47feedf4c7
commit d9d073bcd6

@ -219,7 +219,6 @@
<version>4.5.0</version>
</dependency>
<!-- 封装了各大模型的交互接口 -->
<!-- <dependency>-->
<!-- <groupId>io.springboot.ai</groupId>-->

@ -13,13 +13,15 @@ public class InterceptorConfig implements WebMvcConfigurer {
.addPathPatterns("/user/**")
.addPathPatterns("/reservation/**")
// .addPathPatterns("/information/**")
.addPathPatterns("/hot/**")
// .addPathPatterns("/hot/**")
// .addPathPatterns("/type/**")
.addPathPatterns("/slot/**")
.addPathPatterns("/admin/**")
.addPathPatterns("/school/**")
.excludePathPatterns("/user/test")
.excludePathPatterns("/user/admin")
.excludePathPatterns("/reservation/excel")
.excludePathPatterns("/reservation/payment")
.excludePathPatterns("/swagger-ui/index.html")
.excludePathPatterns("/doc.html")
.excludePathPatterns("/user/login");

@ -1,6 +1,7 @@
package com.example.venue_reservation_service.controller;
import com.example.venue_reservation_service.domain.Comment;
import com.example.venue_reservation_service.dto.DelDTO;
import com.example.venue_reservation_service.dto.PageDTO;
import com.example.venue_reservation_service.dto.SearchDTO;
import com.example.venue_reservation_service.service.CommentService;
@ -49,4 +50,16 @@ public class CommentController {
@RequestParam("commentId") Integer commentId){
return commentService.like(userId, commentId);
}
@ApiOperation("移除某条评论信息")
@PostMapping("/remove/single")
public Result single(@RequestParam("commentId") Integer commentId, @RequestParam("userId") Integer userId){
return commentService.singleRemove(userId, commentId);
}
@ApiOperation("批量移除评论信息")
@PostMapping("/remove/batch")
public Result batch(@RequestBody DelDTO dto){
return commentService.batchRemove(dto);
}
}

@ -3,9 +3,9 @@ package com.example.venue_reservation_service.controller;
import com.example.venue_reservation_service.dto.QuestionDTO;
import com.example.venue_reservation_service.dto.QuestionQueryDTO;
import com.example.venue_reservation_service.dto.ReservationDTO;
import com.example.venue_reservation_service.service.QuestionService;
import com.example.venue_reservation_service.vo.Result;
import io.swagger.annotations.ApiOperation;
import jakarta.annotation.Resource;
import org.springframework.web.bind.annotation.*;
import io.swagger.v3.oas.annotations.Operation;
@ -15,7 +15,7 @@ import io.swagger.v3.oas.annotations.tags.Tag;
@RestController
@RequestMapping("/question")
@Tag(name = "提问管理", description = "用户提问及管理员审核相关接口")
@Tag(name = "用户提问管理", description = "用户提问及管理员审核相关接口")
@CrossOrigin
public class QuestionController {
@ -37,7 +37,7 @@ public class QuestionController {
return questionService.create(dto);
}
@Operation(summary = "用户分页查询提问", description = "用户查询自己的提问列表,支持分页和筛选",
@Operation(summary = "用户分页查询提问", description = "用户(系统用户,管理员)查询自己的提问列表,支持分页和筛选",
parameters = {
@Parameter(
name = "dto",
@ -47,23 +47,14 @@ public class QuestionController {
)
}
)
@PostMapping("/user/page")
@PostMapping("/page")
public Result userPage(@RequestBody QuestionQueryDTO dto) {
return questionService.userPage(dto);
}
@Operation(summary = "管理员分页查询提问", description = "管理员查询所有用户的提问列表,支持分页和筛选",
parameters = {
@Parameter(
name = "dto",
description = "提问查询DTO包含用户ID、状态等筛选条件",
required = true,
schema = @Schema(implementation = ReservationDTO.class)
)
}
)
@PostMapping("/admin/page")
public Result adminPage(@RequestBody ReservationDTO dto) {
return questionService.adminPage(dto);
@ApiOperation("删除提问")
@PostMapping("/remove")
public Result remove(@RequestParam("userId") Integer userId, @RequestParam("questionId") Integer id){
return questionService.remove(userId, id);
}
}

@ -20,23 +20,28 @@ import org.springframework.web.bind.annotation.*;
*/
@RestController
@RequestMapping("/reply")
@Api("回复管理")
@Api("管理员回复管理")
@CrossOrigin
public class ReplyController {
@Autowired
private ReplyService replyService;
@ApiOperation("添加回复")
@ApiOperation("设置回复")
@PostMapping("/create")
public Result createReply(@RequestBody ReplyDTO dto) {
return replyService.createReply(dto);
}
@ApiOperation("修改回复")
@PostMapping("/update")
public Result updateReply(@RequestBody ReplyDTO dto) {
return replyService.updateReply(dto);
/**
*
* @param id
* @return
*/
@ApiOperation("查看回复")
@GetMapping("/view")
public Result view(@RequestParam("questionId") Integer id){
return replyService.viewReply(id);
}
}

@ -2,9 +2,7 @@ package com.example.venue_reservation_service.controller;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.example.venue_reservation_service.domain.Reservation;
import com.example.venue_reservation_service.dto.RAddDTO;
import com.example.venue_reservation_service.dto.ReservationDTO;
import com.example.venue_reservation_service.dto.SlotDTO;
import com.example.venue_reservation_service.dto.*;
import com.example.venue_reservation_service.service.ReservationService;
import com.example.venue_reservation_service.utils.DownExcel;
import com.example.venue_reservation_service.vo.Result;
@ -17,6 +15,7 @@ import org.springframework.web.bind.annotation.*;
import javax.ws.rs.Path;
import java.io.IOException;
import java.util.List;
@RestController
@RequestMapping("/reservation")
@ -46,9 +45,9 @@ public class ReservationController {
}
@ApiOperation("对预约订单进行签到")
@GetMapping("/signIn")
public Result signIn(@RequestParam("reservationId") Integer reservationId){
return reservationService.signInReservation(reservationId);
@PostMapping("/signIn")
public Result signIn(@RequestBody SignInDTO dto){
return reservationService.signInReservation(dto);
}
@ApiOperation("管理员查看详细的预约信息")
@ -57,16 +56,22 @@ public class ReservationController {
return reservationService.queryDetail(id);
}
@ApiOperation("移除预约信息")
@GetMapping("/remove")
public Result remove(){
return null;
@ApiOperation("移除预约信息(单条)")
@PostMapping("/single")
public Result remove(@RequestParam("userId") Integer userId, @RequestParam("reservationId") Integer id){
return reservationService.removeSingle(userId, id);
}
@ApiOperation("移除预约信息(批量)")
@PostMapping("/remove")
public Result remove(@RequestBody DelDTO dto){
return reservationService.removeBatch(dto);
}
@ApiOperation("获取预约数据")
@GetMapping("/data")
public Result data(){
return Result.ok(reservationService.list()).message("数据获取成功");
public Result data(@RequestParam("time") String time){
return reservationService.exportData(time);
}
@ApiOperation("导出用户预约记录")
@ -75,4 +80,10 @@ public class ReservationController {
reservationService.exportExcel(response, userId);
}
@ApiOperation("全年账单数据导出")
@GetMapping("/payment")
public void exportPayments(HttpServletResponse response, @RequestParam(name = "year", defaultValue = "current") String yearFilter) {
// 调用服务层导出方法
reservationService.exportPayments(response, yearFilter);
}
}

@ -1,5 +1,6 @@
package com.example.venue_reservation_service.controller;
import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.example.venue_reservation_service.domain.School;
import com.example.venue_reservation_service.service.SchoolService;
@ -30,16 +31,10 @@ public class SchoolController {
return schoolService.userCertify(school);
}
@ApiOperation("修改认证信息")
@PostMapping("/update")
public Result update(@RequestBody School school){
return schoolService.updateCertify(school);
}
@ApiOperation("获取用户认证信息")
@GetMapping("/detail/{userId}")
public Result detail(@PathVariable("userId") Integer userId){
return Result.ok(schoolService.getOne(Wrappers.<School>lambdaQuery().eq(School::getUserId, userId))).message("查询成功");
return schoolService.getCertify(userId);
}
}

@ -19,7 +19,7 @@ import java.time.LocalTime;
@RestController
@RequestMapping("/user")
@Tag(name = "用户模块", description = "用户模块相关接口,包含登录、信息管理、充值等功能")
@Tag(name = "用户接口管理", description = "用户模块相关接口,包含登录、信息管理、充值等功能")
@CrossOrigin
public class UserController {
@ -116,7 +116,7 @@ public class UserController {
@Operation(
summary = "校验用户身份",
description = "校验用户提交的身份信息(如身份证、学生证等)",
description = "校验用户提交的身份信息(如等)",
parameters = {
@Parameter(
name = "dto",

@ -55,6 +55,4 @@ public class Information implements Serializable {
@TableField(exist = false)
private Double price;
}

@ -5,9 +5,7 @@ import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.AllArgsConstructor;

@ -67,6 +67,16 @@ public class Question implements Serializable {
*/
private String type;
/**
* 10
*/
private Integer toUser;
/**
* 10
*/
private Integer toAdmin;
@TableField(exist = false)
private static final long serialVersionUID = 1L;
}

@ -76,6 +76,18 @@ public class Reservation implements Serializable {
*/
private Integer payId;
/**
*
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime createTime;
/**
*
*/
private Integer isDelete;
@TableField(exist = false)
private static final long serialVersionUID = 1L;

@ -21,12 +21,12 @@ public class School implements Serializable {
private Integer id;
/**
*
*
*/
private String schoolNumber;
/**
*
*
*/
private String type;

@ -54,11 +54,6 @@ public class Type implements Serializable {
@TableField(exist = false)
private List<String> venues;
@TableField(exist = false)
private static final long serialVersionUID = 1L;
}

@ -0,0 +1,13 @@
package com.example.venue_reservation_service.dto;
import lombok.Data;
import java.util.List;
@Data
public class DelDTO {
List<Integer> list;
Integer userId;
}

@ -8,10 +8,6 @@ import lombok.EqualsAndHashCode;
@Schema(description = "用户查询自己的提问")
public class QuestionQueryDTO extends PageDTO{
// 场馆
@Schema(description = "场馆")
private String type;
// 状态
@Schema(description = "状态1待处理2已处理")
private Integer status;

@ -11,7 +11,6 @@ import java.time.LocalDateTime;
@Data
public class ReplyDTO {
/**
*
*/

@ -6,7 +6,7 @@ import lombok.Data;
import java.time.LocalDateTime;
@Data
@Schema(description = "分类查询,用于用户预约订单查询,管理员留言查询")
@Schema(description = "用户预约订单查询")
public class ReservationDTO extends PageDTO{
// 用户编号
@ -14,7 +14,7 @@ public class ReservationDTO extends PageDTO{
private Integer userId;
// 预约订单状态
@Schema(description = "状态")
@Schema(description = "预约订单状态")
private Integer status;
}

@ -0,0 +1,18 @@
package com.example.venue_reservation_service.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Data
@Schema(description = "用户签到对象")
public class SignInDTO {
@Schema(description = "预约订单编号")
private Integer reservationId;
@Schema(description = "场地编号")
private Integer venueId;
@Schema(description = "用户编号")
private Integer userId;
}

@ -50,21 +50,6 @@ public class GlobalExceptionHandler {
return Result.fail().message("头像上传失败,请稍后重试");
}
@ExceptionHandler(IdentityException.class)
public Result handleIdentityException(IdentityException e) {
log.error("身份认证业务异常: {} - {}", e.getErrorCode(), e.getMessage());
recordException(e, "IdentityException");
// 根据错误码返回不同提示(示例)
if ("IDENTITY_002".equals(e.getErrorCode())) {
return Result.fail().message("账号未注册,请联系管理员");
} else if ("IDENTITY_004".equals(e.getErrorCode())) {
return Result.fail().message("网络连接超时,请稍后重试");
} else {
return Result.fail().message(e.getMessage());
}
}
// 新增敏感词过滤异常处理
@ExceptionHandler(SensitiveFilterException.class)
public Result handleSensitiveFilterException(SensitiveFilterException e) {
@ -93,17 +78,14 @@ public class GlobalExceptionHandler {
}
}
/**
*
*/
@ExceptionHandler(SystemException.class)
public Result handleSystemException(SystemException e) {
log.error("系统级异常 [错误码:{}]: {}", e.getErrorCode(), e.getMessage(), e);
recordException(e, "SystemException");
return Result.fail().message(e.getMessage());
// 身份认证API调用异常处理
@ExceptionHandler(IdentityApiException.class)
public Result handleIdentityApiException(IdentityApiException e) {
log.error("身份认证接口调用失败: {}", e.getMessage(), e);
recordException(e, "IdentityApiException");
return Result.fail().message("身份认证服务暂时不可用,请稍后再试");
}
// 记录异常到数据库
private void recordException(Exception e, String exceptionType) {
try {

@ -0,0 +1,8 @@
package com.example.venue_reservation_service.exception;
// 身份认证调用异常
public class IdentityApiException extends RuntimeException {
public IdentityApiException(String message) {
super(message);
}
}

@ -1,23 +0,0 @@
package com.example.venue_reservation_service.exception;
/**
*
*/
public class IdentityException extends RuntimeException {
private final String errorCode;
public IdentityException(String message) {
super(message);
this.errorCode = "IDENTITY_001"; // 默认为通用身份认证错误码
}
public IdentityException(String errorCode, String message) {
super(message);
this.errorCode = errorCode;
}
public String getErrorCode() {
return errorCode;
}
}

@ -0,0 +1,8 @@
package com.example.venue_reservation_service.exception;
// 教职工信息未找到异常
public class StaffNotFoundException extends RuntimeException {
public StaffNotFoundException(String message) {
super(message);
}
}

@ -1,32 +0,0 @@
package com.example.venue_reservation_service.exception;
/**
* -
*/
public class SystemException extends RuntimeException {
private final String errorCode;
public SystemException(String message) {
super(message);
this.errorCode = "SYS_001"; // 默认系统异常错误码
}
public SystemException(String message, Throwable cause) {
super(message, cause);
this.errorCode = "SYS_001";
}
public SystemException(String errorCode, String message) {
super(message);
this.errorCode = errorCode;
}
public SystemException(String errorCode, String message, Throwable cause) {
super(message, cause);
this.errorCode = errorCode;
}
public String getErrorCode() {
return errorCode;
}
}

@ -3,6 +3,7 @@ package com.example.venue_reservation_service.mapper;
import com.example.venue_reservation_service.domain.Admin;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
/**
* @author 31586
@ -13,6 +14,9 @@ import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface AdminMapper extends BaseMapper<Admin> {
String selectVenueByUserId(@Param("userId") Integer userId);
}

@ -2,6 +2,7 @@ package com.example.venue_reservation_service.service;
import com.example.venue_reservation_service.domain.Comment;
import com.baomidou.mybatisplus.extension.service.IService;
import com.example.venue_reservation_service.dto.DelDTO;
import com.example.venue_reservation_service.dto.PageDTO;
import com.example.venue_reservation_service.dto.SearchDTO;
import com.example.venue_reservation_service.vo.Result;
@ -22,4 +23,8 @@ public interface CommentService extends IService<Comment> {
Result withdrawComment(Integer id);
Result like(Integer userId, Integer commentId);
Result singleRemove(Integer userId, Integer commentId);
Result batchRemove(DelDTO dto);
}

@ -18,5 +18,6 @@ public interface QuestionService extends IService<Question> {
Result userPage(QuestionQueryDTO dto);
Result adminPage(ReservationDTO dto);
Result remove(Integer userId, Integer id);
}

@ -6,7 +6,8 @@ import com.example.venue_reservation_service.dto.ReplyDTO;
import com.example.venue_reservation_service.vo.Result;
public interface ReplyService extends IService<Reply> {
Result createReply(ReplyDTO dto);
Result updateReply(ReplyDTO dto);
Result viewReply(Integer id);
}

@ -2,9 +2,7 @@ package com.example.venue_reservation_service.service;
import com.example.venue_reservation_service.domain.Reservation;
import com.baomidou.mybatisplus.extension.service.IService;
import com.example.venue_reservation_service.dto.RAddDTO;
import com.example.venue_reservation_service.dto.ReservationDTO;
import com.example.venue_reservation_service.dto.SlotDTO;
import com.example.venue_reservation_service.dto.*;
import com.example.venue_reservation_service.vo.Result;
import jakarta.servlet.http.HttpServletResponse;
@ -21,12 +19,19 @@ public interface ReservationService extends IService<Reservation> {
Result cancelReservation(Integer reservationId);
Result signInReservation(Integer reservationId);
Result signInReservation(SignInDTO dto);
Result queryDetail(Integer id);
Result exportData(String time);
void dealReservation(Integer reservationId);
void exportExcel(HttpServletResponse response, Integer userId);
Result removeBatch(DelDTO dto);
Result removeSingle(Integer userId, Integer id);
void exportPayments(HttpServletResponse response, String yearFilter);
}

@ -15,6 +15,6 @@ public interface SchoolService extends IService<School> {
Result userCertify(School school);
Result updateCertify(School school);
Result getCertify(Integer userId);
}

@ -9,6 +9,7 @@ import com.example.venue_reservation_service.converter.ListConverter;
import com.example.venue_reservation_service.domain.Comment;
import com.example.venue_reservation_service.domain.User;
import com.example.venue_reservation_service.domain.UserLike;
import com.example.venue_reservation_service.dto.DelDTO;
import com.example.venue_reservation_service.dto.PageDTO;
import com.example.venue_reservation_service.dto.SearchDTO;
import com.example.venue_reservation_service.exception.SensitiveFilterException;
@ -29,6 +30,7 @@ import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
/**
@ -154,6 +156,26 @@ public class CommentServiceImpl extends ServiceImpl<CommentMapper, Comment>
return Result.ok().message(like.getIsDelete() == 1 ? "取消点赞" : "点赞成功");
}
@Override
public Result singleRemove(Integer userId, Integer commentId) {
Comment comment = getById(commentId);
if(Objects.equals(comment.getUserId(), userId)){
removeById(commentId);
}
return Result.ok().message("删除成功");
}
@Override
public Result batchRemove(DelDTO dto) {
for (Integer commentId : dto.getList()) {
Comment comment = getById(commentId);
if(Objects.equals(comment.getUserId(), dto.getUserId())){
removeById(commentId);
}
}
return Result.ok().message("清理成功");
}
}

@ -4,22 +4,30 @@ import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.Query;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.venue_reservation_service.domain.Question;
import com.example.venue_reservation_service.domain.Reply;
import com.example.venue_reservation_service.domain.User;
import com.example.venue_reservation_service.dto.QuestionDTO;
import com.example.venue_reservation_service.dto.QuestionQueryDTO;
import com.example.venue_reservation_service.dto.ReservationDTO;
import com.example.venue_reservation_service.mapper.AdminMapper;
import com.example.venue_reservation_service.mapper.QuestionMapper;
import com.example.venue_reservation_service.mapper.ReplyMapper;
import com.example.venue_reservation_service.mapper.UserMapper;
import com.example.venue_reservation_service.service.QuestionService;
import com.example.venue_reservation_service.vo.QueryVO;
import com.example.venue_reservation_service.vo.Result;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
/**
@ -32,10 +40,19 @@ import java.util.Optional;
public class QuestionServiceImpl extends ServiceImpl<QuestionMapper, Question>
implements QuestionService{
@Resource
private UserMapper userMapper;
@Resource
private AdminMapper adminMapper;
@Resource
private ReplyMapper replyMapper;
@Override
public Result create(QuestionDTO dto) {
String word = dto.getDescription().strip();
String word = dto.getDescription().trim();
Question question = lambdaQuery()
.eq(Question::getDescription, word)
.eq(Question::getUserId, dto.getUserId())
@ -48,40 +65,54 @@ public class QuestionServiceImpl extends ServiceImpl<QuestionMapper, Question>
question.setStatus(0);
question.setCreatedTime(LocalDateTime.now());
}
question.setToUser(1);
saveOrUpdate(question);
return Result.ok().message("保存问题成功");
return Result.ok(question).message("保存问题成功");
}
@Override
public Result userPage(QuestionQueryDTO dto) {
Page<Question> page = new Page<>(dto.getCurrent(), dto.getSize());
return Result.ok().message("查询成功");
}
@Override
public Result adminPage(ReservationDTO dto) {
Page<Question> page = Page.of(dto.getCurrent(), dto.getSize());
page.addOrder(OrderItem.desc("created_time"));
LambdaQueryWrapper<Question> wrapper = new LambdaQueryWrapper<>();
if (dto.getStatus() != null) {
User user = userMapper.selectById(dto.getUserId());
if (Optional.ofNullable(user).isEmpty()) {
return Result.fail().message("用户信息不存在");
}
LambdaQueryWrapper<Question> wrapper = Wrappers.lambdaQuery();
Integer type = user.getType();
if(type == 3){
// 管理员查看所管理场馆中的订单
String venue = adminMapper.selectVenueByUserId(user.getId());
wrapper.eq(Question::getType, venue)
.eq(Question::getToAdmin, 1);
}else{
wrapper.eq(Question::getUserId, user.getId())
.eq(Question::getToUser, 1);
}
if(dto.getStatus() != 2){
wrapper.eq(Question::getStatus, dto.getStatus());
}
Page<Question> resultPage = page(page, wrapper);
wrapper.orderByDesc(Question::getCreatedTime);
page = page(page, wrapper);
QueryVO<Question> vo = new QueryVO<>();
vo.setList(resultPage.getRecords());
vo.setTotal(resultPage.getTotal());
vo.setList(page.getRecords());
vo.setTotal(page.getTotal());
return Result.ok(vo).message("查询成功");
}
@Override
public Result remove(Integer userId, Integer id) {
Question question = getById(id);
if (Optional.ofNullable(question).isEmpty()) {
return Result.fail().message("未查询到问题信息");
}
if (!Objects.equals(question.getUserId(), userId)) {
return Result.fail().message("非本人提问,不可删除");
}
if (question.getStatus() == 1) {
replyMapper.delete(Wrappers.<Reply>lambdaQuery().eq(Reply::getQuestionId, id));
}
removeById(id);
return Result.ok(question).message("移除成功");
}
}

@ -1,19 +1,25 @@
package com.example.venue_reservation_service.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.baomidou.mybatisplus.extension.toolkit.Db;
import com.example.venue_reservation_service.domain.Question;
import com.example.venue_reservation_service.domain.Reply;
import com.example.venue_reservation_service.dto.ReplyDTO;
import com.example.venue_reservation_service.mapper.QuestionMapper;
import com.example.venue_reservation_service.mapper.UserMapper;
import com.example.venue_reservation_service.service.ReplyService;
import com.example.venue_reservation_service.mapper.ReplyMapper;
import com.example.venue_reservation_service.vo.Result;
import jakarta.annotation.Resource;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
import java.util.Objects;
import java.util.Optional;
/**
* @author 31586
@ -24,52 +30,47 @@ import java.util.Objects;
public class ReplyServiceImpl extends ServiceImpl<ReplyMapper, Reply>
implements ReplyService{
@Resource
private UserMapper userMapper;
@Resource
private QuestionMapper questionMapper;
@Override
public Result createReply(ReplyDTO dto) {
String content = dto.getContent().trim();
if (content.isEmpty()) {
if (StrUtil.isBlank(content)) {
return Result.fail("回复内容不能为空");
}
Reply reply = new Reply();
BeanUtils.copyProperties(dto, reply);
reply.setCreatedTime(LocalDateTime.now());
Reply reply = getOne(Wrappers.<Reply>lambdaQuery()
.eq(Reply::getAdminId, dto.getAdminId())
.eq(Reply::getQuestionId, dto.getQuestionId()));
if (Optional.ofNullable(reply).isEmpty()) {
reply = BeanUtil.copyProperties(dto, Reply.class);
reply.setCreatedTime(LocalDateTime.now());
}else{
reply.setContent(dto.getContent());
}
reply.setUpdatedTime(LocalDateTime.now());
save(reply);
Db.lambdaUpdate(Question.class)
.set(Question::getStatus, 1)
.eq(Question::getId, dto.getQuestionId())
.update();
return Result.ok().message("保存回复成功");
saveOrUpdate(reply);
Question question = questionMapper.selectById(reply.getQuestionId());
if (Optional.ofNullable(question).isPresent() && question.getStatus() == 0) {
question.setStatus(1);
questionMapper.updateById(question);
}
return Result.ok(reply).message("回复成功");
}
@Override
public Result updateReply( ReplyDTO dto) {
String content = dto.getContent().trim();
if (content.isEmpty()) {
return Result.fail("回复内容不能为空");
public Result viewReply(Integer id) {
Question question = questionMapper.selectById(id);
if (Optional.ofNullable(question).isEmpty()) {
return Result.fail().message("问题信息不存在");
}
String oldContent = lambdaQuery()
.eq(Reply::getQuestionId, dto.getQuestionId())
.eq(Reply::getAdminId, dto.getAdminId())
.one().getContent();
if(Objects.equals(oldContent, content)) {
return Result.fail().message("回复内容未修改");
if (question.getStatus() == 0) {
return Result.ok().message("该问题未被回复");
}
lambdaUpdate()
.set(Reply::getContent, content)
.set(Reply::getUpdatedTime, LocalDateTime.now())
.eq(Reply::getQuestionId, dto.getQuestionId())
.eq(Reply::getAdminId, dto.getAdminId())
.update();
return Result.ok().message("保存回复成功");
return Result.ok(getOne(Wrappers.<Reply>lambdaQuery().eq(Reply::getQuestionId, id))).message("加载成功");
}
}

@ -1,13 +1,17 @@
package com.example.venue_reservation_service.service.impl;
import cn.hutool.core.bean.BeanUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.venue_reservation_service.domain.*;
import com.example.venue_reservation_service.dto.DelDTO;
import com.example.venue_reservation_service.dto.RAddDTO;
import com.example.venue_reservation_service.dto.ReservationDTO;
import com.example.venue_reservation_service.dto.SignInDTO;
import com.example.venue_reservation_service.mapper.*;
import com.example.venue_reservation_service.mq.DelayMessageSender;
import com.example.venue_reservation_service.service.*;
@ -15,6 +19,7 @@ import com.example.venue_reservation_service.utils.DateUtil;
import com.example.venue_reservation_service.utils.DownExcel;
import com.example.venue_reservation_service.utils.ScheduleUtil;
import com.example.venue_reservation_service.vo.*;
import com.example.venue_reservation_service.vo.excel.PaymentExportDTO;
import com.example.venue_reservation_service.vo.excel.ReservationExcel;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
@ -25,10 +30,12 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.io.IOException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.time.*;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.stream.Collectors;
/**
* @author 31586
@ -189,6 +196,8 @@ public class ReservationServiceImpl extends ServiceImpl<ReservationMapper, Reser
// 设置预约开始和结束时间
reservation.setStartTime(start);
reservation.setEndTime(end);
reservation.setCreateTime(LocalDateTime.now());
reservation.setIsDelete(0);
// 保存预约信息
save(reservation);
@ -228,9 +237,11 @@ public class ReservationServiceImpl extends ServiceImpl<ReservationMapper, Reser
// 修改交易记录
Payment payment = paymentService.getById(reservation.getPayId());
payment.setSituation("过期");
paymentService.updateById(payment);
// 归还支付金额
balanceService.returnMoney(reservation.getUserId(), payment.getAmount());
payment.setAmount(0.0);
paymentService.updateById(payment);
}
}
}
@ -268,7 +279,7 @@ public class ReservationServiceImpl extends ServiceImpl<ReservationMapper, Reser
wrapper.eq(Reservation::getUserId, userId);
}
wrapper.orderByDesc(Reservation::getReservationDate);
wrapper.eq(Reservation::getIsDelete, 0).orderByDesc(Reservation::getReservationDate).orderByDesc(Reservation::getCreateTime);
page = page(page, wrapper);
@ -345,18 +356,25 @@ public class ReservationServiceImpl extends ServiceImpl<ReservationMapper, Reser
paymentService.updateById(payment);
// 修改用户账户余额
balanceService.returnMoney(reservation.getUserId(), payment.getAmount());
return Result.ok().message("预约订单取消成功");
}
@Override
public Result signInReservation(Integer reservationId) {
Reservation reservation = getById(reservationId);
public Result signInReservation(SignInDTO dto) {
Reservation reservation = getById(dto.getReservationId());
if (Optional.ofNullable(reservation).isEmpty()) {
return Result.fail().message("预约信息不存在");
}
if(!Objects.equals(reservation.getUserId(), dto.getUserId())){
return Result.fail().message("非本人订单");
}
if (!Objects.equals(reservation.getVenueId(), dto.getVenueId())) {
return Result.fail().message("非该场地二维码,请更换正确的");
}
if (reservation.getAuditStatus() != 1) {
return Result.fail().message("预约信息不为待签到状态");
}
@ -413,16 +431,138 @@ public class ReservationServiceImpl extends ServiceImpl<ReservationMapper, Reser
return Result.ok(detail).message("ok");
}
@Override
public Result exportData(String time) {
LocalDateTime startTime = null;
LocalDateTime endTime = LocalDateTime.now(); // 查询截止到当前时间
// 根据时间范围计算起始时间
switch (time) {
case "今年" -> startTime = LocalDateTime.of(LocalDateTime.now().getYear(), 1, 1, 0, 0, 0);
case "本月" -> {
YearMonth currentMonth = YearMonth.now();
startTime = LocalDateTime.of(currentMonth.getYear(), currentMonth.getMonthValue(), 1, 0, 0, 0);
}
case "近三月" -> startTime = LocalDateTime.now().minus(3, ChronoUnit.MONTHS);
}
// 构建查询条件
LambdaQueryWrapper<Reservation> queryWrapper = new LambdaQueryWrapper<>();
if (startTime != null) {
queryWrapper.ge(Reservation::getCreateTime, startTime)
.le(Reservation::getCreateTime, endTime);
}
// 附加逻辑删除条件Mybatis-plus默认会处理但显式添加更清晰
// queryWrapper.eq(Reservation::getIsDelete, 0);
return Result.ok(this.list(queryWrapper)).message("查询成功");
}
@Override
public void exportExcel(HttpServletResponse response, Integer userId) {
ReservationMapper mapper = getBaseMapper();
try {
DownExcel.download(response, ReservationExcel.class, mapper.selectByUserId(userId));
DownExcel.download(response, ReservationExcel.class, mapper.selectByUserId(userId), "reservation");
} catch (IOException | IllegalAccessException | InstantiationException e) {
throw new RuntimeException(e);
}
}
@Override
public Result removeBatch(DelDTO dto) {
List<Integer> list = dto.getList();
if(Optional.ofNullable(list).isEmpty() || list.size() == 0){
return Result.fail().message("请选择需要清理的数据");
}
int notDeleted = 0;
for (Integer id : list) {
Reservation reservation = getById(id);
if(reservation.getAuditStatus() == 1 || !Objects.equals(reservation.getUserId(), dto.getUserId()) || (reservation.getAuditStatus() == 2 && LocalDateTime.now().toLocalTime().isBefore(reservation.getEndTime()))){
notDeleted++;
continue;
}
reservation.setIsDelete(1);
updateById(reservation);
}
return Result.ok().message(notDeleted == 0 ? "清理成功" : "移除订单中,存在不可删除订单,已为您自动过滤");
}
@Override
public Result removeSingle(Integer userId, Integer id) {
Reservation reservation = getById(id);
if (Optional.ofNullable(reservation).isEmpty()) {
return Result.fail().message("订单信息不存在");
}
if (reservation.getAuditStatus() == 1) {
return Result.fail().message("订单处于待预约状态,不可删除");
}
if (reservation.getAuditStatus() == 2 && LocalDateTime.now().toLocalTime().isBefore(reservation.getEndTime())) {
return Result.fail().message("订单处于正在使用中状态,不可删除");
}
if (!Objects.equals(reservation.getUserId(), userId)) {
return Result.fail().message("非非本人订单");
}
reservation.setIsDelete(1);
updateById(reservation);
return Result.ok().message("订单删除成功");
}
@Override
public void exportPayments(HttpServletResponse response, String yearFilter) {
try {
// 确定要查询的年份
Year targetYear = parseYearFilter(yearFilter);
// 获取该年份所有账单
List<Payment> payments = getPaymentsForYear(targetYear);
List<PaymentExportDTO> dtos = payments.stream()
.map(PaymentExportDTO::fromEntity)
.collect(Collectors.toList());
// 设置响应头
String fileName = URLEncoder.encode(
String.format("交易账单_%s年数据", targetYear), StandardCharsets.UTF_8);
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setHeader("Content-Disposition", "attachment; filename=" + fileName + ".xlsx");
response.setCharacterEncoding("UTF-8");
// 导出Excel
EasyExcel.write(response.getOutputStream(), PaymentExportDTO.class)
.registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
.sheet("交易账单明细")
.doWrite(dtos);
} catch (IOException e) {
throw new RuntimeException("导出账单失败", e);
}
}
/**
*
* @param yearFilter current-, last-
* @return
*/
private Year parseYearFilter(String yearFilter) {
if ("last".equalsIgnoreCase(yearFilter)) {
return Year.now().minusYears(1);
}
// 默认返回今年
return Year.now();
}
/**
*
* @param year
* @return
*/
private List<Payment> getPaymentsForYear(Year year) {
// 计算该年份的开始和结束时间
LocalDateTime startOfYear = LocalDate.of(year.getValue(), 1, 1).atStartOfDay();
LocalDateTime endOfYear = LocalDate.of(year.getValue(), 12, 31).atTime(23, 59, 59);
return paymentService.list(Wrappers.<Payment>lambdaQuery()
.in(Payment::getSituation, "预约花费", "账户余额充值")
.between(Payment::getTime, startOfYear, endOfYear));
}
}

@ -1,13 +1,13 @@
package com.example.venue_reservation_service.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.venue_reservation_service.domain.School;
import com.example.venue_reservation_service.domain.User;
import com.example.venue_reservation_service.entity.PersonInfo;
import com.example.venue_reservation_service.entity.ResponseData;
import com.example.venue_reservation_service.exception.IdentityException;
import com.example.venue_reservation_service.exception.SystemException;
import com.example.venue_reservation_service.exception.IdentityApiException;
import com.example.venue_reservation_service.mapper.InstitutionMapper;
import com.example.venue_reservation_service.mapper.UserMapper;
import com.example.venue_reservation_service.service.SchoolService;
@ -20,12 +20,6 @@ import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import javax.crypto.NoSuchPaddingException;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.util.List;
import java.util.Optional;
/**
@ -55,94 +49,56 @@ public class SchoolServiceImpl extends ServiceImpl<SchoolMapper, School>
@Override
public Result userCertify(School school) {
// 基础用户校验(复用逻辑)
User user = validateUser(school.getUserId());
if (user == null) {
User user = userMapper.selectById(school.getUserId());
if (Optional.ofNullable(user).isEmpty()) {
return Result.fail().message("用户信息不存在");
}
// 设置用户类型
user.setType("学生".equals(school.getType()) ? 1 : 2);
// 教职工身份验证
if (user.getType() == 2) {
validateStaffIdentity(school);
// if(user.getIsCertify() == 1 && user.getOperableTimes() == 2){
// return Result.fail().message("修改次数已用完,请联系管理员");
// }
// 获取认证类型(教职工 or 学生)
if(!"学生".equals(school.getType())){
// 调用学校身份认证接口
PersonInfo info;
try {
String result = IdentityUtil.getGzzxList(school.getDescription());
ResponseData data = mapper.readValue(result, ResponseData.class);
if(data.getMessage().size() == 0){
return Result.fail().message("未查询到教职工信息");
}
info = data.getMessage().get(0);
} catch (Exception e) {
throw new IdentityApiException("身份认证服务暂时不可用,请稍后再试");
}
if(!school.getSchoolNumber().equals(info.getEmployeeId())){
return Result.fail().message("工号与联系方式不匹配");
}
}
// 更新用户认证状态
user.setOperableTimes(2);
School one = getOne(Wrappers.<School>lambdaQuery().eq(School::getUserId, school.getUserId()));
if(Optional.ofNullable(one).isEmpty()){
one = new School();
}
BeanUtil.copyProperties(school, one, "id");
saveOrUpdate(one);
user.setOperableTimes(user.getIsCertify() == 1 ? Math.max(user.getOperableTimes() - 1, 0) : 2);
user.setIsCertify(1);
userMapper.updateById(user);
// 保存学校信息
save(school);
return Result.ok(school).message("身份认证成功");
return Result.ok(one).message("身份认证成功");
}
@Override
public Result updateCertify(School school) {
// 基础用户校验(复用逻辑)
User user = validateUser(school.getUserId());
if (user == null) {
public Result getCertify(Integer userId) {
User user = userMapper.selectById(userId);
if (Optional.ofNullable(user).isEmpty()) {
return Result.fail().message("用户信息不存在");
}
// 校验修改次数
// if (user.getIsCertify() == 1 && user.getOperableTimes() <= 0) {
// return Result.fail().message("修改次数已用完,请联系管理员进行重置");
// }
// 更新用户认证状态
user.setOperableTimes(user.getOperableTimes() - 1);
user.setIsCertify(1);
userMapper.updateById(user);
// 更新学校信息
updateById(school);
return Result.ok().message("认证信息修改成功");
}
/**
*
*/
private User validateUser(Integer userId) {
return userMapper.selectById(userId);
}
/**
*
*/
private void validateStaffIdentity(School school) {
try {
// 调用身份认证接口
String res = IdentityUtil.getGzzxList(school.getSchoolNumber());
// 结果有效性校验
if ("-1".equals(res)) {
throw new IdentityException("身份认证接口调用失败,请检查参数");
}
// 解析JSON响应
ResponseData result = mapper.readValue(res, ResponseData.class);
if (!"true".equals(result.getSuccess()) || result.getMessage() == null || result.getMessage().isEmpty()) {
throw new IdentityException("身份信息异常,请稍后重试");
}
// 验证返回的教职工信息
PersonInfo info = result.getMessage().get(0);
if (!school.getSchoolNumber().equals(info.getEmployeeId()) ||
!school.getSchoolNumber().equals(info.getPhone())) {
throw new IdentityException("教职工信息不匹配");
}
} catch (NoSuchAlgorithmException | InvalidKeyException | NoSuchPaddingException e) {
throw new SystemException("加密组件异常,请联系管理员", e);
} catch (IOException e) {
throw new IdentityException("IDENTITY_004", "网络连接失败,请检查网络");
} catch (Exception e) {
throw new IdentityException("响应数据解析失败,请稍后重试");
if (user.getIsCertify() == 0) {
return Result.ok().message("用户未认证");
}
return Result.ok(getOne(Wrappers.<School>lambdaQuery().eq(School::getUserId, userId))).message("查询成功");
}
}

@ -8,11 +8,11 @@ import java.io.IOException;
import java.util.List;
public class DownExcel {
public static void download(HttpServletResponse response, Class t, List list) throws IOException, IllegalAccessException,InstantiationException {
public static void download(HttpServletResponse response, Class t, List list, String prefix) throws IOException, IllegalAccessException,InstantiationException {
String substring = UUID.randomUUID().toString().substring(0, 5);
response.setContentType("application/vnd.ms-excel");// 设置文本内省
response.setCharacterEncoding("UTF-8");// 设置字符编码
response.setHeader("Content-disposition", "attachment;filename=reservation-"+substring+".xlsx"); // 设置响应头
response.setHeader("Content-disposition", "attachment;filename="+prefix+"-"+substring+".xlsx"); // 设置响应头
EasyExcel.write(response.getOutputStream(), t)
.sheet("数据报表")
.doWrite(list); //用io流来写入数据

@ -0,0 +1,64 @@
package com.example.venue_reservation_service.vo.excel;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.write.style.*;
import com.alibaba.excel.enums.BooleanEnum;
import com.alibaba.excel.enums.poi.HorizontalAlignmentEnum;
import com.example.venue_reservation_service.domain.Payment;
import lombok.Data;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
/**
*
*/
@Data
@ContentFontStyle(fontName = "楷体", fontHeightInPoints = 16) // 内容字体
@HeadFontStyle(fontName = "楷体", fontHeightInPoints = 16, bold = BooleanEnum.TRUE) // 表头字体
@HeadStyle(horizontalAlignment = HorizontalAlignmentEnum.CENTER) // 表头居中
@ContentStyle(horizontalAlignment = HorizontalAlignmentEnum.CENTER) // 内容居中
@ContentRowHeight(25) // 内容行高
@HeadRowHeight(30) // 表头行高
@ColumnWidth(30) // 默认列宽
public class PaymentExportDTO {
@ExcelProperty(value = "编号", index = 0)
private String id;
@ExcelProperty(value = "用户编号", index = 1)
@ColumnWidth(15) // 单独设置列宽
private String userId;
@ExcelProperty(value = "交易金额(元)", index = 2)
@ColumnWidth(18)
private String amount;
@ExcelProperty(value = "交易类型", index = 3)
private String situation;
@ExcelProperty(value = "交易时间", index = 4)
@ColumnWidth(25)
private String time;
// 将实体对象转换为导出DTO
public static PaymentExportDTO fromEntity(Payment payment) {
PaymentExportDTO dto = new PaymentExportDTO();
dto.setId(String.valueOf(payment.getId()));
dto.setUserId(String.valueOf(payment.getUserId()));
dto.setAmount(String.format("¥%.2f", payment.getAmount()));
dto.setSituation(translateSituation(payment.getSituation()));
dto.setTime(payment.getTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
return dto;
}
// 交易类型翻译
private static String translateSituation(String situation) {
switch (situation) {
case "支出": return "预约花费";
case "支入": return "账户充值";
case "超时": return "未签到超时";
case "取消": return "预约取消";
default: return situation;
}
}
}

@ -15,4 +15,10 @@
id,user_id,type_id,
update_time
</sql>
<select id="selectVenueByUserId" parameterType="integer" resultType="string">
SELECT t.vname FROM venue_admin a
JOIN venue_type t ON a.type_id = t.id
WHERE a.user_id = #{userId}
</select>
</mapper>

@ -2,6 +2,7 @@ package com.example.venue_reservation_service;
import cn.hutool.json.JSONUtil;
import com.example.venue_reservation_service.entity.PersonInfo;
import com.example.venue_reservation_service.entity.ResponseData;
import com.example.venue_reservation_service.service.ReservationService;
import com.example.venue_reservation_service.utils.IdentityUtil;
import com.example.venue_reservation_service.utils.MD5Util;
import com.fasterxml.jackson.core.JsonProcessingException;
@ -18,7 +19,7 @@ class VenueReservationServiceApplicationTests {
@Resource
private RestTemplate restTemplate;
private ReservationService reservationService;
@Test
void contextLoads() throws Exception {
@ -30,7 +31,8 @@ class VenueReservationServiceApplicationTests {
public static void main(String[] args) throws Exception {
String result = IdentityUtil.getGzzxList("13767489908");
System.out.println(result);
ResponseData data = objectMapper.readValue(result, ResponseData.class);
System.out.println(data.getMessage().get(0));
}
// public static void main(String[] args) {

@ -21,7 +21,7 @@ public class IfsDcpIcdcShareTest {
// + "<method>cgyy_dcpint_getJbxx</method>"
+ "<method>getJzgjcxx2</method>"
// +"<sender>08192ec57d80193b9fa4b9a0</sender>"
+"<params>pageSize=8&pageNo=1&SJHM=13767489908</params>"
+"<params>pageSize=10&pageNo=1</params>"
// +"<params>GH=1966&pageSize=5&pageNo=1</params>"
//+"<params>STUDENTID=2017</params>"
+ "</param>";

Loading…
Cancel
Save