添加后端代码、数据库文档和FRP配置
This commit is contained in:
@@ -0,0 +1,17 @@
|
||||
package com.gpf.pethospital;
|
||||
|
||||
import org.mybatis.spring.annotation.MapperScan;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
/**
|
||||
* 爱维宠物医院管理平台主应用
|
||||
*/
|
||||
@SpringBootApplication
|
||||
@MapperScan("com.gpf.pethospital.mapper")
|
||||
public class PetHospitalApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(PetHospitalApplication.class, args);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package com.gpf.pethospital.common;
|
||||
|
||||
public class ApiResponse<T> {
|
||||
private final int code;
|
||||
private final String message;
|
||||
private final T data;
|
||||
|
||||
private ApiResponse(int code, String message, T data) {
|
||||
this.code = code;
|
||||
this.message = message;
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public static <T> ApiResponse<T> success(T data) {
|
||||
return new ApiResponse<>(0, "ok", data);
|
||||
}
|
||||
|
||||
public static <T> ApiResponse<T> success(String message, T data) {
|
||||
return new ApiResponse<>(0, message, data);
|
||||
}
|
||||
|
||||
public static <T> ApiResponse<T> error(int code, String message) {
|
||||
return new ApiResponse<>(code, message, null);
|
||||
}
|
||||
|
||||
public int getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public T getData() {
|
||||
return data;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package com.gpf.pethospital.config;
|
||||
|
||||
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
|
||||
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
|
||||
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
|
||||
import org.apache.ibatis.reflection.MetaObject;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Configuration
|
||||
public class MybatisPlusConfig {
|
||||
@Bean
|
||||
public MybatisPlusInterceptor mybatisPlusInterceptor() {
|
||||
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
|
||||
interceptor.addInnerInterceptor(new PaginationInnerInterceptor());
|
||||
return interceptor;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public MetaObjectHandler metaObjectHandler() {
|
||||
return new MetaObjectHandler() {
|
||||
@Override
|
||||
public void insertFill(MetaObject metaObject) {
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
strictInsertFill(metaObject, "createTime", LocalDateTime.class, now);
|
||||
strictInsertFill(metaObject, "updateTime", LocalDateTime.class, now);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateFill(MetaObject metaObject) {
|
||||
strictUpdateFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now());
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package com.gpf.pethospital.config;
|
||||
|
||||
import com.gpf.pethospital.security.JwtAuthenticationFilter;
|
||||
import com.gpf.pethospital.util.JwtUtil;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.http.SessionCreationPolicy;
|
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.security.web.SecurityFilterChain;
|
||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
||||
|
||||
@Configuration
|
||||
@EnableMethodSecurity
|
||||
public class SecurityConfig {
|
||||
@Value("${jwt.secret}")
|
||||
private String jwtSecret;
|
||||
|
||||
@Value("${jwt.expiration}")
|
||||
private long jwtExpiration;
|
||||
|
||||
@Bean
|
||||
public JwtUtil jwtUtil() {
|
||||
return new JwtUtil(jwtSecret, jwtExpiration);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public PasswordEncoder passwordEncoder() {
|
||||
return new BCryptPasswordEncoder();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public SecurityFilterChain filterChain(HttpSecurity http, JwtUtil jwtUtil) throws Exception {
|
||||
http
|
||||
.csrf(csrf -> csrf.disable())
|
||||
.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
|
||||
.authorizeHttpRequests(auth -> auth
|
||||
.requestMatchers(new AntPathRequestMatcher("/auth/**")).permitAll()
|
||||
.requestMatchers(new AntPathRequestMatcher("/public/**")).permitAll()
|
||||
.anyRequest().authenticated()
|
||||
)
|
||||
.addFilterBefore(new JwtAuthenticationFilter(jwtUtil), UsernamePasswordAuthenticationFilter.class);
|
||||
return http.build();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.gpf.pethospital.config;
|
||||
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.servlet.config.annotation.CorsRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
|
||||
@Configuration
|
||||
public class WebConfig implements WebMvcConfigurer {
|
||||
@Override
|
||||
public void addCorsMappings(CorsRegistry registry) {
|
||||
registry.addMapping("/**")
|
||||
.allowedOrigins("*")
|
||||
.allowedMethods("GET", "POST", "PUT", "DELETE", "PATCH")
|
||||
.allowedHeaders("*")
|
||||
.maxAge(3600);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
package com.gpf.pethospital.controller;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.gpf.pethospital.common.ApiResponse;
|
||||
import com.gpf.pethospital.entity.Appointment;
|
||||
import com.gpf.pethospital.security.AuthUser;
|
||||
import com.gpf.pethospital.service.AppointmentService;
|
||||
import com.gpf.pethospital.util.SecurityUtils;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/appointments")
|
||||
public class AppointmentController {
|
||||
private final AppointmentService appointmentService;
|
||||
|
||||
public AppointmentController(AppointmentService appointmentService) {
|
||||
this.appointmentService = appointmentService;
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
public ApiResponse<?> create(@RequestBody Appointment appointment) {
|
||||
AuthUser user = SecurityUtils.currentUser();
|
||||
if (user != null && "CUSTOMER".equals(user.getRole())) {
|
||||
appointment.setCustomerId(user.getId());
|
||||
}
|
||||
if (appointment.getStatus() == null) {
|
||||
appointment.setStatus("PENDING");
|
||||
}
|
||||
appointmentService.save(appointment);
|
||||
return ApiResponse.success("created", null);
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
public ApiResponse<?> list(@RequestParam(defaultValue = "1") long page,
|
||||
@RequestParam(defaultValue = "10") long size) {
|
||||
AuthUser user = SecurityUtils.currentUser();
|
||||
LambdaQueryWrapper<Appointment> wrapper = new LambdaQueryWrapper<>();
|
||||
if (user != null && "CUSTOMER".equals(user.getRole())) {
|
||||
wrapper.eq(Appointment::getCustomerId, user.getId());
|
||||
}
|
||||
return ApiResponse.success(appointmentService.page(new Page<>(page, size), wrapper));
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAnyRole('ADMIN','DOCTOR')")
|
||||
@GetMapping("/admin")
|
||||
public ApiResponse<?> adminList(@RequestParam(defaultValue = "1") long page,
|
||||
@RequestParam(defaultValue = "10") long size,
|
||||
@RequestParam(required = false) String status) {
|
||||
LambdaQueryWrapper<Appointment> wrapper = new LambdaQueryWrapper<>();
|
||||
if (status != null && !status.isBlank()) {
|
||||
wrapper.eq(Appointment::getStatus, status);
|
||||
}
|
||||
return ApiResponse.success(appointmentService.page(new Page<>(page, size), wrapper));
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAnyRole('ADMIN','DOCTOR')")
|
||||
@PutMapping("/{id}/status")
|
||||
public ApiResponse<?> updateStatus(@PathVariable Long id, @RequestParam String status) {
|
||||
Appointment update = new Appointment();
|
||||
update.setId(id);
|
||||
update.setStatus(status);
|
||||
if ("CANCELLED".equals(status)) {
|
||||
update.setCancelTime(LocalDateTime.now());
|
||||
}
|
||||
appointmentService.updateById(update);
|
||||
return ApiResponse.success("updated", null);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
package com.gpf.pethospital.controller;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.gpf.pethospital.common.ApiResponse;
|
||||
import com.gpf.pethospital.dto.LoginRequest;
|
||||
import com.gpf.pethospital.dto.RegisterRequest;
|
||||
import com.gpf.pethospital.entity.User;
|
||||
import com.gpf.pethospital.service.UserService;
|
||||
import com.gpf.pethospital.util.JwtUtil;
|
||||
import jakarta.validation.Valid;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/auth")
|
||||
public class AuthController {
|
||||
private final UserService userService;
|
||||
private final PasswordEncoder passwordEncoder;
|
||||
private final JwtUtil jwtUtil;
|
||||
|
||||
public AuthController(UserService userService, PasswordEncoder passwordEncoder, JwtUtil jwtUtil) {
|
||||
this.userService = userService;
|
||||
this.passwordEncoder = passwordEncoder;
|
||||
this.jwtUtil = jwtUtil;
|
||||
}
|
||||
|
||||
@PostMapping("/register")
|
||||
public ApiResponse<?> register(@Valid @RequestBody RegisterRequest request) {
|
||||
if ((request.getPhone() == null || request.getPhone().isBlank())
|
||||
&& (request.getEmail() == null || request.getEmail().isBlank())) {
|
||||
return ApiResponse.error(400, "phone or email is required");
|
||||
}
|
||||
LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(User::getUsername, request.getUsername())
|
||||
.or()
|
||||
.eq(request.getPhone() != null && !request.getPhone().isBlank(), User::getPhone, request.getPhone())
|
||||
.or()
|
||||
.eq(request.getEmail() != null && !request.getEmail().isBlank(), User::getEmail, request.getEmail());
|
||||
if (userService.count(wrapper) > 0) {
|
||||
return ApiResponse.error(409, "user already exists");
|
||||
}
|
||||
User user = new User();
|
||||
user.setUsername(request.getUsername());
|
||||
user.setPhone(request.getPhone());
|
||||
user.setEmail(request.getEmail());
|
||||
user.setPassword(passwordEncoder.encode(request.getPassword()));
|
||||
user.setRole("CUSTOMER");
|
||||
user.setStatus(1);
|
||||
userService.save(user);
|
||||
return ApiResponse.success("registered", null);
|
||||
}
|
||||
|
||||
@PostMapping("/login")
|
||||
public ApiResponse<?> login(@Valid @RequestBody LoginRequest request) {
|
||||
LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(User::getUsername, request.getAccount())
|
||||
.or()
|
||||
.eq(User::getPhone, request.getAccount())
|
||||
.or()
|
||||
.eq(User::getEmail, request.getAccount());
|
||||
User user = userService.getOne(wrapper);
|
||||
if (user == null || user.getStatus() != null && user.getStatus() == 0) {
|
||||
return ApiResponse.error(401, "invalid account or disabled");
|
||||
}
|
||||
if (!passwordEncoder.matches(request.getPassword(), user.getPassword())) {
|
||||
return ApiResponse.error(401, "invalid account or password");
|
||||
}
|
||||
String token = jwtUtil.generateToken(user.getId(), user.getRole(), user.getUsername());
|
||||
Map<String, Object> data = new HashMap<>();
|
||||
data.put("token", token);
|
||||
data.put("role", user.getRole());
|
||||
data.put("userId", user.getId());
|
||||
data.put("username", user.getUsername());
|
||||
return ApiResponse.success(data);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package com.gpf.pethospital.controller;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.gpf.pethospital.common.ApiResponse;
|
||||
import com.gpf.pethospital.entity.Drug;
|
||||
import com.gpf.pethospital.service.DrugService;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/drugs")
|
||||
public class DrugController {
|
||||
private final DrugService drugService;
|
||||
|
||||
public DrugController(DrugService drugService) {
|
||||
this.drugService = drugService;
|
||||
}
|
||||
|
||||
@PreAuthorize("hasRole('ADMIN')")
|
||||
@GetMapping
|
||||
public ApiResponse<?> list(@RequestParam(defaultValue = "1") long page,
|
||||
@RequestParam(defaultValue = "10") long size,
|
||||
@RequestParam(required = false) String keyword) {
|
||||
LambdaQueryWrapper<Drug> wrapper = new LambdaQueryWrapper<>();
|
||||
if (keyword != null && !keyword.isBlank()) {
|
||||
wrapper.like(Drug::getName, keyword)
|
||||
.or()
|
||||
.like(Drug::getSpecification, keyword);
|
||||
}
|
||||
return ApiResponse.success(drugService.page(new Page<>(page, size), wrapper));
|
||||
}
|
||||
|
||||
@PreAuthorize("hasRole('ADMIN')")
|
||||
@PostMapping
|
||||
public ApiResponse<?> create(@RequestBody Drug drug) {
|
||||
if (drug.getStatus() == null) {
|
||||
drug.setStatus(1);
|
||||
}
|
||||
drugService.save(drug);
|
||||
return ApiResponse.success("created", null);
|
||||
}
|
||||
|
||||
@PreAuthorize("hasRole('ADMIN')")
|
||||
@PutMapping("/{id}")
|
||||
public ApiResponse<?> update(@PathVariable Long id, @RequestBody Drug drug) {
|
||||
drug.setId(id);
|
||||
drugService.updateById(drug);
|
||||
return ApiResponse.success("updated", null);
|
||||
}
|
||||
|
||||
@PreAuthorize("hasRole('ADMIN')")
|
||||
@DeleteMapping("/{id}")
|
||||
public ApiResponse<?> delete(@PathVariable Long id) {
|
||||
drugService.removeById(id);
|
||||
return ApiResponse.success("deleted", null);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package com.gpf.pethospital.controller;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.gpf.pethospital.common.ApiResponse;
|
||||
import com.gpf.pethospital.entity.MedicalRecord;
|
||||
import com.gpf.pethospital.service.MedicalRecordService;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/medical-records")
|
||||
public class MedicalRecordController {
|
||||
private final MedicalRecordService medicalRecordService;
|
||||
|
||||
public MedicalRecordController(MedicalRecordService medicalRecordService) {
|
||||
this.medicalRecordService = medicalRecordService;
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAnyRole('ADMIN','DOCTOR')")
|
||||
@PostMapping
|
||||
public ApiResponse<?> create(@RequestBody MedicalRecord record) {
|
||||
if (record.getStatus() == null) {
|
||||
record.setStatus("DRAFT");
|
||||
}
|
||||
medicalRecordService.save(record);
|
||||
return ApiResponse.success("created", null);
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
public ApiResponse<?> list(@RequestParam Long visitId) {
|
||||
LambdaQueryWrapper<MedicalRecord> wrapper = new LambdaQueryWrapper<MedicalRecord>()
|
||||
.eq(MedicalRecord::getVisitId, visitId);
|
||||
return ApiResponse.success(medicalRecordService.list(wrapper));
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAnyRole('ADMIN','DOCTOR')")
|
||||
@PutMapping("/{id}")
|
||||
public ApiResponse<?> update(@PathVariable Long id, @RequestBody MedicalRecord record) {
|
||||
record.setId(id);
|
||||
medicalRecordService.updateById(record);
|
||||
return ApiResponse.success("updated", null);
|
||||
}
|
||||
|
||||
@PreAuthorize("hasRole('ADMIN')")
|
||||
@DeleteMapping("/{id}")
|
||||
public ApiResponse<?> delete(@PathVariable Long id) {
|
||||
medicalRecordService.removeById(id);
|
||||
return ApiResponse.success("deleted", null);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
package com.gpf.pethospital.controller;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.gpf.pethospital.common.ApiResponse;
|
||||
import com.gpf.pethospital.dto.ReplyRequest;
|
||||
import com.gpf.pethospital.entity.Message;
|
||||
import com.gpf.pethospital.security.AuthUser;
|
||||
import com.gpf.pethospital.service.MessageService;
|
||||
import com.gpf.pethospital.util.SecurityUtils;
|
||||
import jakarta.validation.Valid;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/messages")
|
||||
public class MessageController {
|
||||
private final MessageService messageService;
|
||||
|
||||
public MessageController(MessageService messageService) {
|
||||
this.messageService = messageService;
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
public ApiResponse<?> create(@RequestBody Message message) {
|
||||
AuthUser user = SecurityUtils.currentUser();
|
||||
if (user != null) {
|
||||
message.setUserId(user.getId());
|
||||
message.setUserName(user.getUsername());
|
||||
}
|
||||
message.setStatus("PENDING");
|
||||
messageService.save(message);
|
||||
return ApiResponse.success("created", null);
|
||||
}
|
||||
|
||||
@PreAuthorize("hasRole('ADMIN')")
|
||||
@GetMapping("/admin")
|
||||
public ApiResponse<?> list(@RequestParam(defaultValue = "1") long page,
|
||||
@RequestParam(defaultValue = "10") long size,
|
||||
@RequestParam(required = false) String status) {
|
||||
LambdaQueryWrapper<Message> wrapper = new LambdaQueryWrapper<>();
|
||||
if (status != null && !status.isBlank()) {
|
||||
wrapper.eq(Message::getStatus, status);
|
||||
}
|
||||
return ApiResponse.success(messageService.page(new Page<>(page, size), wrapper));
|
||||
}
|
||||
|
||||
@PreAuthorize("hasRole('ADMIN')")
|
||||
@PutMapping("/admin/{id}/reply")
|
||||
public ApiResponse<?> reply(@PathVariable Long id, @Valid @RequestBody ReplyRequest request) {
|
||||
AuthUser user = SecurityUtils.currentUser();
|
||||
Message update = new Message();
|
||||
update.setId(id);
|
||||
update.setReply(request.getReply());
|
||||
update.setStatus("PROCESSED");
|
||||
update.setReplyTime(LocalDateTime.now());
|
||||
if (user != null) {
|
||||
update.setReplyUserId(user.getId());
|
||||
}
|
||||
messageService.updateById(update);
|
||||
return ApiResponse.success("updated", null);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package com.gpf.pethospital.controller;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.gpf.pethospital.common.ApiResponse;
|
||||
import com.gpf.pethospital.entity.Notice;
|
||||
import com.gpf.pethospital.service.NoticeService;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
@RestController
|
||||
@RequestMapping
|
||||
public class NoticeController {
|
||||
private final NoticeService noticeService;
|
||||
|
||||
public NoticeController(NoticeService noticeService) {
|
||||
this.noticeService = noticeService;
|
||||
}
|
||||
|
||||
@GetMapping("/public/notices")
|
||||
public ApiResponse<?> publicList(@RequestParam(defaultValue = "1") long page,
|
||||
@RequestParam(defaultValue = "10") long size) {
|
||||
LambdaQueryWrapper<Notice> wrapper = new LambdaQueryWrapper<Notice>()
|
||||
.eq(Notice::getStatus, 1)
|
||||
.orderByDesc(Notice::getIsTop)
|
||||
.orderByDesc(Notice::getCreateTime);
|
||||
return ApiResponse.success(noticeService.page(new Page<>(page, size), wrapper));
|
||||
}
|
||||
|
||||
@GetMapping("/public/notices/{id}")
|
||||
public ApiResponse<?> publicDetail(@PathVariable Long id) {
|
||||
return ApiResponse.success(noticeService.getById(id));
|
||||
}
|
||||
|
||||
@PreAuthorize("hasRole('ADMIN')")
|
||||
@GetMapping("/notices")
|
||||
public ApiResponse<?> list(@RequestParam(defaultValue = "1") long page,
|
||||
@RequestParam(defaultValue = "10") long size) {
|
||||
return ApiResponse.success(noticeService.page(new Page<>(page, size)));
|
||||
}
|
||||
|
||||
@PreAuthorize("hasRole('ADMIN')")
|
||||
@PostMapping("/notices")
|
||||
public ApiResponse<?> create(@RequestBody Notice notice) {
|
||||
if (notice.getStatus() == null) {
|
||||
notice.setStatus(1);
|
||||
}
|
||||
noticeService.save(notice);
|
||||
return ApiResponse.success("created", null);
|
||||
}
|
||||
|
||||
@PreAuthorize("hasRole('ADMIN')")
|
||||
@PutMapping("/notices/{id}")
|
||||
public ApiResponse<?> update(@PathVariable Long id, @RequestBody Notice notice) {
|
||||
notice.setId(id);
|
||||
noticeService.updateById(notice);
|
||||
return ApiResponse.success("updated", null);
|
||||
}
|
||||
|
||||
@PreAuthorize("hasRole('ADMIN')")
|
||||
@DeleteMapping("/notices/{id}")
|
||||
public ApiResponse<?> delete(@PathVariable Long id) {
|
||||
noticeService.removeById(id);
|
||||
return ApiResponse.success("deleted", null);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package com.gpf.pethospital.controller;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.gpf.pethospital.common.ApiResponse;
|
||||
import com.gpf.pethospital.entity.Order;
|
||||
import com.gpf.pethospital.security.AuthUser;
|
||||
import com.gpf.pethospital.service.OrderService;
|
||||
import com.gpf.pethospital.util.SecurityUtils;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/orders")
|
||||
public class OrderController {
|
||||
private final OrderService orderService;
|
||||
|
||||
public OrderController(OrderService orderService) {
|
||||
this.orderService = orderService;
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
public ApiResponse<?> create(@RequestBody Order order) {
|
||||
AuthUser user = SecurityUtils.currentUser();
|
||||
if (user != null && "CUSTOMER".equals(user.getRole())) {
|
||||
order.setCustomerId(user.getId());
|
||||
}
|
||||
if (order.getStatus() == null) {
|
||||
order.setStatus("UNPAID");
|
||||
}
|
||||
orderService.save(order);
|
||||
return ApiResponse.success("created", null);
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
public ApiResponse<?> list(@RequestParam(defaultValue = "1") long page,
|
||||
@RequestParam(defaultValue = "10") long size) {
|
||||
AuthUser user = SecurityUtils.currentUser();
|
||||
LambdaQueryWrapper<Order> wrapper = new LambdaQueryWrapper<>();
|
||||
if (user != null && "CUSTOMER".equals(user.getRole())) {
|
||||
wrapper.eq(Order::getCustomerId, user.getId());
|
||||
}
|
||||
return ApiResponse.success(orderService.page(new Page<>(page, size), wrapper));
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAnyRole('ADMIN','DOCTOR')")
|
||||
@PutMapping("/{id}")
|
||||
public ApiResponse<?> update(@PathVariable Long id, @RequestBody Order order) {
|
||||
order.setId(id);
|
||||
orderService.updateById(order);
|
||||
return ApiResponse.success("updated", null);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
package com.gpf.pethospital.controller;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.gpf.pethospital.common.ApiResponse;
|
||||
import com.gpf.pethospital.entity.Pet;
|
||||
import com.gpf.pethospital.security.AuthUser;
|
||||
import com.gpf.pethospital.service.PetService;
|
||||
import com.gpf.pethospital.util.SecurityUtils;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/pets")
|
||||
public class PetController {
|
||||
private final PetService petService;
|
||||
|
||||
public PetController(PetService petService) {
|
||||
this.petService = petService;
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
public ApiResponse<?> list(@RequestParam(defaultValue = "1") long page,
|
||||
@RequestParam(defaultValue = "10") long size,
|
||||
@RequestParam(required = false) Long ownerId) {
|
||||
AuthUser user = SecurityUtils.currentUser();
|
||||
LambdaQueryWrapper<Pet> wrapper = new LambdaQueryWrapper<>();
|
||||
if (user != null && "CUSTOMER".equals(user.getRole())) {
|
||||
wrapper.eq(Pet::getOwnerId, user.getId());
|
||||
} else if (ownerId != null) {
|
||||
wrapper.eq(Pet::getOwnerId, ownerId);
|
||||
}
|
||||
return ApiResponse.success(petService.page(new Page<>(page, size), wrapper));
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
public ApiResponse<?> create(@RequestBody Pet pet) {
|
||||
AuthUser user = SecurityUtils.currentUser();
|
||||
if (user != null && "CUSTOMER".equals(user.getRole())) {
|
||||
pet.setOwnerId(user.getId());
|
||||
}
|
||||
petService.save(pet);
|
||||
return ApiResponse.success("created", null);
|
||||
}
|
||||
|
||||
@PutMapping("/{id}")
|
||||
public ApiResponse<?> update(@PathVariable Long id, @RequestBody Pet pet) {
|
||||
AuthUser user = SecurityUtils.currentUser();
|
||||
if (user != null && "CUSTOMER".equals(user.getRole())) {
|
||||
Pet existing = petService.getById(id);
|
||||
if (existing == null || !existing.getOwnerId().equals(user.getId())) {
|
||||
return ApiResponse.error(403, "forbidden");
|
||||
}
|
||||
}
|
||||
pet.setId(id);
|
||||
petService.updateById(pet);
|
||||
return ApiResponse.success("updated", null);
|
||||
}
|
||||
|
||||
@DeleteMapping("/{id}")
|
||||
public ApiResponse<?> delete(@PathVariable Long id) {
|
||||
AuthUser user = SecurityUtils.currentUser();
|
||||
if (user != null && "CUSTOMER".equals(user.getRole())) {
|
||||
Pet existing = petService.getById(id);
|
||||
if (existing == null || !existing.getOwnerId().equals(user.getId())) {
|
||||
return ApiResponse.error(403, "forbidden");
|
||||
}
|
||||
}
|
||||
petService.removeById(id);
|
||||
return ApiResponse.success("deleted", null);
|
||||
}
|
||||
|
||||
@PreAuthorize("hasRole('ADMIN')")
|
||||
@GetMapping("/admin/all")
|
||||
public ApiResponse<?> adminList(@RequestParam(defaultValue = "1") long page,
|
||||
@RequestParam(defaultValue = "10") long size) {
|
||||
return ApiResponse.success(petService.page(new Page<>(page, size)));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package com.gpf.pethospital.controller;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.gpf.pethospital.common.ApiResponse;
|
||||
import com.gpf.pethospital.entity.Prescription;
|
||||
import com.gpf.pethospital.security.AuthUser;
|
||||
import com.gpf.pethospital.service.PrescriptionService;
|
||||
import com.gpf.pethospital.util.SecurityUtils;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/prescriptions")
|
||||
public class PrescriptionController {
|
||||
private final PrescriptionService prescriptionService;
|
||||
|
||||
public PrescriptionController(PrescriptionService prescriptionService) {
|
||||
this.prescriptionService = prescriptionService;
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAnyRole('ADMIN','DOCTOR')")
|
||||
@PostMapping
|
||||
public ApiResponse<?> create(@RequestBody Prescription prescription) {
|
||||
if (prescription.getStatus() == null) {
|
||||
prescription.setStatus("DRAFT");
|
||||
}
|
||||
prescriptionService.save(prescription);
|
||||
return ApiResponse.success("created", null);
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
public ApiResponse<?> list(@RequestParam(defaultValue = "1") long page,
|
||||
@RequestParam(defaultValue = "10") long size,
|
||||
@RequestParam(required = false) Long visitId) {
|
||||
AuthUser user = SecurityUtils.currentUser();
|
||||
LambdaQueryWrapper<Prescription> wrapper = new LambdaQueryWrapper<>();
|
||||
if (visitId != null) {
|
||||
wrapper.eq(Prescription::getVisitId, visitId);
|
||||
}
|
||||
if (user != null && "DOCTOR".equals(user.getRole())) {
|
||||
wrapper.eq(Prescription::getDoctorId, user.getId());
|
||||
}
|
||||
return ApiResponse.success(prescriptionService.page(new Page<>(page, size), wrapper));
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAnyRole('ADMIN','DOCTOR')")
|
||||
@PutMapping("/{id}")
|
||||
public ApiResponse<?> update(@PathVariable Long id, @RequestBody Prescription prescription) {
|
||||
prescription.setId(id);
|
||||
prescriptionService.updateById(prescription);
|
||||
return ApiResponse.success("updated", null);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package com.gpf.pethospital.controller;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.gpf.pethospital.common.ApiResponse;
|
||||
import com.gpf.pethospital.entity.PrescriptionItem;
|
||||
import com.gpf.pethospital.service.PrescriptionItemService;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/prescription-items")
|
||||
public class PrescriptionItemController {
|
||||
private final PrescriptionItemService prescriptionItemService;
|
||||
|
||||
public PrescriptionItemController(PrescriptionItemService prescriptionItemService) {
|
||||
this.prescriptionItemService = prescriptionItemService;
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
public ApiResponse<?> list(@RequestParam Long prescriptionId) {
|
||||
LambdaQueryWrapper<PrescriptionItem> wrapper = new LambdaQueryWrapper<PrescriptionItem>()
|
||||
.eq(PrescriptionItem::getPrescriptionId, prescriptionId);
|
||||
return ApiResponse.success(prescriptionItemService.list(wrapper));
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAnyRole('ADMIN','DOCTOR')")
|
||||
@PostMapping
|
||||
public ApiResponse<?> create(@RequestBody PrescriptionItem item) {
|
||||
prescriptionItemService.save(item);
|
||||
return ApiResponse.success("created", null);
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAnyRole('ADMIN','DOCTOR')")
|
||||
@PutMapping("/{id}")
|
||||
public ApiResponse<?> update(@PathVariable Long id, @RequestBody PrescriptionItem item) {
|
||||
item.setId(id);
|
||||
prescriptionItemService.updateById(item);
|
||||
return ApiResponse.success("updated", null);
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAnyRole('ADMIN','DOCTOR')")
|
||||
@DeleteMapping("/{id}")
|
||||
public ApiResponse<?> delete(@PathVariable Long id) {
|
||||
prescriptionItemService.removeById(id);
|
||||
return ApiResponse.success("deleted", null);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package com.gpf.pethospital.controller;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.gpf.pethospital.common.ApiResponse;
|
||||
import com.gpf.pethospital.entity.Report;
|
||||
import com.gpf.pethospital.security.AuthUser;
|
||||
import com.gpf.pethospital.service.ReportService;
|
||||
import com.gpf.pethospital.util.SecurityUtils;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/reports")
|
||||
public class ReportController {
|
||||
private final ReportService reportService;
|
||||
|
||||
public ReportController(ReportService reportService) {
|
||||
this.reportService = reportService;
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAnyRole('ADMIN','DOCTOR')")
|
||||
@PostMapping
|
||||
public ApiResponse<?> create(@RequestBody Report report) {
|
||||
reportService.save(report);
|
||||
return ApiResponse.success("created", null);
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
public ApiResponse<?> list(@RequestParam(defaultValue = "1") long page,
|
||||
@RequestParam(defaultValue = "10") long size,
|
||||
@RequestParam(required = false) Long petId) {
|
||||
AuthUser user = SecurityUtils.currentUser();
|
||||
LambdaQueryWrapper<Report> wrapper = new LambdaQueryWrapper<>();
|
||||
if (petId != null) {
|
||||
wrapper.eq(Report::getPetId, petId);
|
||||
}
|
||||
if (user != null && "DOCTOR".equals(user.getRole())) {
|
||||
wrapper.eq(Report::getDoctorId, user.getId());
|
||||
}
|
||||
return ApiResponse.success(reportService.page(new Page<>(page, size), wrapper));
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAnyRole('ADMIN','DOCTOR')")
|
||||
@PutMapping("/{id}")
|
||||
public ApiResponse<?> update(@PathVariable Long id, @RequestBody Report report) {
|
||||
report.setId(id);
|
||||
reportService.updateById(report);
|
||||
return ApiResponse.success("updated", null);
|
||||
}
|
||||
|
||||
@PreAuthorize("hasRole('ADMIN')")
|
||||
@DeleteMapping("/{id}")
|
||||
public ApiResponse<?> delete(@PathVariable Long id) {
|
||||
reportService.removeById(id);
|
||||
return ApiResponse.success("deleted", null);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
package com.gpf.pethospital.controller;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.gpf.pethospital.common.ApiResponse;
|
||||
import com.gpf.pethospital.entity.Order;
|
||||
import com.gpf.pethospital.entity.User;
|
||||
import com.gpf.pethospital.service.AppointmentService;
|
||||
import com.gpf.pethospital.service.OrderService;
|
||||
import com.gpf.pethospital.service.PetService;
|
||||
import com.gpf.pethospital.service.UserService;
|
||||
import com.gpf.pethospital.service.VisitService;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/admin/stats")
|
||||
public class StatsController {
|
||||
private final OrderService orderService;
|
||||
private final AppointmentService appointmentService;
|
||||
private final VisitService visitService;
|
||||
private final PetService petService;
|
||||
private final UserService userService;
|
||||
|
||||
public StatsController(OrderService orderService,
|
||||
AppointmentService appointmentService,
|
||||
VisitService visitService,
|
||||
PetService petService,
|
||||
UserService userService) {
|
||||
this.orderService = orderService;
|
||||
this.appointmentService = appointmentService;
|
||||
this.visitService = visitService;
|
||||
this.petService = petService;
|
||||
this.userService = userService;
|
||||
}
|
||||
|
||||
@PreAuthorize("hasRole('ADMIN')")
|
||||
@GetMapping
|
||||
public ApiResponse<?> summary() {
|
||||
Map<String, Object> data = new HashMap<>();
|
||||
data.put("orders", orderService.count());
|
||||
data.put("appointments", appointmentService.count());
|
||||
data.put("visits", visitService.count());
|
||||
data.put("pets", petService.count());
|
||||
data.put("customers", userService.count(new LambdaQueryWrapper<User>().eq(User::getRole, "CUSTOMER")));
|
||||
|
||||
QueryWrapper<Order> wrapper = new QueryWrapper<>();
|
||||
wrapper.select("SUM(amount) AS total");
|
||||
List<Map<String, Object>> result = orderService.listMaps(wrapper);
|
||||
BigDecimal total = BigDecimal.ZERO;
|
||||
if (!result.isEmpty() && result.get(0).get("total") != null) {
|
||||
total = new BigDecimal(result.get(0).get("total").toString());
|
||||
}
|
||||
data.put("orderAmountTotal", total);
|
||||
return ApiResponse.success(data);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package com.gpf.pethospital.controller;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.gpf.pethospital.common.ApiResponse;
|
||||
import com.gpf.pethospital.entity.Drug;
|
||||
import com.gpf.pethospital.entity.StockIn;
|
||||
import com.gpf.pethospital.service.DrugService;
|
||||
import com.gpf.pethospital.service.StockInService;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/stock-in")
|
||||
public class StockInController {
|
||||
private final StockInService stockInService;
|
||||
private final DrugService drugService;
|
||||
|
||||
public StockInController(StockInService stockInService, DrugService drugService) {
|
||||
this.stockInService = stockInService;
|
||||
this.drugService = drugService;
|
||||
}
|
||||
|
||||
@PreAuthorize("hasRole('ADMIN')")
|
||||
@GetMapping
|
||||
public ApiResponse<?> list(@RequestParam(defaultValue = "1") long page,
|
||||
@RequestParam(defaultValue = "10") long size,
|
||||
@RequestParam(required = false) Long drugId) {
|
||||
LambdaQueryWrapper<StockIn> wrapper = new LambdaQueryWrapper<>();
|
||||
if (drugId != null) {
|
||||
wrapper.eq(StockIn::getDrugId, drugId);
|
||||
}
|
||||
return ApiResponse.success(stockInService.page(new Page<>(page, size), wrapper));
|
||||
}
|
||||
|
||||
@PreAuthorize("hasRole('ADMIN')")
|
||||
@PostMapping
|
||||
@Transactional
|
||||
public ApiResponse<?> create(@RequestBody StockIn stockIn) {
|
||||
stockInService.save(stockIn);
|
||||
if (stockIn.getDrugId() != null && stockIn.getQuantity() != null) {
|
||||
Drug drug = drugService.getById(stockIn.getDrugId());
|
||||
if (drug != null) {
|
||||
int current = drug.getStock() == null ? 0 : drug.getStock();
|
||||
drug.setStock(current + stockIn.getQuantity());
|
||||
drugService.updateById(drug);
|
||||
}
|
||||
}
|
||||
return ApiResponse.success("created", null);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package com.gpf.pethospital.controller;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.gpf.pethospital.common.ApiResponse;
|
||||
import com.gpf.pethospital.entity.Drug;
|
||||
import com.gpf.pethospital.entity.StockOut;
|
||||
import com.gpf.pethospital.service.DrugService;
|
||||
import com.gpf.pethospital.service.StockOutService;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/stock-out")
|
||||
public class StockOutController {
|
||||
private final StockOutService stockOutService;
|
||||
private final DrugService drugService;
|
||||
|
||||
public StockOutController(StockOutService stockOutService, DrugService drugService) {
|
||||
this.stockOutService = stockOutService;
|
||||
this.drugService = drugService;
|
||||
}
|
||||
|
||||
@PreAuthorize("hasRole('ADMIN')")
|
||||
@GetMapping
|
||||
public ApiResponse<?> list(@RequestParam(defaultValue = "1") long page,
|
||||
@RequestParam(defaultValue = "10") long size,
|
||||
@RequestParam(required = false) Long drugId) {
|
||||
LambdaQueryWrapper<StockOut> wrapper = new LambdaQueryWrapper<>();
|
||||
if (drugId != null) {
|
||||
wrapper.eq(StockOut::getDrugId, drugId);
|
||||
}
|
||||
return ApiResponse.success(stockOutService.page(new Page<>(page, size), wrapper));
|
||||
}
|
||||
|
||||
@PreAuthorize("hasRole('ADMIN')")
|
||||
@PostMapping
|
||||
@Transactional
|
||||
public ApiResponse<?> create(@RequestBody StockOut stockOut) {
|
||||
stockOutService.save(stockOut);
|
||||
if (stockOut.getDrugId() != null && stockOut.getQuantity() != null) {
|
||||
Drug drug = drugService.getById(stockOut.getDrugId());
|
||||
if (drug != null) {
|
||||
int current = drug.getStock() == null ? 0 : drug.getStock();
|
||||
drug.setStock(Math.max(0, current - stockOut.getQuantity()));
|
||||
drugService.updateById(drug);
|
||||
}
|
||||
}
|
||||
return ApiResponse.success("created", null);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
package com.gpf.pethospital.controller;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.gpf.pethospital.common.ApiResponse;
|
||||
import com.gpf.pethospital.entity.User;
|
||||
import com.gpf.pethospital.security.AuthUser;
|
||||
import com.gpf.pethospital.service.UserService;
|
||||
import com.gpf.pethospital.util.SecurityUtils;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/users")
|
||||
public class UserController {
|
||||
private final UserService userService;
|
||||
private final PasswordEncoder passwordEncoder;
|
||||
|
||||
public UserController(UserService userService, PasswordEncoder passwordEncoder) {
|
||||
this.userService = userService;
|
||||
this.passwordEncoder = passwordEncoder;
|
||||
}
|
||||
|
||||
@GetMapping("/me")
|
||||
public ApiResponse<?> me() {
|
||||
AuthUser authUser = SecurityUtils.currentUser();
|
||||
if (authUser == null) {
|
||||
return ApiResponse.error(401, "unauthorized");
|
||||
}
|
||||
User user = userService.getById(authUser.getId());
|
||||
if (user != null) {
|
||||
user.setPassword(null);
|
||||
}
|
||||
return ApiResponse.success(user);
|
||||
}
|
||||
|
||||
@PutMapping("/me")
|
||||
public ApiResponse<?> updateMe(@RequestBody User payload) {
|
||||
AuthUser authUser = SecurityUtils.currentUser();
|
||||
if (authUser == null) {
|
||||
return ApiResponse.error(401, "unauthorized");
|
||||
}
|
||||
User update = new User();
|
||||
update.setId(authUser.getId());
|
||||
update.setUsername(payload.getUsername());
|
||||
update.setPhone(payload.getPhone());
|
||||
update.setEmail(payload.getEmail());
|
||||
update.setAvatar(payload.getAvatar());
|
||||
userService.updateById(update);
|
||||
return ApiResponse.success("updated", null);
|
||||
}
|
||||
|
||||
@PreAuthorize("hasRole('ADMIN')")
|
||||
@GetMapping
|
||||
public ApiResponse<?> list(@RequestParam(defaultValue = "1") long page,
|
||||
@RequestParam(defaultValue = "10") long size,
|
||||
@RequestParam(required = false) String role) {
|
||||
LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
|
||||
if (role != null && !role.isBlank()) {
|
||||
wrapper.eq(User::getRole, role);
|
||||
}
|
||||
Page<User> result = userService.page(new Page<>(page, size), wrapper);
|
||||
result.getRecords().forEach(u -> u.setPassword(null));
|
||||
return ApiResponse.success(result);
|
||||
}
|
||||
|
||||
@PreAuthorize("hasRole('ADMIN')")
|
||||
@PostMapping
|
||||
public ApiResponse<?> create(@RequestBody User user) {
|
||||
if (user.getPassword() == null || user.getPassword().isBlank()) {
|
||||
return ApiResponse.error(400, "password required");
|
||||
}
|
||||
user.setPassword(passwordEncoder.encode(user.getPassword()));
|
||||
if (user.getStatus() == null) {
|
||||
user.setStatus(1);
|
||||
}
|
||||
userService.save(user);
|
||||
return ApiResponse.success("created", null);
|
||||
}
|
||||
|
||||
@PreAuthorize("hasRole('ADMIN')")
|
||||
@PutMapping("/{id}/status")
|
||||
public ApiResponse<?> updateStatus(@PathVariable Long id, @RequestParam Integer status) {
|
||||
User update = new User();
|
||||
update.setId(id);
|
||||
update.setStatus(status);
|
||||
userService.updateById(update);
|
||||
return ApiResponse.success("updated", null);
|
||||
}
|
||||
|
||||
@PreAuthorize("hasRole('ADMIN')")
|
||||
@PutMapping("/{id}/reset-password")
|
||||
public ApiResponse<?> resetPassword(@PathVariable Long id, @RequestParam String newPassword) {
|
||||
User update = new User();
|
||||
update.setId(id);
|
||||
update.setPassword(passwordEncoder.encode(newPassword));
|
||||
userService.updateById(update);
|
||||
return ApiResponse.success("updated", null);
|
||||
}
|
||||
|
||||
@PreAuthorize("hasRole('ADMIN')")
|
||||
@GetMapping("/stats")
|
||||
public ApiResponse<?> stats() {
|
||||
Map<String, Object> data = new HashMap<>();
|
||||
data.put("total", userService.count());
|
||||
data.put("admins", userService.count(new LambdaQueryWrapper<User>().eq(User::getRole, "ADMIN")));
|
||||
data.put("doctors", userService.count(new LambdaQueryWrapper<User>().eq(User::getRole, "DOCTOR")));
|
||||
data.put("customers", userService.count(new LambdaQueryWrapper<User>().eq(User::getRole, "CUSTOMER")));
|
||||
return ApiResponse.success(data);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package com.gpf.pethospital.controller;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.gpf.pethospital.common.ApiResponse;
|
||||
import com.gpf.pethospital.entity.Pet;
|
||||
import com.gpf.pethospital.entity.VaccineRecord;
|
||||
import com.gpf.pethospital.security.AuthUser;
|
||||
import com.gpf.pethospital.service.PetService;
|
||||
import com.gpf.pethospital.service.VaccineRecordService;
|
||||
import com.gpf.pethospital.util.SecurityUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/vaccines")
|
||||
public class VaccineRecordController {
|
||||
private final VaccineRecordService vaccineRecordService;
|
||||
private final PetService petService;
|
||||
|
||||
public VaccineRecordController(VaccineRecordService vaccineRecordService, PetService petService) {
|
||||
this.vaccineRecordService = vaccineRecordService;
|
||||
this.petService = petService;
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
public ApiResponse<?> list(@RequestParam Long petId,
|
||||
@RequestParam(defaultValue = "1") long page,
|
||||
@RequestParam(defaultValue = "10") long size) {
|
||||
AuthUser user = SecurityUtils.currentUser();
|
||||
if (user != null && "CUSTOMER".equals(user.getRole())) {
|
||||
Pet pet = petService.getById(petId);
|
||||
if (pet == null || !pet.getOwnerId().equals(user.getId())) {
|
||||
return ApiResponse.error(403, "forbidden");
|
||||
}
|
||||
}
|
||||
LambdaQueryWrapper<VaccineRecord> wrapper = new LambdaQueryWrapper<VaccineRecord>()
|
||||
.eq(VaccineRecord::getPetId, petId);
|
||||
return ApiResponse.success(vaccineRecordService.page(new Page<>(page, size), wrapper));
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
public ApiResponse<?> create(@RequestBody VaccineRecord record) {
|
||||
vaccineRecordService.save(record);
|
||||
return ApiResponse.success("created", null);
|
||||
}
|
||||
|
||||
@PutMapping("/{id}")
|
||||
public ApiResponse<?> update(@PathVariable Long id, @RequestBody VaccineRecord record) {
|
||||
record.setId(id);
|
||||
vaccineRecordService.updateById(record);
|
||||
return ApiResponse.success("updated", null);
|
||||
}
|
||||
|
||||
@DeleteMapping("/{id}")
|
||||
public ApiResponse<?> delete(@PathVariable Long id) {
|
||||
vaccineRecordService.removeById(id);
|
||||
return ApiResponse.success("deleted", null);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package com.gpf.pethospital.controller;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.gpf.pethospital.common.ApiResponse;
|
||||
import com.gpf.pethospital.entity.Visit;
|
||||
import com.gpf.pethospital.security.AuthUser;
|
||||
import com.gpf.pethospital.service.VisitService;
|
||||
import com.gpf.pethospital.util.SecurityUtils;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/visits")
|
||||
public class VisitController {
|
||||
private final VisitService visitService;
|
||||
|
||||
public VisitController(VisitService visitService) {
|
||||
this.visitService = visitService;
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAnyRole('ADMIN','DOCTOR')")
|
||||
@PostMapping
|
||||
public ApiResponse<?> create(@RequestBody Visit visit) {
|
||||
if (visit.getStatus() == null) {
|
||||
visit.setStatus("IN_PROGRESS");
|
||||
}
|
||||
if (visit.getPaymentStatus() == null) {
|
||||
visit.setPaymentStatus("UNPAID");
|
||||
}
|
||||
visitService.save(visit);
|
||||
return ApiResponse.success("created", null);
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
public ApiResponse<?> list(@RequestParam(defaultValue = "1") long page,
|
||||
@RequestParam(defaultValue = "10") long size) {
|
||||
AuthUser user = SecurityUtils.currentUser();
|
||||
LambdaQueryWrapper<Visit> wrapper = new LambdaQueryWrapper<>();
|
||||
if (user != null) {
|
||||
if ("CUSTOMER".equals(user.getRole())) {
|
||||
wrapper.eq(Visit::getCustomerId, user.getId());
|
||||
} else if ("DOCTOR".equals(user.getRole())) {
|
||||
wrapper.eq(Visit::getDoctorId, user.getId());
|
||||
}
|
||||
}
|
||||
return ApiResponse.success(visitService.page(new Page<>(page, size), wrapper));
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAnyRole('ADMIN','DOCTOR')")
|
||||
@PutMapping("/{id}")
|
||||
public ApiResponse<?> update(@PathVariable Long id, @RequestBody Visit visit) {
|
||||
visit.setId(id);
|
||||
visitService.updateById(visit);
|
||||
return ApiResponse.success("updated", null);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.gpf.pethospital.dto;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
|
||||
public class LoginRequest {
|
||||
@NotBlank
|
||||
private String account;
|
||||
@NotBlank
|
||||
private String password;
|
||||
|
||||
public String getAccount() {
|
||||
return account;
|
||||
}
|
||||
|
||||
public void setAccount(String account) {
|
||||
this.account = account;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
public void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package com.gpf.pethospital.dto;
|
||||
|
||||
import jakarta.validation.constraints.Email;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
|
||||
public class RegisterRequest {
|
||||
@NotBlank
|
||||
private String username;
|
||||
private String phone;
|
||||
@Email
|
||||
private String email;
|
||||
@NotBlank
|
||||
private String password;
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public void setUsername(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
public String getPhone() {
|
||||
return phone;
|
||||
}
|
||||
|
||||
public void setPhone(String phone) {
|
||||
this.phone = phone;
|
||||
}
|
||||
|
||||
public String getEmail() {
|
||||
return email;
|
||||
}
|
||||
|
||||
public void setEmail(String email) {
|
||||
this.email = email;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
public void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.gpf.pethospital.dto;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
|
||||
public class ReplyRequest {
|
||||
@NotBlank
|
||||
private String reply;
|
||||
|
||||
public String getReply() {
|
||||
return reply;
|
||||
}
|
||||
|
||||
public void setReply(String reply) {
|
||||
this.reply = reply;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
package com.gpf.pethospital.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 门诊预约实体
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
@TableName("appointment")
|
||||
public class Appointment {
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 顾客ID
|
||||
*/
|
||||
private Long customerId;
|
||||
|
||||
/**
|
||||
* 宠物ID
|
||||
*/
|
||||
private Long petId;
|
||||
|
||||
/**
|
||||
* 预约医生ID(可为空,表示不指定医生)
|
||||
*/
|
||||
private Long doctorId;
|
||||
|
||||
/**
|
||||
* 科室
|
||||
*/
|
||||
private String department;
|
||||
|
||||
/**
|
||||
* 预约日期
|
||||
*/
|
||||
private LocalDate appointmentDate;
|
||||
|
||||
/**
|
||||
* 预约时段(例如:09:00-10:00)
|
||||
*/
|
||||
private String timeSlot;
|
||||
|
||||
/**
|
||||
* 预约状态:PENDING-待确认, CONFIRMED-已确认, ARRIVED-已到诊, CANCELLED-已取消, NO_SHOW-爽约
|
||||
*/
|
||||
private String status;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String remark;
|
||||
|
||||
/**
|
||||
* 取消时间
|
||||
*/
|
||||
private LocalDateTime cancelTime;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@TableField(fill = FieldFill.INSERT)
|
||||
private LocalDateTime createTime;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
@TableField(fill = FieldFill.INSERT_UPDATE)
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
/**
|
||||
* 删除标记:0-未删除, 1-已删除
|
||||
*/
|
||||
@TableLogic
|
||||
private Integer deleted;
|
||||
}
|
||||
93
backend/src/main/java/com/gpf/pethospital/entity/Drug.java
Normal file
93
backend/src/main/java/com/gpf/pethospital/entity/Drug.java
Normal file
@@ -0,0 +1,93 @@
|
||||
package com.gpf.pethospital.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 药品实体
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
@TableName("drug")
|
||||
public class Drug {
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 药品名称
|
||||
*/
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 规格
|
||||
*/
|
||||
private String specification;
|
||||
|
||||
/**
|
||||
* 单位(如:片、盒、瓶)
|
||||
*/
|
||||
private String unit;
|
||||
|
||||
/**
|
||||
* 当前库存数量
|
||||
*/
|
||||
private Integer stock;
|
||||
|
||||
/**
|
||||
* 预警阈值
|
||||
*/
|
||||
private Integer alertThreshold;
|
||||
|
||||
/**
|
||||
* 进价
|
||||
*/
|
||||
private BigDecimal purchasePrice;
|
||||
|
||||
/**
|
||||
* 售价
|
||||
*/
|
||||
private BigDecimal salePrice;
|
||||
|
||||
/**
|
||||
* 生产厂家
|
||||
*/
|
||||
private String manufacturer;
|
||||
|
||||
/**
|
||||
* 批准文号
|
||||
*/
|
||||
private String approvalNumber;
|
||||
|
||||
/**
|
||||
* 有效期
|
||||
*/
|
||||
private LocalDateTime expiryDate;
|
||||
|
||||
/**
|
||||
* 状态:0-禁用, 1-启用
|
||||
*/
|
||||
private Integer status;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@TableField(fill = FieldFill.INSERT)
|
||||
private LocalDateTime createTime;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
@TableField(fill = FieldFill.INSERT_UPDATE)
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
/**
|
||||
* 删除标记:0-未删除, 1-已删除
|
||||
*/
|
||||
@TableLogic
|
||||
private Integer deleted;
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
package com.gpf.pethospital.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 病历实体
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
@TableName("medical_record")
|
||||
public class MedicalRecord {
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 就诊记录ID
|
||||
*/
|
||||
private Long visitId;
|
||||
|
||||
/**
|
||||
* 主诉
|
||||
*/
|
||||
private String chiefComplaint;
|
||||
|
||||
/**
|
||||
* 现病史
|
||||
*/
|
||||
private String presentIllness;
|
||||
|
||||
/**
|
||||
* 体格检查
|
||||
*/
|
||||
private String physicalExamination;
|
||||
|
||||
/**
|
||||
* 检查结果
|
||||
*/
|
||||
private String examinationResults;
|
||||
|
||||
/**
|
||||
* 诊断结论
|
||||
*/
|
||||
private String diagnosis;
|
||||
|
||||
/**
|
||||
* 治疗方案
|
||||
*/
|
||||
private String treatmentPlan;
|
||||
|
||||
/**
|
||||
* 医嘱
|
||||
*/
|
||||
private String advice;
|
||||
|
||||
/**
|
||||
* 状态:DRAFT-草稿, COMPLETED-已完成
|
||||
*/
|
||||
private String status;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@TableField(fill = FieldFill.INSERT)
|
||||
private LocalDateTime createTime;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
@TableField(fill = FieldFill.INSERT_UPDATE)
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
/**
|
||||
* 删除标记:0-未删除, 1-已删除
|
||||
*/
|
||||
@TableLogic
|
||||
private Integer deleted;
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
package com.gpf.pethospital.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 留言实体
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
@TableName("message")
|
||||
public class Message {
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 留言人ID
|
||||
*/
|
||||
private Long userId;
|
||||
|
||||
/**
|
||||
* 留言人姓名
|
||||
*/
|
||||
private String userName;
|
||||
|
||||
/**
|
||||
* 联系方式
|
||||
*/
|
||||
private String contact;
|
||||
|
||||
/**
|
||||
* 标题
|
||||
*/
|
||||
private String title;
|
||||
|
||||
/**
|
||||
* 内容
|
||||
*/
|
||||
private String content;
|
||||
|
||||
/**
|
||||
* 处理状态:PENDING-待处理, PROCESSED-已处理
|
||||
*/
|
||||
private String status;
|
||||
|
||||
/**
|
||||
* 回复内容
|
||||
*/
|
||||
private String reply;
|
||||
|
||||
/**
|
||||
* 回复时间
|
||||
*/
|
||||
private LocalDateTime replyTime;
|
||||
|
||||
/**
|
||||
* 回复者ID
|
||||
*/
|
||||
private Long replyUserId;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@TableField(fill = FieldFill.INSERT)
|
||||
private LocalDateTime createTime;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
@TableField(fill = FieldFill.INSERT_UPDATE)
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
/**
|
||||
* 删除标记:0-未删除, 1-已删除
|
||||
*/
|
||||
@TableLogic
|
||||
private Integer deleted;
|
||||
}
|
||||
62
backend/src/main/java/com/gpf/pethospital/entity/Notice.java
Normal file
62
backend/src/main/java/com/gpf/pethospital/entity/Notice.java
Normal file
@@ -0,0 +1,62 @@
|
||||
package com.gpf.pethospital.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 公告实体
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
@TableName("notice")
|
||||
public class Notice {
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 标题
|
||||
*/
|
||||
private String title;
|
||||
|
||||
/**
|
||||
* 内容
|
||||
*/
|
||||
private String content;
|
||||
|
||||
/**
|
||||
* 是否置顶:0-否, 1-是
|
||||
*/
|
||||
private Integer isTop;
|
||||
|
||||
/**
|
||||
* 状态:0-下架, 1-上架
|
||||
*/
|
||||
private Integer status;
|
||||
|
||||
/**
|
||||
* 发布者ID
|
||||
*/
|
||||
private Long publisherId;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@TableField(fill = FieldFill.INSERT)
|
||||
private LocalDateTime createTime;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
@TableField(fill = FieldFill.INSERT_UPDATE)
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
/**
|
||||
* 删除标记:0-未删除, 1-已删除
|
||||
*/
|
||||
@TableLogic
|
||||
private Integer deleted;
|
||||
}
|
||||
78
backend/src/main/java/com/gpf/pethospital/entity/Order.java
Normal file
78
backend/src/main/java/com/gpf/pethospital/entity/Order.java
Normal file
@@ -0,0 +1,78 @@
|
||||
package com.gpf.pethospital.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.FieldFill;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableLogic;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 订单实体
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
@TableName("order_info")
|
||||
public class Order {
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 就诊记录ID
|
||||
*/
|
||||
private Long visitId;
|
||||
|
||||
/**
|
||||
* 顾客ID
|
||||
*/
|
||||
private Long customerId;
|
||||
|
||||
/**
|
||||
* 订单金额
|
||||
*/
|
||||
private BigDecimal amount;
|
||||
|
||||
/**
|
||||
* 订单状态:UNPAID-未支付, PAID-已支付, CANCELLED-已取消, REFUNDING-退款中, REFUNDED-已退款
|
||||
*/
|
||||
private String status;
|
||||
|
||||
/**
|
||||
* 支付方式:OFFLINE-线下支付, ALIPAY-支付宝, WECHAT-微信支付
|
||||
*/
|
||||
private String paymentMethod;
|
||||
|
||||
/**
|
||||
* 支付时间
|
||||
*/
|
||||
private LocalDateTime paymentTime;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String remark;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@TableField(fill = FieldFill.INSERT)
|
||||
private LocalDateTime createTime;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
@TableField(fill = FieldFill.INSERT_UPDATE)
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
/**
|
||||
* 删除标记:0-未删除, 1-已删除
|
||||
*/
|
||||
@TableLogic
|
||||
private Integer deleted;
|
||||
}
|
||||
78
backend/src/main/java/com/gpf/pethospital/entity/Pet.java
Normal file
78
backend/src/main/java/com/gpf/pethospital/entity/Pet.java
Normal file
@@ -0,0 +1,78 @@
|
||||
package com.gpf.pethospital.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 宠物实体
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
@TableName("pet")
|
||||
public class Pet {
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 宠物主人ID
|
||||
*/
|
||||
private Long ownerId;
|
||||
|
||||
/**
|
||||
* 宠物名称
|
||||
*/
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 品种
|
||||
*/
|
||||
private String breed;
|
||||
|
||||
/**
|
||||
* 性别:MALE-雄性, FEMALE-雌性
|
||||
*/
|
||||
private String gender;
|
||||
|
||||
/**
|
||||
* 生日
|
||||
*/
|
||||
private LocalDate birthday;
|
||||
|
||||
/**
|
||||
* 体重(kg)
|
||||
*/
|
||||
private Double weight;
|
||||
|
||||
/**
|
||||
* 照片URL
|
||||
*/
|
||||
private String photo;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String remark;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@TableField(fill = FieldFill.INSERT)
|
||||
private LocalDateTime createTime;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
@TableField(fill = FieldFill.INSERT_UPDATE)
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
/**
|
||||
* 删除标记:0-未删除, 1-已删除
|
||||
*/
|
||||
@TableLogic
|
||||
private Integer deleted;
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package com.gpf.pethospital.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 处方实体
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
@TableName("prescription")
|
||||
public class Prescription {
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 就诊记录ID
|
||||
*/
|
||||
private Long visitId;
|
||||
|
||||
/**
|
||||
* 医生ID
|
||||
*/
|
||||
private Long doctorId;
|
||||
|
||||
/**
|
||||
* 处方状态:DRAFT-草稿, SUBMITTED-已提交, ISSUED-已发药, VOIDED-已作废
|
||||
*/
|
||||
private String status;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String remark;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@TableField(fill = FieldFill.INSERT)
|
||||
private LocalDateTime createTime;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
@TableField(fill = FieldFill.INSERT_UPDATE)
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
/**
|
||||
* 删除标记:0-未删除, 1-已删除
|
||||
*/
|
||||
@TableLogic
|
||||
private Integer deleted;
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
package com.gpf.pethospital.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 处方明细实体
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
@TableName("prescription_item")
|
||||
public class PrescriptionItem {
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 处方ID
|
||||
*/
|
||||
private Long prescriptionId;
|
||||
|
||||
/**
|
||||
* 药品ID
|
||||
*/
|
||||
private Long drugId;
|
||||
|
||||
/**
|
||||
* 药品名称(冗余字段,方便查询)
|
||||
*/
|
||||
private String drugName;
|
||||
|
||||
/**
|
||||
* 规格
|
||||
*/
|
||||
private String specification;
|
||||
|
||||
/**
|
||||
* 数量
|
||||
*/
|
||||
private Integer quantity;
|
||||
|
||||
/**
|
||||
* 用法用量
|
||||
*/
|
||||
private String usage;
|
||||
|
||||
/**
|
||||
* 用药天数
|
||||
*/
|
||||
private Integer days;
|
||||
|
||||
/**
|
||||
* 单价
|
||||
*/
|
||||
private BigDecimal unitPrice;
|
||||
|
||||
/**
|
||||
* 小计
|
||||
*/
|
||||
private BigDecimal subtotal;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@TableField(fill = FieldFill.INSERT)
|
||||
private LocalDateTime createTime;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
@TableField(fill = FieldFill.INSERT_UPDATE)
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
/**
|
||||
* 删除标记:0-未删除, 1-已删除
|
||||
*/
|
||||
@TableLogic
|
||||
private Integer deleted;
|
||||
}
|
||||
72
backend/src/main/java/com/gpf/pethospital/entity/Report.java
Normal file
72
backend/src/main/java/com/gpf/pethospital/entity/Report.java
Normal file
@@ -0,0 +1,72 @@
|
||||
package com.gpf.pethospital.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 检查报告实体
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
@TableName("report")
|
||||
public class Report {
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 就诊记录ID
|
||||
*/
|
||||
private Long visitId;
|
||||
|
||||
/**
|
||||
* 宠物ID
|
||||
*/
|
||||
private Long petId;
|
||||
|
||||
/**
|
||||
* 报告类型(如:血常规、X光、B超等)
|
||||
*/
|
||||
private String type;
|
||||
|
||||
/**
|
||||
* 报告名称
|
||||
*/
|
||||
private String title;
|
||||
|
||||
/**
|
||||
* 报告内容摘要
|
||||
*/
|
||||
private String summary;
|
||||
|
||||
/**
|
||||
* 附件URL(图片或PDF)
|
||||
*/
|
||||
private String attachmentUrl;
|
||||
|
||||
/**
|
||||
* 检查医生ID
|
||||
*/
|
||||
private Long doctorId;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@TableField(fill = FieldFill.INSERT)
|
||||
private LocalDateTime createTime;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
@TableField(fill = FieldFill.INSERT_UPDATE)
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
/**
|
||||
* 删除标记:0-未删除, 1-已删除
|
||||
*/
|
||||
@TableLogic
|
||||
private Integer deleted;
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
package com.gpf.pethospital.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.FieldFill;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableLogic;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 入库流水实体
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
@TableName("stock_in")
|
||||
public class StockIn {
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 药品ID
|
||||
*/
|
||||
private Long drugId;
|
||||
|
||||
/**
|
||||
* 入库数量
|
||||
*/
|
||||
private Integer quantity;
|
||||
|
||||
/**
|
||||
* 经办人ID
|
||||
*/
|
||||
private Long operatorId;
|
||||
|
||||
/**
|
||||
* 入库时间
|
||||
*/
|
||||
private LocalDateTime stockInTime;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String remark;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@TableField(fill = FieldFill.INSERT)
|
||||
private LocalDateTime createTime;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
@TableField(fill = FieldFill.INSERT_UPDATE)
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
/**
|
||||
* 删除标记:0-未删除, 1-已删除
|
||||
*/
|
||||
@TableLogic
|
||||
private Integer deleted;
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
package com.gpf.pethospital.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.FieldFill;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableLogic;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 出库/消耗流水实体
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
@TableName("stock_out")
|
||||
public class StockOut {
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 药品ID
|
||||
*/
|
||||
private Long drugId;
|
||||
|
||||
/**
|
||||
* 处方ID(可为空)
|
||||
*/
|
||||
private Long prescriptionId;
|
||||
|
||||
/**
|
||||
* 出库数量
|
||||
*/
|
||||
private Integer quantity;
|
||||
|
||||
/**
|
||||
* 经办人ID
|
||||
*/
|
||||
private Long operatorId;
|
||||
|
||||
/**
|
||||
* 出库时间
|
||||
*/
|
||||
private LocalDateTime stockOutTime;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String remark;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@TableField(fill = FieldFill.INSERT)
|
||||
private LocalDateTime createTime;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
@TableField(fill = FieldFill.INSERT_UPDATE)
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
/**
|
||||
* 删除标记:0-未删除, 1-已删除
|
||||
*/
|
||||
@TableLogic
|
||||
private Integer deleted;
|
||||
}
|
||||
72
backend/src/main/java/com/gpf/pethospital/entity/User.java
Normal file
72
backend/src/main/java/com/gpf/pethospital/entity/User.java
Normal file
@@ -0,0 +1,72 @@
|
||||
package com.gpf.pethospital.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 用户实体
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
@TableName("`user`")
|
||||
public class User {
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 用户名/姓名
|
||||
*/
|
||||
private String username;
|
||||
|
||||
/**
|
||||
* 手机号
|
||||
*/
|
||||
private String phone;
|
||||
|
||||
/**
|
||||
* 邮箱
|
||||
*/
|
||||
private String email;
|
||||
|
||||
/**
|
||||
* 密码(加密后)
|
||||
*/
|
||||
private String password;
|
||||
|
||||
/**
|
||||
* 角色:ADMIN-管理员, DOCTOR-医生, CUSTOMER-顾客
|
||||
*/
|
||||
private String role;
|
||||
|
||||
/**
|
||||
* 状态:0-禁用, 1-启用
|
||||
*/
|
||||
private Integer status;
|
||||
|
||||
/**
|
||||
* 头像URL
|
||||
*/
|
||||
private String avatar;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@TableField(fill = FieldFill.INSERT)
|
||||
private LocalDateTime createTime;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
@TableField(fill = FieldFill.INSERT_UPDATE)
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
/**
|
||||
* 删除标记:0-未删除, 1-已删除
|
||||
*/
|
||||
@TableLogic
|
||||
private Integer deleted;
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
package com.gpf.pethospital.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 疫苗/驱虫记录实体
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
@TableName("vaccine_record")
|
||||
public class VaccineRecord {
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 宠物ID
|
||||
*/
|
||||
private Long petId;
|
||||
|
||||
/**
|
||||
* 记录类型:VACCINE-疫苗, DEWORMING-驱虫
|
||||
*/
|
||||
private String type;
|
||||
|
||||
/**
|
||||
* 项目名称(如:狂犬疫苗、体内驱虫等)
|
||||
*/
|
||||
private String itemName;
|
||||
|
||||
/**
|
||||
* 执行日期
|
||||
*/
|
||||
private LocalDate executeDate;
|
||||
|
||||
/**
|
||||
* 下次提醒日期
|
||||
*/
|
||||
private LocalDate nextReminderDate;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String remark;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@TableField(fill = FieldFill.INSERT)
|
||||
private LocalDateTime createTime;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
@TableField(fill = FieldFill.INSERT_UPDATE)
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
/**
|
||||
* 删除标记:0-未删除, 1-已删除
|
||||
*/
|
||||
@TableLogic
|
||||
private Integer deleted;
|
||||
}
|
||||
93
backend/src/main/java/com/gpf/pethospital/entity/Visit.java
Normal file
93
backend/src/main/java/com/gpf/pethospital/entity/Visit.java
Normal file
@@ -0,0 +1,93 @@
|
||||
package com.gpf.pethospital.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 就诊记录实体
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
@TableName("visit")
|
||||
public class Visit {
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 预约ID(可为空,现场挂号无预约)
|
||||
*/
|
||||
private Long appointmentId;
|
||||
|
||||
/**
|
||||
* 顾客ID
|
||||
*/
|
||||
private Long customerId;
|
||||
|
||||
/**
|
||||
* 宠物ID
|
||||
*/
|
||||
private Long petId;
|
||||
|
||||
/**
|
||||
* 接诊医生ID
|
||||
*/
|
||||
private Long doctorId;
|
||||
|
||||
/**
|
||||
* 就诊状态:IN_PROGRESS-就诊中, COMPLETED-已完成
|
||||
*/
|
||||
private String status;
|
||||
|
||||
/**
|
||||
* 总费用
|
||||
*/
|
||||
private BigDecimal totalAmount;
|
||||
|
||||
/**
|
||||
* 支付状态:UNPAID-未支付, PAID-已支付, REFUNDING-退款中, REFUNDED-已退款
|
||||
*/
|
||||
private String paymentStatus;
|
||||
|
||||
/**
|
||||
* 支付方式:OFFLINE-线下支付, ALIPAY-支付宝, WECHAT-微信支付
|
||||
*/
|
||||
private String paymentMethod;
|
||||
|
||||
/**
|
||||
* 支付时间
|
||||
*/
|
||||
private LocalDateTime paymentTime;
|
||||
|
||||
/**
|
||||
* 开始就诊时间
|
||||
*/
|
||||
private LocalDateTime startTime;
|
||||
|
||||
/**
|
||||
* 结束就诊时间
|
||||
*/
|
||||
private LocalDateTime endTime;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@TableField(fill = FieldFill.INSERT)
|
||||
private LocalDateTime createTime;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
@TableField(fill = FieldFill.INSERT_UPDATE)
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
/**
|
||||
* 删除标记:0-未删除, 1-已删除
|
||||
*/
|
||||
@TableLogic
|
||||
private Integer deleted;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.gpf.pethospital.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.gpf.pethospital.entity.Appointment;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface AppointmentMapper extends BaseMapper<Appointment> {
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.gpf.pethospital.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.gpf.pethospital.entity.Drug;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface DrugMapper extends BaseMapper<Drug> {
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.gpf.pethospital.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.gpf.pethospital.entity.MedicalRecord;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface MedicalRecordMapper extends BaseMapper<MedicalRecord> {
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.gpf.pethospital.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.gpf.pethospital.entity.Message;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface MessageMapper extends BaseMapper<Message> {
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.gpf.pethospital.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.gpf.pethospital.entity.Notice;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface NoticeMapper extends BaseMapper<Notice> {
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.gpf.pethospital.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.gpf.pethospital.entity.Order;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface OrderMapper extends BaseMapper<Order> {
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.gpf.pethospital.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.gpf.pethospital.entity.Pet;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface PetMapper extends BaseMapper<Pet> {
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.gpf.pethospital.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.gpf.pethospital.entity.PrescriptionItem;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface PrescriptionItemMapper extends BaseMapper<PrescriptionItem> {
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.gpf.pethospital.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.gpf.pethospital.entity.Prescription;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface PrescriptionMapper extends BaseMapper<Prescription> {
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.gpf.pethospital.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.gpf.pethospital.entity.Report;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface ReportMapper extends BaseMapper<Report> {
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.gpf.pethospital.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.gpf.pethospital.entity.StockIn;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface StockInMapper extends BaseMapper<StockIn> {
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.gpf.pethospital.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.gpf.pethospital.entity.StockOut;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface StockOutMapper extends BaseMapper<StockOut> {
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.gpf.pethospital.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.gpf.pethospital.entity.User;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface UserMapper extends BaseMapper<User> {
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.gpf.pethospital.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.gpf.pethospital.entity.VaccineRecord;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface VaccineRecordMapper extends BaseMapper<VaccineRecord> {
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.gpf.pethospital.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.gpf.pethospital.entity.Visit;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface VisitMapper extends BaseMapper<Visit> {
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.gpf.pethospital.security;
|
||||
|
||||
public class AuthUser {
|
||||
private final Long id;
|
||||
private final String username;
|
||||
private final String role;
|
||||
|
||||
public AuthUser(Long id, String username, String role) {
|
||||
this.id = id;
|
||||
this.username = username;
|
||||
this.role = role;
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public String getRole() {
|
||||
return role;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package com.gpf.pethospital.security;
|
||||
|
||||
import com.gpf.pethospital.util.JwtUtil;
|
||||
import io.jsonwebtoken.Claims;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
|
||||
public class JwtAuthenticationFilter extends OncePerRequestFilter {
|
||||
private final JwtUtil jwtUtil;
|
||||
|
||||
public JwtAuthenticationFilter(JwtUtil jwtUtil) {
|
||||
this.jwtUtil = jwtUtil;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
|
||||
throws ServletException, IOException {
|
||||
String token = resolveToken(request);
|
||||
if (StringUtils.hasText(token)) {
|
||||
try {
|
||||
Claims claims = jwtUtil.parseToken(token);
|
||||
String username = claims.get("username", String.class);
|
||||
String role = claims.get("role", String.class);
|
||||
Number uid = claims.get("uid", Number.class);
|
||||
Long userId = uid == null ? null : uid.longValue();
|
||||
SimpleGrantedAuthority authority = new SimpleGrantedAuthority("ROLE_" + role);
|
||||
AuthUser principal = new AuthUser(userId, username, role);
|
||||
Authentication auth = new UsernamePasswordAuthenticationToken(principal, null, Collections.singleton(authority));
|
||||
SecurityContextHolder.getContext().setAuthentication(auth);
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
}
|
||||
filterChain.doFilter(request, response);
|
||||
}
|
||||
|
||||
private String resolveToken(HttpServletRequest request) {
|
||||
String bearer = request.getHeader("Authorization");
|
||||
if (StringUtils.hasText(bearer) && bearer.startsWith("Bearer ")) {
|
||||
return bearer.substring(7);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.gpf.pethospital.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.gpf.pethospital.entity.Appointment;
|
||||
|
||||
public interface AppointmentService extends IService<Appointment> {
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.gpf.pethospital.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.gpf.pethospital.entity.Drug;
|
||||
|
||||
public interface DrugService extends IService<Drug> {
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.gpf.pethospital.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.gpf.pethospital.entity.MedicalRecord;
|
||||
|
||||
public interface MedicalRecordService extends IService<MedicalRecord> {
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.gpf.pethospital.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.gpf.pethospital.entity.Message;
|
||||
|
||||
public interface MessageService extends IService<Message> {
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.gpf.pethospital.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.gpf.pethospital.entity.Notice;
|
||||
|
||||
public interface NoticeService extends IService<Notice> {
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.gpf.pethospital.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.gpf.pethospital.entity.Order;
|
||||
|
||||
public interface OrderService extends IService<Order> {
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.gpf.pethospital.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.gpf.pethospital.entity.Pet;
|
||||
|
||||
public interface PetService extends IService<Pet> {
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.gpf.pethospital.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.gpf.pethospital.entity.PrescriptionItem;
|
||||
|
||||
public interface PrescriptionItemService extends IService<PrescriptionItem> {
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.gpf.pethospital.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.gpf.pethospital.entity.Prescription;
|
||||
|
||||
public interface PrescriptionService extends IService<Prescription> {
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.gpf.pethospital.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.gpf.pethospital.entity.Report;
|
||||
|
||||
public interface ReportService extends IService<Report> {
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.gpf.pethospital.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.gpf.pethospital.entity.StockIn;
|
||||
|
||||
public interface StockInService extends IService<StockIn> {
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.gpf.pethospital.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.gpf.pethospital.entity.StockOut;
|
||||
|
||||
public interface StockOutService extends IService<StockOut> {
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.gpf.pethospital.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.gpf.pethospital.entity.User;
|
||||
|
||||
public interface UserService extends IService<User> {
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.gpf.pethospital.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.gpf.pethospital.entity.VaccineRecord;
|
||||
|
||||
public interface VaccineRecordService extends IService<VaccineRecord> {
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.gpf.pethospital.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.gpf.pethospital.entity.Visit;
|
||||
|
||||
public interface VisitService extends IService<Visit> {
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.gpf.pethospital.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.gpf.pethospital.entity.Appointment;
|
||||
import com.gpf.pethospital.mapper.AppointmentMapper;
|
||||
import com.gpf.pethospital.service.AppointmentService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class AppointmentServiceImpl extends ServiceImpl<AppointmentMapper, Appointment> implements AppointmentService {
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.gpf.pethospital.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.gpf.pethospital.entity.Drug;
|
||||
import com.gpf.pethospital.mapper.DrugMapper;
|
||||
import com.gpf.pethospital.service.DrugService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class DrugServiceImpl extends ServiceImpl<DrugMapper, Drug> implements DrugService {
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.gpf.pethospital.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.gpf.pethospital.entity.MedicalRecord;
|
||||
import com.gpf.pethospital.mapper.MedicalRecordMapper;
|
||||
import com.gpf.pethospital.service.MedicalRecordService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class MedicalRecordServiceImpl extends ServiceImpl<MedicalRecordMapper, MedicalRecord> implements MedicalRecordService {
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.gpf.pethospital.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.gpf.pethospital.entity.Message;
|
||||
import com.gpf.pethospital.mapper.MessageMapper;
|
||||
import com.gpf.pethospital.service.MessageService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class MessageServiceImpl extends ServiceImpl<MessageMapper, Message> implements MessageService {
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.gpf.pethospital.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.gpf.pethospital.entity.Notice;
|
||||
import com.gpf.pethospital.mapper.NoticeMapper;
|
||||
import com.gpf.pethospital.service.NoticeService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class NoticeServiceImpl extends ServiceImpl<NoticeMapper, Notice> implements NoticeService {
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.gpf.pethospital.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.gpf.pethospital.entity.Order;
|
||||
import com.gpf.pethospital.mapper.OrderMapper;
|
||||
import com.gpf.pethospital.service.OrderService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements OrderService {
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.gpf.pethospital.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.gpf.pethospital.entity.Pet;
|
||||
import com.gpf.pethospital.mapper.PetMapper;
|
||||
import com.gpf.pethospital.service.PetService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class PetServiceImpl extends ServiceImpl<PetMapper, Pet> implements PetService {
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.gpf.pethospital.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.gpf.pethospital.entity.PrescriptionItem;
|
||||
import com.gpf.pethospital.mapper.PrescriptionItemMapper;
|
||||
import com.gpf.pethospital.service.PrescriptionItemService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class PrescriptionItemServiceImpl extends ServiceImpl<PrescriptionItemMapper, PrescriptionItem> implements PrescriptionItemService {
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.gpf.pethospital.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.gpf.pethospital.entity.Prescription;
|
||||
import com.gpf.pethospital.mapper.PrescriptionMapper;
|
||||
import com.gpf.pethospital.service.PrescriptionService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class PrescriptionServiceImpl extends ServiceImpl<PrescriptionMapper, Prescription> implements PrescriptionService {
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.gpf.pethospital.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.gpf.pethospital.entity.Report;
|
||||
import com.gpf.pethospital.mapper.ReportMapper;
|
||||
import com.gpf.pethospital.service.ReportService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> implements ReportService {
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.gpf.pethospital.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.gpf.pethospital.entity.StockIn;
|
||||
import com.gpf.pethospital.mapper.StockInMapper;
|
||||
import com.gpf.pethospital.service.StockInService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class StockInServiceImpl extends ServiceImpl<StockInMapper, StockIn> implements StockInService {
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.gpf.pethospital.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.gpf.pethospital.entity.StockOut;
|
||||
import com.gpf.pethospital.mapper.StockOutMapper;
|
||||
import com.gpf.pethospital.service.StockOutService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class StockOutServiceImpl extends ServiceImpl<StockOutMapper, StockOut> implements StockOutService {
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.gpf.pethospital.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.gpf.pethospital.entity.User;
|
||||
import com.gpf.pethospital.mapper.UserMapper;
|
||||
import com.gpf.pethospital.service.UserService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.gpf.pethospital.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.gpf.pethospital.entity.VaccineRecord;
|
||||
import com.gpf.pethospital.mapper.VaccineRecordMapper;
|
||||
import com.gpf.pethospital.service.VaccineRecordService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class VaccineRecordServiceImpl extends ServiceImpl<VaccineRecordMapper, VaccineRecord> implements VaccineRecordService {
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.gpf.pethospital.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.gpf.pethospital.entity.Visit;
|
||||
import com.gpf.pethospital.mapper.VisitMapper;
|
||||
import com.gpf.pethospital.service.VisitService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class VisitServiceImpl extends ServiceImpl<VisitMapper, Visit> implements VisitService {
|
||||
}
|
||||
41
backend/src/main/java/com/gpf/pethospital/util/JwtUtil.java
Normal file
41
backend/src/main/java/com/gpf/pethospital/util/JwtUtil.java
Normal file
@@ -0,0 +1,41 @@
|
||||
package com.gpf.pethospital.util;
|
||||
|
||||
import io.jsonwebtoken.Claims;
|
||||
import io.jsonwebtoken.Jwts;
|
||||
import io.jsonwebtoken.SignatureAlgorithm;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class JwtUtil {
|
||||
private final String secret;
|
||||
private final long expirationMs;
|
||||
|
||||
public JwtUtil(String secret, long expirationMs) {
|
||||
this.secret = secret;
|
||||
this.expirationMs = expirationMs;
|
||||
}
|
||||
|
||||
public String generateToken(Long userId, String role, String username) {
|
||||
Map<String, Object> claims = new HashMap<>();
|
||||
claims.put("uid", userId);
|
||||
claims.put("role", role);
|
||||
claims.put("username", username);
|
||||
Date now = new Date();
|
||||
Date exp = new Date(now.getTime() + expirationMs);
|
||||
return Jwts.builder()
|
||||
.setClaims(claims)
|
||||
.setIssuedAt(now)
|
||||
.setExpiration(exp)
|
||||
.signWith(SignatureAlgorithm.HS256, secret)
|
||||
.compact();
|
||||
}
|
||||
|
||||
public Claims parseToken(String token) {
|
||||
return Jwts.parser()
|
||||
.setSigningKey(secret)
|
||||
.parseClaimsJws(token)
|
||||
.getBody();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.gpf.pethospital.util;
|
||||
|
||||
import com.gpf.pethospital.security.AuthUser;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
|
||||
public class SecurityUtils {
|
||||
public static AuthUser currentUser() {
|
||||
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
||||
if (authentication != null && authentication.getPrincipal() instanceof AuthUser) {
|
||||
return (AuthUser) authentication.getPrincipal();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
61
backend/src/main/resources/application-dev.yml
Normal file
61
backend/src/main/resources/application-dev.yml
Normal file
@@ -0,0 +1,61 @@
|
||||
server:
|
||||
port: 8081
|
||||
servlet:
|
||||
context-path: /api
|
||||
|
||||
spring:
|
||||
application:
|
||||
name: pet-hospital
|
||||
|
||||
datasource:
|
||||
driver-class-name: org.h2.Driver
|
||||
url: jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE;MODE=MYSQL;
|
||||
username: sa
|
||||
password: password
|
||||
hikari:
|
||||
maximum-pool-size: 10
|
||||
minimum-idle: 5
|
||||
connection-timeout: 30000
|
||||
|
||||
jackson:
|
||||
time-zone: GMT+8
|
||||
date-format: yyyy-MM-dd HH:mm:ss
|
||||
|
||||
h2:
|
||||
console:
|
||||
enabled: true
|
||||
path: /h2-console
|
||||
|
||||
jpa:
|
||||
hibernate:
|
||||
ddl-auto: create-drop
|
||||
show-sql: true
|
||||
|
||||
sql:
|
||||
init:
|
||||
mode: always
|
||||
schema-locations: classpath*:schema-h2.sql
|
||||
data-locations: classpath*:data.sql
|
||||
|
||||
mybatis-plus:
|
||||
configuration:
|
||||
map-underscore-to-camel-case: true
|
||||
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
|
||||
global-config:
|
||||
db-config:
|
||||
id-type: auto
|
||||
logic-delete-field: deleted
|
||||
logic-delete-value: 1
|
||||
logic-not-delete-value: 0
|
||||
mapper-locations: classpath*:mapper/**/*.xml
|
||||
ddl-auto: create-drop
|
||||
|
||||
# JWT配置
|
||||
jwt:
|
||||
secret: petHospitalSecretKey2024GuanPengFeiGraduateDesign
|
||||
expiration: 86400000 # 24小时
|
||||
|
||||
# 文件上传配置
|
||||
file:
|
||||
upload-path: /tmp/pet-hospital/uploads/
|
||||
max-size: 10MB
|
||||
36
backend/src/main/resources/application.yml
Normal file
36
backend/src/main/resources/application.yml
Normal file
@@ -0,0 +1,36 @@
|
||||
server:
|
||||
port: 8080
|
||||
servlet:
|
||||
context-path: /api
|
||||
|
||||
spring:
|
||||
profiles:
|
||||
active: dev
|
||||
application:
|
||||
name: pet-hospital
|
||||
|
||||
jackson:
|
||||
time-zone: GMT+8
|
||||
date-format: yyyy-MM-dd HH:mm:ss
|
||||
|
||||
mybatis-plus:
|
||||
configuration:
|
||||
map-underscore-to-camel-case: true
|
||||
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
|
||||
global-config:
|
||||
db-config:
|
||||
id-type: auto
|
||||
logic-delete-field: deleted
|
||||
logic-delete-value: 1
|
||||
logic-not-delete-value: 0
|
||||
mapper-locations: classpath*:mapper/**/*.xml
|
||||
|
||||
# JWT配置
|
||||
jwt:
|
||||
secret: pet-hospital-secret-key-2024-guanpengfei-graduate-design
|
||||
expiration: 86400000 # 24小时
|
||||
|
||||
# 文件上传配置
|
||||
file:
|
||||
upload-path: /tmp/pet-hospital/uploads/
|
||||
max-size: 10MB
|
||||
17
backend/src/main/resources/data.sql
Normal file
17
backend/src/main/resources/data.sql
Normal file
@@ -0,0 +1,17 @@
|
||||
-- 插入初始管理员用户
|
||||
INSERT INTO `user` (username, password, phone, email, role, status) VALUES ('admin', '$2a$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', '13800138000', 'admin@example.com', 'ADMIN', 1);
|
||||
|
||||
-- 插入初始医生用户
|
||||
INSERT INTO `user` (username, password, phone, email, role, status) VALUES ('doctor', '$2a$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', '13700137000', 'doctor@example.com', 'DOCTOR', 1);
|
||||
|
||||
-- 插入初始顾客用户
|
||||
INSERT INTO `user` (username, password, phone, email, role, status) VALUES ('customer', '$2a$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', '13900139000', 'customer@example.com', 'CUSTOMER', 1);
|
||||
|
||||
-- 插入示例宠物
|
||||
INSERT INTO pet (name, species, breed, gender, birthday, owner_id) VALUES ('小白', '狗', '金毛', 'MALE', '2023-01-01', 3);
|
||||
|
||||
-- 插入示例医生
|
||||
INSERT INTO doctor (name, department, title, phone, email, status) VALUES ('张医生', '内科', '主治医师', '13600136000', 'zhang@hospital.com', 1);
|
||||
|
||||
-- 插入示例药品
|
||||
INSERT INTO drug (name, category, manufacturer, specification, unit_price, stock_quantity, unit, status) VALUES ('阿莫西林', '抗生素', '制药厂A', '0.25g*24粒', 25.50, 100, '盒', 1);
|
||||
242
backend/src/main/resources/schema-h2.sql
Normal file
242
backend/src/main/resources/schema-h2.sql
Normal file
@@ -0,0 +1,242 @@
|
||||
-- 如果表不存在则创建表,如果存在则添加缺失的列
|
||||
|
||||
-- 检查并创建appointment表或添加缺失列
|
||||
CREATE TABLE IF NOT EXISTS appointment (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
customer_id BIGINT NOT NULL,
|
||||
pet_id BIGINT NOT NULL,
|
||||
doctor_id BIGINT,
|
||||
department VARCHAR(50),
|
||||
appointment_date DATE,
|
||||
time_slot VARCHAR(20), -- 添加这个缺失的列
|
||||
status VARCHAR(20) DEFAULT 'PENDING',
|
||||
remark TEXT,
|
||||
cancel_time TIMESTAMP NULL,
|
||||
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
deleted INT DEFAULT 0
|
||||
);
|
||||
|
||||
-- 检查并创建visit表
|
||||
CREATE TABLE IF NOT EXISTS visit (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
appointment_id BIGINT,
|
||||
customer_id BIGINT NOT NULL,
|
||||
pet_id BIGINT NOT NULL,
|
||||
doctor_id BIGINT NOT NULL,
|
||||
symptoms TEXT,
|
||||
diagnosis TEXT,
|
||||
treatment_plan TEXT,
|
||||
status VARCHAR(20) DEFAULT 'PENDING',
|
||||
total_amount DECIMAL(10,2),
|
||||
payment_status VARCHAR(20) DEFAULT 'UNPAID',
|
||||
payment_method VARCHAR(20),
|
||||
payment_time TIMESTAMP NULL,
|
||||
start_time TIMESTAMP,
|
||||
end_time TIMESTAMP,
|
||||
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
deleted INT DEFAULT 0
|
||||
);
|
||||
|
||||
-- 检查并创建prescription表
|
||||
CREATE TABLE IF NOT EXISTS prescription (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
visit_id BIGINT,
|
||||
doctor_id BIGINT,
|
||||
customer_id BIGINT,
|
||||
total_amount DECIMAL(10,2),
|
||||
status VARCHAR(20) DEFAULT 'DRAFT',
|
||||
remark TEXT,
|
||||
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
deleted INT DEFAULT 0
|
||||
);
|
||||
|
||||
-- 检查并创建prescription_item表
|
||||
CREATE TABLE IF NOT EXISTS prescription_item (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
prescription_id BIGINT NOT NULL,
|
||||
drug_id BIGINT NOT NULL,
|
||||
quantity INT NOT NULL,
|
||||
dosage VARCHAR(100),
|
||||
frequency VARCHAR(50),
|
||||
duration VARCHAR(50),
|
||||
usage_instructions TEXT,
|
||||
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
deleted INT DEFAULT 0
|
||||
);
|
||||
|
||||
-- 检查并创建order_info表
|
||||
CREATE TABLE IF NOT EXISTS order_info (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
visit_id BIGINT,
|
||||
customer_id BIGINT NOT NULL,
|
||||
amount DECIMAL(10,2),
|
||||
status VARCHAR(20) DEFAULT 'UNPAID',
|
||||
payment_method VARCHAR(20),
|
||||
payment_time TIMESTAMP NULL,
|
||||
remark TEXT,
|
||||
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
deleted INT DEFAULT 0
|
||||
);
|
||||
|
||||
-- 检查并创建drug表
|
||||
CREATE TABLE IF NOT EXISTS drug (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
name VARCHAR(100) NOT NULL,
|
||||
category VARCHAR(50),
|
||||
manufacturer VARCHAR(100),
|
||||
specification VARCHAR(100),
|
||||
unit_price DECIMAL(10,2),
|
||||
stock_quantity INT DEFAULT 0,
|
||||
unit VARCHAR(20),
|
||||
status INT DEFAULT 1,
|
||||
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
deleted INT DEFAULT 0
|
||||
);
|
||||
|
||||
-- 检查并创建pet表
|
||||
CREATE TABLE IF NOT EXISTS pet (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
owner_id BIGINT NOT NULL,
|
||||
name VARCHAR(50) NOT NULL,
|
||||
species VARCHAR(50),
|
||||
breed VARCHAR(100),
|
||||
gender VARCHAR(10), -- 修改为VARCHAR以支持MALE/FEMALE
|
||||
birthday DATE, -- 添加birthday字段而不是age
|
||||
weight DOUBLE, -- 添加weight字段
|
||||
photo VARCHAR(255), -- 添加photo字段
|
||||
remark TEXT, -- 添加remark字段
|
||||
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
deleted INT DEFAULT 0
|
||||
);
|
||||
|
||||
-- 检查并创建doctor表
|
||||
CREATE TABLE IF NOT EXISTS doctor (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
name VARCHAR(50) NOT NULL,
|
||||
department VARCHAR(50),
|
||||
title VARCHAR(50),
|
||||
phone VARCHAR(20),
|
||||
email VARCHAR(100),
|
||||
avatar VARCHAR(255),
|
||||
status INT DEFAULT 1,
|
||||
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
deleted INT DEFAULT 0
|
||||
);
|
||||
|
||||
-- 检查并创建user表
|
||||
CREATE TABLE IF NOT EXISTS `user` (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
username VARCHAR(50) NOT NULL UNIQUE,
|
||||
phone VARCHAR(20),
|
||||
email VARCHAR(100),
|
||||
password VARCHAR(255) NOT NULL,
|
||||
role VARCHAR(20) DEFAULT 'CUSTOMER',
|
||||
status INT DEFAULT 1,
|
||||
avatar VARCHAR(255),
|
||||
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
deleted INT DEFAULT 0
|
||||
);
|
||||
|
||||
-- 检查并创建medical_record表
|
||||
CREATE TABLE IF NOT EXISTS medical_record (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
visit_id BIGINT NOT NULL,
|
||||
record_type VARCHAR(50), -- CHECKUP体检, DIAGNOSIS诊断, TREATMENT治疗
|
||||
content TEXT,
|
||||
attachment_urls TEXT,
|
||||
doctor_id BIGINT,
|
||||
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
deleted INT DEFAULT 0
|
||||
);
|
||||
|
||||
-- 检查并创建message表
|
||||
CREATE TABLE IF NOT EXISTS message (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
sender_id BIGINT,
|
||||
receiver_id BIGINT NOT NULL,
|
||||
content TEXT NOT NULL,
|
||||
type VARCHAR(20) DEFAULT 'NOTICE', -- NOTICE通知, CHAT聊天
|
||||
status VARCHAR(20) DEFAULT 'UNREAD', -- UNREAD未读, READ已读
|
||||
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
deleted INT DEFAULT 0
|
||||
);
|
||||
|
||||
-- 检查并创建notice表
|
||||
CREATE TABLE IF NOT EXISTS notice (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
title VARCHAR(200) NOT NULL,
|
||||
content TEXT NOT NULL,
|
||||
publisher_id BIGINT NOT NULL,
|
||||
publish_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
status INT DEFAULT 1,
|
||||
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
deleted INT DEFAULT 0
|
||||
);
|
||||
|
||||
-- 检查并创建report表
|
||||
CREATE TABLE IF NOT EXISTS report (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
report_type VARCHAR(50) NOT NULL, -- REVENUE收入, CUSTOMER客户, PET宠物, DRUG药品
|
||||
report_data JSON,
|
||||
period_start DATE,
|
||||
period_end DATE,
|
||||
generated_by BIGINT,
|
||||
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
deleted INT DEFAULT 0
|
||||
);
|
||||
|
||||
-- 检查并创建stock_in表
|
||||
CREATE TABLE IF NOT EXISTS stock_in (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
drug_id BIGINT NOT NULL,
|
||||
quantity INT NOT NULL,
|
||||
unit_price DECIMAL(10,2),
|
||||
supplier VARCHAR(100),
|
||||
operator_id BIGINT,
|
||||
remark TEXT,
|
||||
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
deleted INT DEFAULT 0
|
||||
);
|
||||
|
||||
-- 检查并创建stock_out表
|
||||
CREATE TABLE IF NOT EXISTS stock_out (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
drug_id BIGINT NOT NULL,
|
||||
quantity INT NOT NULL,
|
||||
unit_price DECIMAL(10,2),
|
||||
purpose VARCHAR(100), -- 用途:销售、损耗等
|
||||
operator_id BIGINT,
|
||||
remark TEXT,
|
||||
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
deleted INT DEFAULT 0
|
||||
);
|
||||
|
||||
-- 检查并创建vaccine_record表
|
||||
CREATE TABLE IF NOT EXISTS vaccine_record (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
pet_id BIGINT NOT NULL,
|
||||
vaccine_name VARCHAR(100) NOT NULL,
|
||||
dose_number INT,
|
||||
injection_date DATE,
|
||||
next_appointment_date DATE,
|
||||
doctor_id BIGINT,
|
||||
remark TEXT,
|
||||
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
deleted INT DEFAULT 0
|
||||
);
|
||||
230
backend/src/main/resources/schema.sql
Normal file
230
backend/src/main/resources/schema.sql
Normal file
@@ -0,0 +1,230 @@
|
||||
-- 用户表
|
||||
CREATE TABLE IF NOT EXISTS `user` (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
username VARCHAR(50) NOT NULL UNIQUE,
|
||||
phone VARCHAR(20),
|
||||
email VARCHAR(100),
|
||||
password VARCHAR(255) NOT NULL,
|
||||
role VARCHAR(20) DEFAULT 'CUSTOMER',
|
||||
status INT DEFAULT 1,
|
||||
avatar VARCHAR(255),
|
||||
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
deleted INT DEFAULT 0
|
||||
);
|
||||
|
||||
-- 宠物表
|
||||
CREATE TABLE IF NOT EXISTS pet (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
name VARCHAR(50) NOT NULL,
|
||||
species VARCHAR(50),
|
||||
breed VARCHAR(100),
|
||||
gender CHAR(1),
|
||||
age INT,
|
||||
owner_id BIGINT NOT NULL,
|
||||
health_status VARCHAR(100),
|
||||
vaccination_status VARCHAR(100),
|
||||
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
deleted INT DEFAULT 0
|
||||
);
|
||||
|
||||
-- 医生表
|
||||
CREATE TABLE IF NOT EXISTS doctor (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
name VARCHAR(50) NOT NULL,
|
||||
department VARCHAR(50),
|
||||
title VARCHAR(50),
|
||||
phone VARCHAR(20),
|
||||
email VARCHAR(100),
|
||||
avatar VARCHAR(255),
|
||||
status INT DEFAULT 1,
|
||||
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
deleted INT DEFAULT 0
|
||||
);
|
||||
|
||||
-- 就诊记录表
|
||||
CREATE TABLE IF NOT EXISTS visit (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
pet_id BIGINT NOT NULL,
|
||||
doctor_id BIGINT NOT NULL,
|
||||
customer_id BIGINT NOT NULL,
|
||||
symptoms TEXT,
|
||||
diagnosis TEXT,
|
||||
treatment_plan TEXT,
|
||||
visit_date DATE,
|
||||
status VARCHAR(20) DEFAULT 'PENDING',
|
||||
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
deleted INT DEFAULT 0
|
||||
);
|
||||
|
||||
-- 处方表
|
||||
CREATE TABLE IF NOT EXISTS prescription (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
visit_id BIGINT NOT NULL,
|
||||
doctor_id BIGINT NOT NULL,
|
||||
customer_id BIGINT NOT NULL,
|
||||
total_amount DECIMAL(10,2),
|
||||
status VARCHAR(20) DEFAULT 'ACTIVE',
|
||||
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
deleted INT DEFAULT 0
|
||||
);
|
||||
|
||||
-- 处方明细表
|
||||
CREATE TABLE IF NOT EXISTS prescription_item (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
prescription_id BIGINT NOT NULL,
|
||||
drug_id BIGINT NOT NULL,
|
||||
quantity INT NOT NULL,
|
||||
dosage VARCHAR(100),
|
||||
frequency VARCHAR(50),
|
||||
duration VARCHAR(50),
|
||||
usage_instructions TEXT,
|
||||
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
deleted INT DEFAULT 0
|
||||
);
|
||||
|
||||
-- 药品表
|
||||
CREATE TABLE IF NOT EXISTS drug (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
name VARCHAR(100) NOT NULL,
|
||||
category VARCHAR(50),
|
||||
manufacturer VARCHAR(100),
|
||||
specification VARCHAR(100),
|
||||
unit_price DECIMAL(10,2),
|
||||
stock_quantity INT DEFAULT 0,
|
||||
unit VARCHAR(20),
|
||||
status INT DEFAULT 1,
|
||||
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
deleted INT DEFAULT 0
|
||||
);
|
||||
|
||||
-- 订单表
|
||||
CREATE TABLE IF NOT EXISTS order_info (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
visit_id BIGINT,
|
||||
customer_id BIGINT NOT NULL,
|
||||
amount DECIMAL(10,2),
|
||||
status VARCHAR(20) DEFAULT 'UNPAID',
|
||||
payment_method VARCHAR(20),
|
||||
payment_time TIMESTAMP NULL,
|
||||
remark TEXT,
|
||||
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
deleted INT DEFAULT 0
|
||||
);
|
||||
|
||||
-- 预约表
|
||||
CREATE TABLE IF NOT EXISTS appointment (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
pet_id BIGINT NOT NULL,
|
||||
doctor_id BIGINT NOT NULL,
|
||||
customer_id BIGINT NOT NULL,
|
||||
appointment_date DATE NOT NULL,
|
||||
appointment_time TIME NOT NULL,
|
||||
reason TEXT,
|
||||
status VARCHAR(20) DEFAULT 'PENDING',
|
||||
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
deleted INT DEFAULT 0
|
||||
);
|
||||
|
||||
-- 疫苗接种记录表
|
||||
CREATE TABLE IF NOT EXISTS vaccine_record (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
pet_id BIGINT NOT NULL,
|
||||
vaccine_name VARCHAR(100) NOT NULL,
|
||||
dose_number INT,
|
||||
injection_date DATE,
|
||||
next_appointment_date DATE,
|
||||
doctor_id BIGINT,
|
||||
remark TEXT,
|
||||
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
deleted INT DEFAULT 0
|
||||
);
|
||||
|
||||
-- 库存入库表
|
||||
CREATE TABLE IF NOT EXISTS stock_in (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
drug_id BIGINT NOT NULL,
|
||||
quantity INT NOT NULL,
|
||||
unit_price DECIMAL(10,2),
|
||||
supplier VARCHAR(100),
|
||||
operator_id BIGINT,
|
||||
remark TEXT,
|
||||
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
deleted INT DEFAULT 0
|
||||
);
|
||||
|
||||
-- 库存出库表
|
||||
CREATE TABLE IF NOT EXISTS stock_out (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
drug_id BIGINT NOT NULL,
|
||||
quantity INT NOT NULL,
|
||||
unit_price DECIMAL(10,2),
|
||||
purpose VARCHAR(100), -- 用途:销售、损耗等
|
||||
operator_id BIGINT,
|
||||
remark TEXT,
|
||||
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
deleted INT DEFAULT 0
|
||||
);
|
||||
|
||||
-- 消息表
|
||||
CREATE TABLE IF NOT EXISTS message (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
sender_id BIGINT,
|
||||
receiver_id BIGINT NOT NULL,
|
||||
content TEXT NOT NULL,
|
||||
type VARCHAR(20) DEFAULT 'NOTICE', -- NOTICE通知, CHAT聊天
|
||||
status VARCHAR(20) DEFAULT 'UNREAD', -- UNREAD未读, READ已读
|
||||
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
deleted INT DEFAULT 0
|
||||
);
|
||||
|
||||
-- 公告表
|
||||
CREATE TABLE IF NOT EXISTS notice (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
title VARCHAR(200) NOT NULL,
|
||||
content TEXT NOT NULL,
|
||||
publisher_id BIGINT NOT NULL,
|
||||
publish_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
status INT DEFAULT 1,
|
||||
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
deleted INT DEFAULT 0
|
||||
);
|
||||
|
||||
-- 医疗记录表
|
||||
CREATE TABLE IF NOT EXISTS medical_record (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
visit_id BIGINT NOT NULL,
|
||||
record_type VARCHAR(50), -- CHECKUP体检, DIAGNOSIS诊断, TREATMENT治疗
|
||||
content TEXT,
|
||||
attachment_urls TEXT,
|
||||
doctor_id BIGINT,
|
||||
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
deleted INT DEFAULT 0
|
||||
);
|
||||
|
||||
-- 报表统计表
|
||||
CREATE TABLE IF NOT EXISTS report (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
report_type VARCHAR(50) NOT NULL, -- REVENUE收入, CUSTOMER客户, PET宠物, DRUG药品
|
||||
report_data JSON,
|
||||
period_start DATE,
|
||||
period_end DATE,
|
||||
generated_by BIGINT,
|
||||
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
deleted INT DEFAULT 0
|
||||
);
|
||||
Reference in New Issue
Block a user