diff --git a/pom.xml b/pom.xml index ef36511..a3f2635 100644 --- a/pom.xml +++ b/pom.xml @@ -229,6 +229,10 @@ org.springframework.boot spring-boot-starter-data-mongodb + + org.springframework.boot + spring-boot-starter-mail + diff --git a/src/main/java/com/example/venue_reservation_service/config/InterceptorConfig.java b/src/main/java/com/example/venue_reservation_service/config/InterceptorConfig.java index c4d75e5..b4c42ed 100644 --- a/src/main/java/com/example/venue_reservation_service/config/InterceptorConfig.java +++ b/src/main/java/com/example/venue_reservation_service/config/InterceptorConfig.java @@ -20,6 +20,7 @@ public class InterceptorConfig implements WebMvcConfigurer { .addPathPatterns("/school/**") .excludePathPatterns("/user/test") .excludePathPatterns("/user/admin") + .excludePathPatterns("/user/reset") .excludePathPatterns("/reservation/excel") .excludePathPatterns("/reservation/payment") .excludePathPatterns("/swagger-ui/index.html") diff --git a/src/main/java/com/example/venue_reservation_service/controller/DeviceController.java b/src/main/java/com/example/venue_reservation_service/controller/DeviceController.java new file mode 100644 index 0000000..b1f4d48 --- /dev/null +++ b/src/main/java/com/example/venue_reservation_service/controller/DeviceController.java @@ -0,0 +1,57 @@ +package com.example.venue_reservation_service.controller; + +import com.example.venue_reservation_service.domain.Device; +import com.example.venue_reservation_service.mapper.DeviceMapper; +import com.example.venue_reservation_service.service.DeviceService; +import com.example.venue_reservation_service.vo.Result; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import jakarta.annotation.Resource; +import org.springframework.messaging.simp.SimpMessagingTemplate; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.web.bind.annotation.CrossOrigin; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; + +@RestController +@RequestMapping("/device") +@Api("设备数据管理") +@CrossOrigin +public class DeviceController { + + @Resource + private DeviceService deviceService; + + @Resource + private DeviceMapper deviceMapper; + + @Resource + private SimpMessagingTemplate messagingTemplate; + + // 获取最新设备数据 + @ApiOperation("获取最新设备数据") + @GetMapping("/latest") + public Result getLatestDevices() { + return Result.ok(deviceService.getLatestDevices()).message("加载成功"); + } +// + // 定时任务 - 每秒生成一条数据 +// @Scheduled(fixedRate = 1000) +// public void generateAndSendDeviceData() { +// // 生成并保存新数据 +// Device newDevice = deviceService.generateDeviceData(); +// deviceService.save(newDevice); +// +// // 检查并清理旧数据 +// long count = deviceService.count(); +// if (count > 100) { +// deviceMapper.deleteOldestRecords(50); +// } +// +// // 推送新数据到前端 +// messagingTemplate.convertAndSend("/topic/devices", newDevice); +// } +} \ No newline at end of file diff --git a/src/main/java/com/example/venue_reservation_service/controller/InformationController.java b/src/main/java/com/example/venue_reservation_service/controller/InformationController.java index 7a3fa15..87814ff 100644 --- a/src/main/java/com/example/venue_reservation_service/controller/InformationController.java +++ b/src/main/java/com/example/venue_reservation_service/controller/InformationController.java @@ -34,7 +34,7 @@ public class InformationController { @ApiOperation("获取某个场馆内的所有场地数据") @GetMapping("/detail") - public Result detail(@RequestParam("type_id")Integer typeId){ + public Result detail(@RequestParam("type_id") Integer typeId){ return informationService.getDetails(typeId); } diff --git a/src/main/java/com/example/venue_reservation_service/controller/ReservationController.java b/src/main/java/com/example/venue_reservation_service/controller/ReservationController.java index d068d01..4d9a8cc 100644 --- a/src/main/java/com/example/venue_reservation_service/controller/ReservationController.java +++ b/src/main/java/com/example/venue_reservation_service/controller/ReservationController.java @@ -1,22 +1,15 @@ 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.*; +import com.example.venue_reservation_service.mapper.ReservationMapper; import com.example.venue_reservation_service.service.ReservationService; -import com.example.venue_reservation_service.utils.DownExcel; import com.example.venue_reservation_service.vo.Result; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import jakarta.annotation.Resource; import jakarta.servlet.http.HttpServletResponse; -import org.apache.ibatis.annotations.Param; import org.springframework.web.bind.annotation.*; -import javax.ws.rs.Path; -import java.io.IOException; -import java.util.List; - @RestController @RequestMapping("/reservation") @Api("预约操作管理") @@ -26,6 +19,14 @@ public class ReservationController { @Resource private ReservationService reservationService; + @Resource + private ReservationMapper reservationMapper; + + @GetMapping("/list") + public Result userList(@RequestParam("userId") Integer userId){ + return Result.ok(reservationMapper.selectByUserId(userId)).message("查询成功"); + } + @ApiOperation("添加预约信息") @PostMapping("/create") public Result create(@RequestBody RAddDTO dto){ @@ -86,4 +87,11 @@ public class ReservationController { // 调用服务层导出方法 reservationService.exportPayments(response, yearFilter); } + + @ApiOperation("智能场地推荐") + @GetMapping("/recommend") + public Result recommend(@RequestParam("userId") Integer userId){ + return reservationService.recommend(userId); + } + } diff --git a/src/main/java/com/example/venue_reservation_service/controller/UserController.java b/src/main/java/com/example/venue_reservation_service/controller/UserController.java index 0709696..9da8174 100644 --- a/src/main/java/com/example/venue_reservation_service/controller/UserController.java +++ b/src/main/java/com/example/venue_reservation_service/controller/UserController.java @@ -5,6 +5,7 @@ import com.example.venue_reservation_service.dto.*; import com.example.venue_reservation_service.mq.DelayMessageSender; import com.example.venue_reservation_service.service.UserService; import com.example.venue_reservation_service.vo.Result; +import io.swagger.annotations.ApiOperation; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.media.Schema; @@ -289,4 +290,10 @@ public class UserController { public Result info(@PathVariable("id") Integer userId) { return userService.getUserInfo(userId); } + + @ApiOperation("基于qq邮箱重置密码") + @PostMapping("/reset") + public Result reset(@RequestBody ResetDTO dto){ + return userService.passwordReset(dto); + } } \ No newline at end of file diff --git a/src/main/java/com/example/venue_reservation_service/domain/Device.java b/src/main/java/com/example/venue_reservation_service/domain/Device.java new file mode 100644 index 0000000..f374da4 --- /dev/null +++ b/src/main/java/com/example/venue_reservation_service/domain/Device.java @@ -0,0 +1,57 @@ +package com.example.venue_reservation_service.domain; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import java.time.LocalDateTime; +import java.util.Date; + +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +/** + * + * @TableName venue_device + */ +@TableName(value ="venue_device") +@Data +public class Device implements Serializable { + /** + * + */ + @TableId(type = IdType.AUTO) + private Integer id; + + /** + * + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime timestamp; + + /** + * + */ + private Double temperature; + + /** + * + */ + private Double humidity; + + /** + * + */ + private Integer fanStatus; + + /** + * + */ + private Integer warningStatus; + + @TableField(exist = false) + private static final long serialVersionUID = 1L; +} \ No newline at end of file diff --git a/src/main/java/com/example/venue_reservation_service/domain/Information.java b/src/main/java/com/example/venue_reservation_service/domain/Information.java index 70e192d..05a748a 100644 --- a/src/main/java/com/example/venue_reservation_service/domain/Information.java +++ b/src/main/java/com/example/venue_reservation_service/domain/Information.java @@ -5,7 +5,11 @@ import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import java.io.Serializable; +import java.time.LocalDateTime; + +import com.fasterxml.jackson.annotation.JsonFormat; import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; /** * @@ -50,6 +54,13 @@ public class Information implements Serializable { */ private String qrCode; + /** + * 场地创建时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime updateTime; + @TableField(exist = false) private static final long serialVersionUID = 1L; diff --git a/src/main/java/com/example/venue_reservation_service/dto/ResetDTO.java b/src/main/java/com/example/venue_reservation_service/dto/ResetDTO.java new file mode 100644 index 0000000..59ee737 --- /dev/null +++ b/src/main/java/com/example/venue_reservation_service/dto/ResetDTO.java @@ -0,0 +1,11 @@ +package com.example.venue_reservation_service.dto; + +import lombok.Data; + +@Data +public class ResetDTO { + + private String phone; + + private String email; +} diff --git a/src/main/java/com/example/venue_reservation_service/entity/RecommendVO.java b/src/main/java/com/example/venue_reservation_service/entity/RecommendVO.java new file mode 100644 index 0000000..b6ec52d --- /dev/null +++ b/src/main/java/com/example/venue_reservation_service/entity/RecommendVO.java @@ -0,0 +1,15 @@ +package com.example.venue_reservation_service.entity; + +import com.example.venue_reservation_service.domain.Information; +import com.example.venue_reservation_service.vo.excel.ReservationExcel; +import lombok.Data; + +@Data +public class RecommendVO { + + private ReservationExcel excel; + + private Information information; + + private Double price; +} diff --git a/src/main/java/com/example/venue_reservation_service/mapper/DeviceMapper.java b/src/main/java/com/example/venue_reservation_service/mapper/DeviceMapper.java new file mode 100644 index 0000000..edb9c56 --- /dev/null +++ b/src/main/java/com/example/venue_reservation_service/mapper/DeviceMapper.java @@ -0,0 +1,31 @@ +package com.example.venue_reservation_service.mapper; + +import com.example.venue_reservation_service.domain.Device; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Delete; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; + +import java.util.List; + +/** +* @author 31586 +* @description 针对表【venue_device】的数据库操作Mapper +* @createDate 2025-06-29 14:38:46 +* @Entity generator.domain.Device +*/ +@Mapper +public interface DeviceMapper extends BaseMapper { + + @Select("SELECT * FROM venue_device ORDER BY timestamp DESC LIMIT #{limit}") + List selectLatestDevices(@Param("limit") int limit); + + @Delete("DELETE FROM venue_device ORDER BY timestamp ASC LIMIT #{count}") + void deleteOldestRecords(@Param("count") int count); + +} + + + + diff --git a/src/main/java/com/example/venue_reservation_service/netty/NettyChatServer.java b/src/main/java/com/example/venue_reservation_service/netty/NettyChatServer.java index e70cb68..9418c4b 100644 --- a/src/main/java/com/example/venue_reservation_service/netty/NettyChatServer.java +++ b/src/main/java/com/example/venue_reservation_service/netty/NettyChatServer.java @@ -15,6 +15,7 @@ import io.netty.handler.codec.http.websocketx.extensions.compression.WebSocketSe import io.netty.handler.stream.ChunkedWriteHandler; import jakarta.annotation.PostConstruct; import jakarta.annotation.PreDestroy; +import jakarta.annotation.Resource; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; @@ -25,7 +26,7 @@ public class NettyChatServer { @Value("${server.netty.port}") private int port; - @Autowired + @Resource private ChatServerHandler chatServerHandler; // 确保正确注入 private EventLoopGroup bossGroup; diff --git a/src/main/java/com/example/venue_reservation_service/repository/ChatMessageRepository.java b/src/main/java/com/example/venue_reservation_service/repository/ChatMessageRepository.java index 7709b72..2f1815d 100644 --- a/src/main/java/com/example/venue_reservation_service/repository/ChatMessageRepository.java +++ b/src/main/java/com/example/venue_reservation_service/repository/ChatMessageRepository.java @@ -4,6 +4,7 @@ import com.example.venue_reservation_service.entity.ChatMessage; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.mongodb.repository.MongoRepository; + import java.time.LocalDateTime; public interface ChatMessageRepository extends MongoRepository { diff --git a/src/main/java/com/example/venue_reservation_service/service/DeviceService.java b/src/main/java/com/example/venue_reservation_service/service/DeviceService.java new file mode 100644 index 0000000..f89d442 --- /dev/null +++ b/src/main/java/com/example/venue_reservation_service/service/DeviceService.java @@ -0,0 +1,17 @@ +package com.example.venue_reservation_service.service; + +import com.example.venue_reservation_service.domain.Device; +import com.baomidou.mybatisplus.extension.service.IService; + +import java.util.List; + +/** +* @author 31586 +* @description 针对表【venue_device】的数据库操作Service +* @createDate 2025-06-29 14:38:46 +*/ +public interface DeviceService extends IService { + Device generateDeviceData(); + + List getLatestDevices(); +} diff --git a/src/main/java/com/example/venue_reservation_service/service/EmailService.java b/src/main/java/com/example/venue_reservation_service/service/EmailService.java new file mode 100644 index 0000000..c6f16bf --- /dev/null +++ b/src/main/java/com/example/venue_reservation_service/service/EmailService.java @@ -0,0 +1,37 @@ +package com.example.venue_reservation_service.service; + +import org.springframework.core.io.InputStreamSource; + +public interface EmailService { + /** + * 发送简单邮件 + * @param to 收件人 + * @param subject 主题 + * @param text 内容 + */ + void sendSimpleMessage(String to, String subject, String text); + + /** + * 发送HTML格式邮件 + * @param to 收件人 + * @param subject 主题 + * @param htmlContent HTML内容 + */ + void sendHtmlMessage(String to, String subject, String htmlContent); + + /** + * 发送带附件的邮件 + * @param to 收件人 + * @param subject 主题 + * @param text 内容 + * @param attachmentFilename 附件文件名 + * @param attachment 附件 + */ + void sendMessageWithAttachment( + String to, + String subject, + String text, + String attachmentFilename, + InputStreamSource attachment + ); +} \ No newline at end of file diff --git a/src/main/java/com/example/venue_reservation_service/service/ReservationService.java b/src/main/java/com/example/venue_reservation_service/service/ReservationService.java index a4873ba..c821fba 100644 --- a/src/main/java/com/example/venue_reservation_service/service/ReservationService.java +++ b/src/main/java/com/example/venue_reservation_service/service/ReservationService.java @@ -34,4 +34,6 @@ public interface ReservationService extends IService { Result removeSingle(Integer userId, Integer id); void exportPayments(HttpServletResponse response, String yearFilter); + + Result recommend(Integer userId); } diff --git a/src/main/java/com/example/venue_reservation_service/service/UserService.java b/src/main/java/com/example/venue_reservation_service/service/UserService.java index 8bf942a..2a213d3 100644 --- a/src/main/java/com/example/venue_reservation_service/service/UserService.java +++ b/src/main/java/com/example/venue_reservation_service/service/UserService.java @@ -40,4 +40,6 @@ public interface UserService extends IService { Result upload(Integer userId, MultipartFile file); Result getUserInfo(Integer userId); + + Result passwordReset(ResetDTO dto); } diff --git a/src/main/java/com/example/venue_reservation_service/service/impl/DeviceServiceImpl.java b/src/main/java/com/example/venue_reservation_service/service/impl/DeviceServiceImpl.java new file mode 100644 index 0000000..5a24819 --- /dev/null +++ b/src/main/java/com/example/venue_reservation_service/service/impl/DeviceServiceImpl.java @@ -0,0 +1,49 @@ +package com.example.venue_reservation_service.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.example.venue_reservation_service.domain.Device; +import com.example.venue_reservation_service.mapper.DeviceMapper; +import com.example.venue_reservation_service.service.DeviceService; +import jakarta.annotation.Resource; +import org.apache.ibatis.annotations.Mapper; +import org.springframework.stereotype.Service; + +import java.time.LocalDateTime; +import java.util.List; + +/** +* @author 31586 +* @description 针对表【venue_device】的数据库操作Service实现 +* @createDate 2025-06-29 14:38:46 +*/ +@Service +public class DeviceServiceImpl extends ServiceImpl implements DeviceService { + + @Resource + private DeviceMapper deviceMapper; + + // 模拟设备数据 + @Override + public Device generateDeviceData() { + Device device = new Device(); + device.setTimestamp(LocalDateTime.now()); + device.setTemperature(20 + Math.random() * 15); + device.setHumidity(30 + Math.random() * 50); + device.setFanStatus(device.getTemperature() > 25 ? 1 : 0); + device.setWarningStatus((device.getTemperature() > 30 || + device.getHumidity() > 70 || + device.getHumidity() < 30) ? 1 : 0); + return device; + } + + // 获取最新设备数据 + @Override + public List getLatestDevices() { + return deviceMapper.selectLatestDevices(50); + } + +} + + + + diff --git a/src/main/java/com/example/venue_reservation_service/service/impl/EmailServiceImpl.java b/src/main/java/com/example/venue_reservation_service/service/impl/EmailServiceImpl.java new file mode 100644 index 0000000..3b7f794 --- /dev/null +++ b/src/main/java/com/example/venue_reservation_service/service/impl/EmailServiceImpl.java @@ -0,0 +1,80 @@ +package com.example.venue_reservation_service.service.impl; + +import com.example.venue_reservation_service.service.EmailService; +import jakarta.mail.MessagingException; +import jakarta.mail.internet.MimeMessage; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.core.io.InputStreamSource; +import org.springframework.mail.MailException; +import org.springframework.mail.SimpleMailMessage; +import org.springframework.mail.javamail.JavaMailSender; +import org.springframework.mail.javamail.MimeMessageHelper; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class EmailServiceImpl implements EmailService { + + private final JavaMailSender mailSender; + + @Value("${spring.mail.username}") + private String from; + + @Override + public void sendSimpleMessage(String to, String subject, String text) { + try { + SimpleMailMessage message = new SimpleMailMessage(); + message.setFrom(from); + message.setTo(to); + message.setSubject(subject); + message.setText(text); + + mailSender.send(message); + } catch (MailException e) { + throw new RuntimeException("邮件发送失败", e); + } + } + + @Override + public void sendHtmlMessage(String to, String subject, String htmlContent) { + try { + MimeMessage message = mailSender.createMimeMessage(); + MimeMessageHelper helper = new MimeMessageHelper(message, true, "UTF-8"); + + helper.setFrom(from); + helper.setTo(to); + helper.setSubject(subject); + helper.setText(htmlContent, true); + + mailSender.send(message); + } catch (MessagingException e) { + throw new RuntimeException("HTML邮件发送失败", e); + } + } + + @Override + public void sendMessageWithAttachment( + String to, + String subject, + String text, + String attachmentFilename, + InputStreamSource attachment + ) { + try { + MimeMessage message = mailSender.createMimeMessage(); + MimeMessageHelper helper = new MimeMessageHelper(message, true, "UTF-8"); + + helper.setFrom(from); + helper.setTo(to); + helper.setSubject(subject); + helper.setText(text); + + helper.addAttachment(attachmentFilename, attachment); + + mailSender.send(message); + } catch (MessagingException e) { + throw new RuntimeException("带附件邮件发送失败", e); + } + } +} diff --git a/src/main/java/com/example/venue_reservation_service/service/impl/InformationServiceImpl.java b/src/main/java/com/example/venue_reservation_service/service/impl/InformationServiceImpl.java index f94e56f..8d9059e 100644 --- a/src/main/java/com/example/venue_reservation_service/service/impl/InformationServiceImpl.java +++ b/src/main/java/com/example/venue_reservation_service/service/impl/InformationServiceImpl.java @@ -18,6 +18,7 @@ import com.github.yulichang.wrapper.MPJLambdaWrapper; import jakarta.annotation.Resource; import jakarta.servlet.http.HttpServletResponse; import org.apache.commons.io.FilenameUtils; +import org.springframework.beans.factory.annotation.Value; import org.springframework.core.io.InputStreamResource; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; @@ -29,6 +30,7 @@ import org.springframework.web.multipart.MultipartFile; import java.io.InputStream; import java.time.Duration; import java.time.LocalDate; +import java.time.LocalDateTime; import java.time.LocalTime; import java.time.temporal.ChronoUnit; import java.util.*; @@ -78,6 +80,9 @@ public class InformationServiceImpl extends ServiceImpl page = new Page<>(dto.getCurrent(), dto.getSize()); @@ -106,6 +111,11 @@ public class InformationServiceImpl extends ServiceImpl informationList = list(wrapper); + informationList.forEach(item -> { + if(StringUtils.isNotBlank(item.getImgUrl())){ + item.setImgUrl(imgPrefix + item.getImgUrl()); + } + }); return Result.ok(informationList).message("场地信息获取成功"); } @@ -131,7 +141,14 @@ public class InformationServiceImpl extends ServiceImpl vo = new QueryVO(); vo.setTotal(page.getTotal()); - vo.setList(page.getRecords()); + List records = page.getRecords(); + records.forEach(item -> { + if(StringUtils.isNotBlank(item.getImgUrl())){ + item.setImgUrl(imgPrefix + item.getImgUrl()); + } + item.setQrCode(imgPrefix + item.getQrCode()); + }); + vo.setList(records); return Result.ok(vo).message("场地信息查询成功"); } @@ -144,16 +161,17 @@ public class InformationServiceImpl extends ServiceImpl { - // 处理当前预约 - dealReservation(reservation.getId()); - }; +// Runnable task = () -> { +// // 处理当前预约 +// dealReservation(reservation.getId()); +// }; // scheduleUtil.scheduleOneTimeTask(task, reservationDate, end); // // 定时任务解耦设计 @@ -563,6 +567,21 @@ public class ReservationServiceImpl extends ServiceImpllambdaQuery().eq(Reservation::getUserId, userId)); + VenueRecommender recommender = new VenueRecommender(reservationMapper.selectByUserId(count > 50 ? userId:null), userId); + RecommendVO vo = new RecommendVO(); + ReservationExcel excel = recommender.generateRecommendation(); + int hours = excel.getEndTime().getHour() - excel.getStartTime().getHour(); + vo.setExcel(excel); + vo.setInformation(informationService.getById(excel.getVenueId())); + vo.setPrice(priceService.getPrice(excel.getVenueId()) * hours); + return Result.ok(vo).message("推荐结果"); + } + } diff --git a/src/main/java/com/example/venue_reservation_service/service/impl/TypeServiceImpl.java b/src/main/java/com/example/venue_reservation_service/service/impl/TypeServiceImpl.java index 896a954..f304edb 100644 --- a/src/main/java/com/example/venue_reservation_service/service/impl/TypeServiceImpl.java +++ b/src/main/java/com/example/venue_reservation_service/service/impl/TypeServiceImpl.java @@ -9,6 +9,7 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.example.venue_reservation_service.domain.Information; import com.example.venue_reservation_service.domain.InformationTime; import com.example.venue_reservation_service.dto.PageDTO; +import com.example.venue_reservation_service.exception.MinioRemoveException; import com.example.venue_reservation_service.mapper.InformationMapper; import com.example.venue_reservation_service.mapper.TypeMapper; import com.example.venue_reservation_service.domain.Type; @@ -41,11 +42,23 @@ public class TypeServiceImpl extends ServiceImpl @Resource private InformationMapper informationMapper; + @Value("${access.url}") + private String imgPrefix; + @Override public Result queryTypes(PageDTO dto) { Page page = new Page<>(dto.getCurrent(), dto.getSize()); page = page(page, null); - return Result.ok(new QueryVO(page.getRecords(), page.getTotal())).message("场馆信息获取成功"); + List records = page.getRecords(); + records.forEach(item -> { + if(StringUtils.isNotBlank(item.getImgUrl())){ + item.setImgUrl(imgPrefix + item.getImgUrl()); + } + }); + QueryVO vo = new QueryVO<>(); + vo.setList(records); + vo.setTotal(page.getTotal()); + return Result.ok(vo).message("场馆信息获取成功"); } private boolean isSame(Type type){ @@ -103,35 +116,28 @@ public class TypeServiceImpl extends ServiceImpl if (Optional.ofNullable(type).isEmpty()) { return Result.fail().message("场馆信息不存在"); } + if(StringUtils.isNotBlank(type.getImgUrl())){ + try{ + minioUtil.removeFile(type.getImgUrl()); + }catch (Exception e){ + throw new MinioRemoveException("场馆图片异常,请稍后重试"); + } + } // 对照片重新命名 - // 获取文件后缀名 String extension = FilenameUtils.getExtension( file.getOriginalFilename()); - try { // 重新生成文件名称 String filename = UUID.randomUUID() + "-" + id + "." + extension; // 调用minio接口上传照片 minioUtil.uploadFile(file, filename, file.getContentType()); - String url = minioUtil.getPresignedObjectUrl(filename); - // 删除原来的照片 - String imgUrl = type.getImgUrl(); - if (imgUrl!=null && !"".equals(imgUrl)){ - String[] split = imgUrl.split("/"); - // 获取照片名字 - String img = split[split.length - 1]; - minioUtil.removeFile(img); - } - System.out.println(url); - type.setImgUrl(url); + type.setImgUrl(filename); updateById(type); - } catch (Exception e) { e.printStackTrace(); return Result.fail().message("图片上传失败"); } - return Result.ok().message("图片上传成功"); } diff --git a/src/main/java/com/example/venue_reservation_service/service/impl/UserServiceImpl.java b/src/main/java/com/example/venue_reservation_service/service/impl/UserServiceImpl.java index e4fece6..38c64e7 100644 --- a/src/main/java/com/example/venue_reservation_service/service/impl/UserServiceImpl.java +++ b/src/main/java/com/example/venue_reservation_service/service/impl/UserServiceImpl.java @@ -21,10 +21,14 @@ import com.example.venue_reservation_service.vo.Result; import com.github.yulichang.wrapper.MPJLambdaWrapper; import jakarta.annotation.Resource; import org.apache.commons.io.FilenameUtils; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; +import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Service; import org.springframework.web.client.RestTemplate; import org.springframework.web.multipart.MultipartFile; + +import java.time.Duration; import java.time.LocalDate; import java.time.LocalDateTime; import java.util.List; @@ -65,12 +69,21 @@ public class UserServiceImpl extends ServiceImpl @Value("${spring.application.name}") private String name; - @Value("${access.url}") - private String imgUrl; - @Resource private MinioUtil minioUtil; + @Resource + private EmailService emailService; + + @Autowired + private RedisTemplate redisTemplate; + + @Value("${access.url}") + private String imgPrefix; + + private static final String LOGIN_LOCK_PREFIX = "login_lock:"; + private static final int MAX_LOGIN_ATTEMPTS = 3; + private static final long LOCK_DURATION_MS = 5 * 60 * 1000; // 5 minutes in milliseconds @Override public Result getOpenId(String code) { Map vo = restTemplate.getForObject("https://api.weixin.qq.com/sns/jscode2session?"+ @@ -102,6 +115,7 @@ public class UserServiceImpl extends ServiceImpl user.setAccessCode(PasswordGenerator.generatePassword()); user.setRegisterTime(LocalDateTime.now()); user.setIsUpload(0); + user.setAvatar(""); save(user); // 添加新的账户余额信息 Balance balance = new Balance(0.0, user.getId()); @@ -113,7 +127,7 @@ public class UserServiceImpl extends ServiceImpl Double money = balanceService.getOne(Wrappers.lambdaQuery().eq(Balance::getUserId, user.getId())) .getBalance(); if(user.getIsUpload() == 1){ - user.setAvatar(imgUrl + user.getAvatar()); + user.setAvatar(imgPrefix + user.getAvatar()); } user.setBalance(money); loginVo.setUser(user); @@ -132,24 +146,24 @@ public class UserServiceImpl extends ServiceImpl } String password = dto.getPasswd(); - String redisKey = "login_lock:" + account; // 使用固定前缀 + String redisKey = LOGIN_LOCK_PREFIX + account; // 使用固定前缀 if (!user.getAccessCode().equals(password)) { // 处理密码错误的情况 - if (redisUtil.hasKey(redisKey)) { - String[] parts = String.valueOf(redisUtil.get(redisKey)).split("-"); + if (redisTemplate.hasKey(redisKey)) { + String[] parts = String.valueOf(redisTemplate.opsForValue().get(redisKey)).split("-"); int failCount = Integer.parseInt(parts[0]); long firstFailTime = Long.parseLong(parts[1]); // 错误次数已达上限 - if (failCount >= 3) { - long lockTime = 5 * 60 * 1000; // 5分钟毫秒数 + if (failCount >= MAX_LOGIN_ATTEMPTS) { + long lockTime = LOCK_DURATION_MS; // 5分钟毫秒数 long remainMillis = lockTime - (System.currentTimeMillis() - firstFailTime); if (remainMillis > 0) { return Result.fail().message("该账号已被锁定,请在 " + (remainMillis / 1000) + " 秒后重新登录"); } else { // 锁定已过期,重置计数器 - redisUtil.remove(redisKey); + redisTemplate.delete(redisKey); } } } @@ -157,8 +171,8 @@ public class UserServiceImpl extends ServiceImpl // 更新错误计数器(包含首次错误情况) int newCount = 1; long timestamp = System.currentTimeMillis(); - if (redisUtil.hasKey(redisKey)) { - String[] parts = String.valueOf(redisUtil.get(redisKey)).split("-"); + if (redisTemplate.hasKey(redisKey)) { + String[] parts = String.valueOf(redisTemplate.opsForValue().get(redisKey)).split("-"); newCount = Integer.parseInt(parts[0]) + 1; timestamp = Long.parseLong(parts[1]); // 保持第一次错误时间 } @@ -166,9 +180,9 @@ public class UserServiceImpl extends ServiceImpl // 更新Redis,仅首次设置过期时间 String value = newCount + "-" + timestamp; if (newCount == 1) { - redisUtil.set(redisKey, value, 5 * 60); + redisTemplate.opsForValue().set(redisKey, value, Duration.ofMinutes(5)); } else { - redisUtil.set(redisKey, value); // 更新次数但保留原TTL + redisTemplate.opsForValue().set(redisKey, value); // 更新次数但保留原TTL } return Result.fail().message("账号密码不匹配"); @@ -176,13 +190,13 @@ public class UserServiceImpl extends ServiceImpl // 密码正确,登录成功 // 清除登录错误计数 - if (redisUtil.hasKey(redisKey)) { - redisUtil.remove(redisKey); + if (redisTemplate.hasKey(redisKey)) { + redisTemplate.delete(redisKey); } user.setAccessCode(""); if (user.getIsUpload() == 1) { - user.setAvatar(imgUrl + user.getAvatar()); + user.setAvatar(imgPrefix + user.getAvatar()); } LoginVo vo = new LoginVo(); vo.setUser(user); @@ -190,6 +204,7 @@ public class UserServiceImpl extends ServiceImpl return Result.ok(vo).message("登录成功"); } + /** * 用户信息修改 * 可修改内容:用户名(username)、电话(phone)、邮箱(email) @@ -415,7 +430,7 @@ public class UserServiceImpl extends ServiceImpl user.setIsUpload(1); user.setAvatar(filename); updateById(user); - return Result.ok(imgUrl + user.getAvatar()).message("头像上传成功"); + return Result.ok(imgPrefix + user.getAvatar()).message("头像上传成功"); } catch (MinioRemoveException | ImageValidateException | MinioUploadException e) { throw e; // 抛出给全局异常处理器 @@ -440,10 +455,32 @@ public class UserServiceImpl extends ServiceImpl if (Optional.ofNullable(balance).isPresent()) { user.setBalance(balance.getBalance()); } - user.setAvatar(imgUrl + user.getAvatar()); + if(StringUtils.isNotBlank(user.getAvatar())){ + user.setAvatar(imgPrefix + user.getAvatar()); + } user.setAccessCode(""); return Result.ok(user).message("用户信息查询成功"); } + + @Override + public Result passwordReset(ResetDTO dto) { + User user = getOne(Wrappers.lambdaQuery().eq(User::getUserPhone, dto.getPhone())); + if (Optional.ofNullable(user).isEmpty()) { + return Result.fail().message("手机号未认证"); + } + if (Optional.ofNullable(user.getEmail()).isEmpty()) { + return Result.fail().message("邮箱未认证"); + } + if (!user.getEmail().equals(dto.getEmail())) { + return Result.fail().message("手机号信息与邮箱信息不匹配"); + } + try{ + emailService.sendSimpleMessage(dto.getEmail(), user.getUserPhone() + "用户密码重置", PasswordGenerator.generatePassword()); + }catch (Exception e){ + return Result.fail().message("邮件发送失败,请稍后重新尝试"); + } + return Result.ok().message("邮件发送成功"); + } } diff --git a/src/main/java/com/example/venue_reservation_service/service/impl/VenueHotServiceImpl.java b/src/main/java/com/example/venue_reservation_service/service/impl/VenueHotServiceImpl.java index 5c9715c..dff8860 100644 --- a/src/main/java/com/example/venue_reservation_service/service/impl/VenueHotServiceImpl.java +++ b/src/main/java/com/example/venue_reservation_service/service/impl/VenueHotServiceImpl.java @@ -21,6 +21,7 @@ import com.example.venue_reservation_service.utils.MinioUtil; import com.example.venue_reservation_service.vo.QueryVO; import com.example.venue_reservation_service.vo.Result; import jakarta.annotation.Resource; +import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; @@ -46,12 +47,21 @@ public class VenueHotServiceImpl extends ServiceImpl @Resource private PaymentMapper paymentMapper; + @Value("${access.url}") + private String imgPrefix; + @Override public Result getHots(PageDTO dto) { Page page = new Page<>(dto.getCurrent(), dto.getSize()); page = page(page, null); QueryVO vo = new QueryVO<>(); - vo.setList(page.getRecords()); + List records = page.getRecords(); + records.forEach(item ->{ + if(StringUtils.isNotBlank(item.getImgUrl())){ + item.setImgUrl(imgPrefix + item.getImgUrl()); + } + }); + vo.setList(records); vo.setTotal(page.getTotal()); return Result.ok(vo).message("查询成功"); } @@ -98,9 +108,8 @@ public class VenueHotServiceImpl extends ServiceImpl String filename = System.currentTimeMillis() + "-" + id + "." +split[split.length - 1] ; minioUtil.uploadFile(file, filename, file.getContentType()); - String url = minioUtil.getPresignedObjectUrl(filename); - System.out.println(); - hot.setImgUrl(url); + + hot.setImgUrl(filename); updateById(hot); }catch (Exception e){ e.printStackTrace(); diff --git a/src/main/java/com/example/venue_reservation_service/utils/RedisUtil.java b/src/main/java/com/example/venue_reservation_service/utils/RedisUtil.java index 2cf5bad..34a739a 100644 --- a/src/main/java/com/example/venue_reservation_service/utils/RedisUtil.java +++ b/src/main/java/com/example/venue_reservation_service/utils/RedisUtil.java @@ -156,36 +156,6 @@ public class RedisUtil { return redisTemplate.opsForSet().members(key); } - /** - * 随机获取变量中指定个数的元素 - * - * @param key 键 - * @param count 值 - * @return - */ - public void randomMembers(String key, long count) { - redisTemplate.opsForSet().randomMembers(key, count); - } - - /** - * 随机获取变量中的元素 - * - * @param key 键 - * @return - */ - public Object randomMember(String key) { - return redisTemplate.opsForSet().randomMember(key); - } - - /** - * 弹出变量中的元素 - * - * @param key 键 - * @return - */ - public Object pop(String key) { - return redisTemplate.opsForSet().pop("setValue"); - } /** * 获取变量中值的长度 diff --git a/src/main/java/com/example/venue_reservation_service/utils/VenueRecommender.java b/src/main/java/com/example/venue_reservation_service/utils/VenueRecommender.java new file mode 100644 index 0000000..28dd4c1 --- /dev/null +++ b/src/main/java/com/example/venue_reservation_service/utils/VenueRecommender.java @@ -0,0 +1,262 @@ +package com.example.venue_reservation_service.utils; + +import com.example.venue_reservation_service.vo.excel.ReservationExcel; + +import java.util.*; +import java.time.LocalDate; +import java.time.LocalTime; +import java.time.format.DateTimeFormatter; +import java.util.stream.Collectors; + +public class VenueRecommender { + + + + // 用户-物品评分矩阵 + private Map> userVenueScores; + // 物品-物品相似度矩阵 + private Map> venueSimilarities; + // 所有预约记录 + private List allReservations; + // 目标用户ID + private int targetUserId; + + public VenueRecommender(List reservations, int targetUserId) { + this.allReservations = reservations; + this.targetUserId = targetUserId; + this.userVenueScores = new HashMap<>(); + this.venueSimilarities = new HashMap<>(); + } + + // 构建用户-物品评分矩阵 + private void buildUserVenueMatrix() { + // 按用户分组 + Map> reservationsByUser = allReservations.stream() + .collect(Collectors.groupingBy(ReservationExcel::getUserId)); + + for (Map.Entry> entry : reservationsByUser.entrySet()) { + int userId = entry.getKey(); + List userReservations = entry.getValue(); + + // 按场地分组,计算用户对每个场地的偏好得分 + Map venueCounts = userReservations.stream() + .collect(Collectors.groupingBy(ReservationExcel::getVenueId, Collectors.counting())); + + // 找到最大计数用于归一化 + long maxCount = venueCounts.values().stream().max(Long::compare).orElse(1L); + + Map venueScores = new HashMap<>(); + for (Map.Entry venueEntry : venueCounts.entrySet()) { + // 归一化到0-1之间 + double score = (double) venueEntry.getValue() / maxCount; + venueScores.put(venueEntry.getKey(), score); + } + + userVenueScores.put(userId, venueScores); + } + } + + // 计算场地之间的余弦相似度 + private void calculateVenueSimilarities() { + // 获取所有场地ID + Set allVenues = allReservations.stream() + .map(ReservationExcel::getVenueId) + .collect(Collectors.toSet()); + + // 为每个场地构建特征向量(基于用户评分) + Map> venueUserVectors = new HashMap<>(); + + // 初始化 + for (int venueId : allVenues) { + venueUserVectors.put(venueId, new HashMap<>()); + } + + // 填充向量 + for (Map.Entry> userEntry : userVenueScores.entrySet()) { + int userId = userEntry.getKey(); + Map venueScores = userEntry.getValue(); + + for (Map.Entry venueEntry : venueScores.entrySet()) { + int venueId = venueEntry.getKey(); + double score = venueEntry.getValue(); + venueUserVectors.get(venueId).put(userId, score); + } + } + + // 计算场地之间的相似度 + for (int venue1 : allVenues) { + Map vector1 = venueUserVectors.get(venue1); + Map similarities = new HashMap<>(); + + for (int venue2 : allVenues) { + if (venue1 == venue2) { + similarities.put(venue2, 1.0); // 自相似度为1 + continue; + } + + Map vector2 = venueUserVectors.get(venue2); + + // 计算余弦相似度 + double dotProduct = 0.0; + double norm1 = 0.0; + double norm2 = 0.0; + + // 收集所有共同的用户 + Set commonUsers = new HashSet<>(vector1.keySet()); + commonUsers.retainAll(vector2.keySet()); + + // 如果没有共同用户,相似度为0 + if (commonUsers.isEmpty()) { + similarities.put(venue2, 0.0); + continue; + } + + for (int userId : commonUsers) { + double score1 = vector1.get(userId); + double score2 = vector2.get(userId); + dotProduct += score1 * score2; + norm1 += score1 * score1; + norm2 += score2 * score2; + } + + norm1 = Math.sqrt(norm1); + norm2 = Math.sqrt(norm2); + + double similarity = (norm1 * norm2 == 0) ? 0 : dotProduct / (norm1 * norm2); + similarities.put(venue2, similarity); + } + + venueSimilarities.put(venue1, similarities); + } + } + + // 为目标用户生成推荐 + public ReservationExcel generateRecommendation() { + // 获取目标用户的预约记录 + List userReservations = allReservations.stream() + .filter(r -> r.getUserId() == targetUserId) + .collect(Collectors.toList()); + + // 如果用户预约记录少于50条,使用热门推荐 + if (userReservations.size() < 50) { + return recommendPopular(); + } + + // 否则使用基于物品的协同过滤 + buildUserVenueMatrix(); + calculateVenueSimilarities(); + + // 获取用户预约过的场地 + Set userVenues = userReservations.stream() + .map(ReservationExcel::getVenueId) + .collect(Collectors.toSet()); + + // 计算用户未预约过的场地的得分 + Map venueScores = new HashMap<>(); + + for (int venueId : venueSimilarities.keySet()) { + if (userVenues.contains(venueId)) { + continue; // 跳过用户已经预约过的场地 + } + + double score = 0.0; + for (int userVenue : userVenues) { + double similarity = venueSimilarities.get(userVenue).get(venueId); + double userPreference = userVenueScores.getOrDefault(targetUserId, new HashMap<>()) + .getOrDefault(userVenue, 0.0); + score += similarity * userPreference; + } + + venueScores.put(venueId, score); + } + + // 如果没有合适的推荐,回退到热门推荐 + if (venueScores.isEmpty()) { + return recommendPopular(); + } + + // 找到得分最高的场地 + int recommendedVenueId = Collections.max(venueScores.entrySet(), Map.Entry.comparingByValue()).getKey(); + + // 为该场地推荐一个合适的时间段 + return recommendTimeSlot(recommendedVenueId, userReservations); + } + + // 热门推荐(基于所有用户的预约记录) + private ReservationExcel recommendPopular() { + // 找出最热门的场地 + Map venuePopularity = allReservations.stream() + .collect(Collectors.groupingBy(ReservationExcel::getVenueId, Collectors.counting())); + + int popularVenueId = Collections.max(venuePopularity.entrySet(), Map.Entry.comparingByValue()).getKey(); + + // 找出该场地最热门的时间段 + Map timeSlotPopularity = allReservations.stream() + .filter(r -> r.getVenueId() == popularVenueId) + .collect(Collectors.groupingBy(ReservationExcel::getTimeSlot, Collectors.counting())); + + String popularTimeSlot = Collections.max(timeSlotPopularity.entrySet(), Map.Entry.comparingByValue()).getKey(); + + // 找出该场地最热门的星期几 + Map dayPopularity = allReservations.stream() + .filter(r -> r.getVenueId() == popularVenueId) + .collect(Collectors.groupingBy(ReservationExcel::getDayOfWeek, Collectors.counting())); + + String popularDay = Collections.max(dayPopularity.entrySet(), Map.Entry.comparingByValue()).getKey(); + + // 创建推荐记录(使用下周的同一天) + LocalDate nextWeek = LocalDate.now().plusWeeks(1); + LocalDate recommendedDate = nextWeek.with(java.time.DayOfWeek.valueOf(popularDay.toUpperCase())); + + // 设置时间段 + LocalTime startTime, endTime; + if (popularTimeSlot.equals("morning")) { + startTime = LocalTime.of(9, 0); + endTime = LocalTime.of(11, 0); + } else if (popularTimeSlot.equals("afternoon")) { + startTime = LocalTime.of(14, 0); + endTime = LocalTime.of(16, 0); + } else { + startTime = LocalTime.of(19, 0); + endTime = LocalTime.of(21, 0); + } + + return new ReservationExcel(0, targetUserId, popularVenueId, startTime, endTime, recommendedDate); + } + + // 为指定场地推荐时间段(基于用户历史偏好) + private ReservationExcel recommendTimeSlot(int venueId, List userReservations) { + // 分析用户偏好的时间段 + Map userTimeSlotPref = userReservations.stream() + .collect(Collectors.groupingBy(ReservationExcel::getTimeSlot, Collectors.counting())); + + String preferredTimeSlot = Collections.max(userTimeSlotPref.entrySet(), Map.Entry.comparingByValue()).getKey(); + + // 分析用户偏好的星期几 + Map userDayPref = userReservations.stream() + .collect(Collectors.groupingBy(ReservationExcel::getDayOfWeek, Collectors.counting())); + + String preferredDay = Collections.max(userDayPref.entrySet(), Map.Entry.comparingByValue()).getKey(); + + // 创建推荐记录(使用下周的同一天) + LocalDate nextWeek = LocalDate.now().plusWeeks(1); + LocalDate recommendedDate = nextWeek.with(java.time.DayOfWeek.valueOf(preferredDay.toUpperCase())); + + // 设置时间段 + LocalTime startTime, endTime; + if (preferredTimeSlot.equals("morning")) { + startTime = LocalTime.of(9, 0); + endTime = LocalTime.of(11, 0); + } else if (preferredTimeSlot.equals("afternoon")) { + startTime = LocalTime.of(14, 0); + endTime = LocalTime.of(16, 0); + } else { + startTime = LocalTime.of(19, 0); + endTime = LocalTime.of(21, 0); + } + + return new ReservationExcel(0, targetUserId, venueId, startTime, endTime, recommendedDate); + } + + +} \ No newline at end of file diff --git a/src/main/java/com/example/venue_reservation_service/vo/excel/ReservationExcel.java b/src/main/java/com/example/venue_reservation_service/vo/excel/ReservationExcel.java index e4e89e7..babbf1f 100644 --- a/src/main/java/com/example/venue_reservation_service/vo/excel/ReservationExcel.java +++ b/src/main/java/com/example/venue_reservation_service/vo/excel/ReservationExcel.java @@ -11,6 +11,7 @@ import java.time.LocalTime; import com.example.venue_reservation_service.converter.LocalDateStringConverter; import com.example.venue_reservation_service.converter.LocalTimeStringConverter; import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import org.springframework.format.annotation.DateTimeFormat; @@ -24,6 +25,7 @@ import org.springframework.format.annotation.DateTimeFormat; @HeadFontStyle(fontName = "宋体", fontHeightInPoints = 16) // 内容字体设置成16, 字体默认宋体 @ContentFontStyle(fontName = "宋体", fontHeightInPoints = 16) +@AllArgsConstructor public class ReservationExcel implements Serializable { @ExcelProperty("预约记录编号") @@ -46,4 +48,19 @@ public class ReservationExcel implements Serializable { @ExcelProperty(value = "预约日期", converter = LocalDateStringConverter.class) private LocalDate reservationDate; + // 获取时间段标识(上午、下午、晚上) + public String getTimeSlot() { + if (startTime.isBefore(LocalTime.of(12, 0))) { + return "morning"; + } else if (startTime.isBefore(LocalTime.of(17, 0))) { + return "afternoon"; + } else { + return "evening"; + } + } + + // 获取星期几 + public String getDayOfWeek() { + return reservationDate.getDayOfWeek().toString().toLowerCase(); + } } diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 72ab5b6..072baa4 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -1,7 +1,7 @@ server: port: 9020 -# servlet: -# context-path: / + servlet: + context-path: /api netty: port: 9030 @@ -65,10 +65,25 @@ spring: boot: admin: client: - url: http://119.29.191.232:10020 # 服务端地址 + url: http://119.29.191.232:10020/monitor # 服务端地址 username: admin # 服务端用户名 password: admin123! # 服务端密码 - + mail: + host: smtp.qq.com + port: 587 + username: 3158614516@qq.com # 你的QQ邮箱地址 + password: zjhjoakssikudejc # 不是QQ密码,是SMTP授权码 + protocol: smtp + properties: + mail: + smtp: + auth: true + starttls: + enable: true + required: true + connectiontimeout: 5000 + timeout: 5000 + writetimeout: 5000 # 暴露完整监控端点 management: endpoints: @@ -116,7 +131,7 @@ minio: secret-key: minioadmin bucket: venue-sport access: - url: http://${localhosturl}:9000/${minio.bucket}/ + url: https://ruanjiansc.cn/${minio.bucket}/ logging: level: diff --git a/src/main/resources/mapper/DeviceMapper.xml b/src/main/resources/mapper/DeviceMapper.xml new file mode 100644 index 0000000..5e786ef --- /dev/null +++ b/src/main/resources/mapper/DeviceMapper.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + id,timestamp,temperature, + humidity,fan_status,warning_status + + diff --git a/src/test/java/com/example/venue_reservation_service/VenueReservationServiceApplicationTests.java b/src/test/java/com/example/venue_reservation_service/VenueReservationServiceApplicationTests.java index 1d68150..54074af 100644 --- a/src/test/java/com/example/venue_reservation_service/VenueReservationServiceApplicationTests.java +++ b/src/test/java/com/example/venue_reservation_service/VenueReservationServiceApplicationTests.java @@ -1,8 +1,15 @@ package com.example.venue_reservation_service; import cn.hutool.json.JSONUtil; +import com.baomidou.mybatisplus.core.toolkit.StringUtils; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.example.venue_reservation_service.domain.Information; +import com.example.venue_reservation_service.domain.Reservation; import com.example.venue_reservation_service.entity.PersonInfo; import com.example.venue_reservation_service.entity.ResponseData; +import com.example.venue_reservation_service.service.InformationService; import com.example.venue_reservation_service.service.ReservationService; +import com.example.venue_reservation_service.service.impl.InformationServiceImpl; +import com.example.venue_reservation_service.service.impl.ReservationServiceImpl; import com.example.venue_reservation_service.utils.IdentityUtil; import com.example.venue_reservation_service.utils.MD5Util; import com.fasterxml.jackson.core.JsonProcessingException; @@ -13,26 +20,54 @@ import org.springframework.boot.test.context.SpringBootTest; import org.springframework.web.client.RestTemplate; import reactor.core.publisher.Flux; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + @SpringBootTest class VenueReservationServiceApplicationTests { @Resource - private ReservationService reservationService; + private InformationService informationService; + @Test void contextLoads() throws Exception { + Map tys = new HashMap<>(); + tys.put("南区风雨球场", "篮球"); + tys.put("北区羽毛球场", "羽毛球"); + tys.put("北区网球场", "北区网球"); - } + List names = new ArrayList<>(); + names.add("1号场"); + names.add("2号场"); + names.add("3号场"); + names.add("4号场"); + names.add("5号场"); + names.add("6号场"); + names.add("7号场"); + names.add("8号场"); + names.add("9号场"); + names.add("10号场"); + names.add("11号场"); + names.add("12号场"); + for (String name : names) { + Information information = new Information(); + information.setLocation("北区网球场"); + information.setTypeId(1); + information.setType("网球"); + information.setVenueName(name); + information.setLocation("北区网球场"); + informationService.addInformation(information); + } + } - private static final ObjectMapper objectMapper = new ObjectMapper(); public static void main(String[] args) throws Exception { - String result = IdentityUtil.getGzzxList("13767489908"); - ResponseData data = objectMapper.readValue(result, ResponseData.class); - System.out.println(data.getMessage().get(0)); } // public static void main(String[] args) {