后端代码主体

This commit is contained in:
BLRTTX 2024-12-17 22:05:03 +08:00
commit d81742c873
169 changed files with 5394 additions and 0 deletions

33
.gitignore vendored Normal file
View File

@ -0,0 +1,33 @@
HELP.md
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
!**/src/main/**/build/
!**/src/test/**/build/
### VS Code ###
.vscode/

38
common/.gitignore vendored Normal file
View File

@ -0,0 +1,38 @@
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/
### IntelliJ IDEA ###
.idea/modules.xml
.idea/jarRepositories.xml
.idea/compiler.xml
.idea/libraries/
*.iws
*.iml
*.ipr
### Eclipse ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
!**/src/main/**/build/
!**/src/test/**/build/
### VS Code ###
.vscode/
### Mac OS ###
.DS_Store

104
common/pom.xml Normal file
View File

@ -0,0 +1,104 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.atjy</groupId>
<artifactId>hassle_free</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>common</artifactId>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!--mybatis-plus-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-spring-boot3-starter</artifactId>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>com.github.whvcse</groupId>
<artifactId>easy-captcha</artifactId>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>dysmsapi20170525</artifactId>
</dependency>
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,9 @@
package com.atjy.common.constant;
public class RedisConstant {
public static final String ADMIN_LOGIN_PREFIX = "admin:login:";
public static final Integer ADMIN_LOGIN_CAPTCHA_TTL_SEC = 60;
public static final String APP_LOGIN_PREFIX = "app:login:";
public static final Integer APP_LOGIN_CODE_RESEND_TIME_SEC = 60;
public static final Integer APP_LOGIN_CODE_TTL_SEC = 60;
}

View File

@ -0,0 +1,15 @@
package com.atjy.common.exception;
import com.atjy.common.result.ResultCodeEnum;
import lombok.Data;
@Data
public class HassleFreeException extends RuntimeException {
private Integer status;
public HassleFreeException(ResultCodeEnum resultCodeEnum) {
super(resultCodeEnum.getMessage());
this.status = resultCodeEnum.getStatus();
}
}

View File

@ -0,0 +1,12 @@
package com.atjy.common.login;
import lombok.AllArgsConstructor;
import lombok.Data;
@Data
@AllArgsConstructor
public class LoginUser {
private Long userId;
private String username;
}

View File

@ -0,0 +1,17 @@
package com.atjy.common.login;
public class LoginUserHolder {
public static ThreadLocal<LoginUser> threadLocal = new ThreadLocal<>();
public static void setLoginUser(LoginUser loginUser) {
threadLocal.set(loginUser);
}
public static LoginUser getLoginUser() {
return threadLocal.get();
}
public static void clear() {
threadLocal.remove();
}
}

View File

@ -0,0 +1,17 @@
package com.atjy.common.minio;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
@Data
@ConfigurationProperties(prefix = "minio")
public class MinioProperties {
private String endpoint;
private String accessKey;
private String secretKey;
private String bucketName;
}

View File

@ -0,0 +1,20 @@
package com.atjy.common.redis;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializer;
@Configuration
public class RedisConfiguration {
@Bean
public RedisTemplate<String, Object> stringObjectRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
template.setKeySerializer(RedisSerializer.string());
template.setValueSerializer(RedisSerializer.java());
return template;
}
}

View File

@ -0,0 +1,56 @@
package com.atjy.common.result;
import lombok.Data;
/**
* 全局统一返回结果类
*/
@Data
public class Result<T> {
//返回码
private Integer status;
//返回消息
private String message;
//返回数据
private T data;
public Result() {
}
private static <T> Result<T> build(T data) {
Result<T> result = new Result<>();
if (data != null)
result.setData(data);
return result;
}
public static <T> Result<T> build(T body, ResultCodeEnum resultCodeEnum) {
Result<T> result = build(body);
result.setStatus(resultCodeEnum.getStatus());
result.setMessage(resultCodeEnum.getMessage());
return result;
}
public static <T> Result<T> ok(T data) {
return build(data, ResultCodeEnum.SUCCESS);
}
public static <T> Result<T> ok() {
return Result.ok(null);
}
public static <T> Result<T> fail() {
return build(null, ResultCodeEnum.FAIL);
}
public static <T> Result<T> fail(Integer status, String message) {
Result<T> result = build(null);
result.setStatus(status);
result.setMessage(message);
return result;
}
}

View File

@ -0,0 +1,51 @@
package com.atjy.common.result;
import lombok.Getter;
@Getter
public enum ResultCodeEnum {
SUCCESS(200, "成功"),
FAIL(201, "失败"),
PARAM_ERROR(202, "参数不正确"),
SERVICE_ERROR(203, "服务异常"),
DATA_ERROR(204, "数据异常"),
ILLEGAL_REQUEST(205, "非法请求"),
REPEAT_SUBMIT(206, "重复提交"),
DELETE_ERROR(207, "请先删除子集"),
ADMIN_ACCOUNT_EXIST_ERROR(301, "账号已存在"),
ADMIN_CAPTCHA_CODE_ERROR(302, "验证码错误"),
ADMIN_CAPTCHA_CODE_EXPIRED(303, "验证码已过期"),
ADMIN_CAPTCHA_CODE_NOT_FOUND(304, "未输入验证码"),
ADMIN_LOGIN_AUTH(305, "未登陆"),
ADMIN_ACCOUNT_NOT_EXIST_ERROR(306, "账号不存在"),
ADMIN_ACCOUNT_ERROR(307, "用户名或密码错误"),
ADMIN_ACCOUNT_DISABLED_ERROR(308, "该用户已被禁用"),
ADMIN_ACCESS_FORBIDDEN(309, "无访问权限"),
APP_LOGIN_AUTH(501, "未登陆"),
APP_LOGIN_PHONE_EMPTY(502, "手机号码为空"),
APP_LOGIN_CODE_EMPTY(503, "验证码为空"),
APP_SEND_SMS_TOO_OFTEN(504, "验证法发送过于频繁"),
APP_LOGIN_CODE_EXPIRED(505, "验证码已过期"),
APP_LOGIN_CODE_ERROR(506, "验证码错误"),
APP_ACCOUNT_DISABLED_ERROR(507, "该用户已被禁用"),
TOKEN_EXPIRED(601, "token过期"),
TOKEN_INVALID(602, "token非法");
private final Integer status;
private final String message;
ResultCodeEnum(Integer status, String message) {
this.status = status;
this.message = message;
}
}

View File

@ -0,0 +1,14 @@
package com.atjy.common.utils;
import java.util.*;
public class CodeUtil {
public static String getRandomCode(int length) {
StringBuilder builder = new StringBuilder();
Random random = new Random();
for (int i = 0; i < length; i++) {
builder.append(random.nextInt(10));
}
return builder.toString();
}
}

View File

@ -0,0 +1,48 @@
package com.atjy.common.utils;
import com.atjy.common.exception.HassleFreeException;
import com.atjy.common.result.ResultCodeEnum;
import io.jsonwebtoken.*;
import io.jsonwebtoken.security.Keys;
import javax.crypto.SecretKey;
import java.util.Date;
public class JwtUtil {
private static long tokenExpiration = 60 * 60 * 1000L;
private static SecretKey secretKey = Keys.hmacShaKeyFor("Zv95JuIHKadVbSJBqqTbrnAZxXf4ixVZ".getBytes());
public static String createToken(Long userId, String username) {
String jwt = Jwts.builder()
.setExpiration(new Date(System.currentTimeMillis() + tokenExpiration))
.setSubject("LOGIN_USER")
.claim("userId", userId)
.claim("username", username)
.signWith(secretKey, SignatureAlgorithm.HS256)
.compact();
return jwt;
}
public static Claims parseToken(String token) {
if (token == null) {
throw new HassleFreeException(ResultCodeEnum.ADMIN_LOGIN_AUTH);
}
try {
JwtParser jwtParser = Jwts.parserBuilder().setSigningKey(secretKey).build();
return jwtParser.parseClaimsJws(token).getBody();
} catch (ExpiredJwtException e) {
throw new HassleFreeException(ResultCodeEnum.TOKEN_EXPIRED);
} catch (JwtException e) {
throw new HassleFreeException(ResultCodeEnum.TOKEN_INVALID);
}
}
public static void main(String[] args) {
System.out.println(createToken(8L, "15674675667"));
}
}

38
model/.gitignore vendored Normal file
View File

@ -0,0 +1,38 @@
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/
### IntelliJ IDEA ###
.idea/modules.xml
.idea/jarRepositories.xml
.idea/compiler.xml
.idea/libraries/
*.iws
*.iml
*.ipr
### Eclipse ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
!**/src/main/**/build/
!**/src/test/**/build/
### VS Code ###
.vscode/
### Mac OS ###
.DS_Store

34
model/pom.xml Normal file
View File

@ -0,0 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.atjy</groupId>
<artifactId>hassle_free</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>model</artifactId>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!--mybatis-plus-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-spring-boot3-starter</artifactId>
</dependency>
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,18 @@
package com.atjy.model.entity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Data
@Schema(description = "预约信息")
@TableName(value = "appointment_info")
public class AppointmentInfo extends BaseEntity {
private static final long serialVersionUID = 1L;
@Schema(description = "预约日期")
@TableField(value = "appointment_date")
private String appointmentDate;
}

View File

@ -0,0 +1,48 @@
package com.atjy.model.entity;
import com.atjy.model.enums.ArticleItemType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonIgnore;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.util.Date;
@Data
@Schema(description = "医说信息")
@TableName(value = "article_info")
public class ArticleInfo extends BaseEntity {
private static final long serialVersionUID = 1L;
@Schema(description = "大标题")
@TableField(value = "title_big")
private String titleBig;
@Schema(description = "小标题")
@TableField(value = "title_small")
private String titleSmall;
@Schema(description = "阅读量")
@TableField(value = "number")
private Integer number;
@Schema(description = "发布时间")
@TableField(value = "publish_time")
@JsonIgnore
private Date publishTime;
@Schema(description = "医生id")
@TableField(value = "doctor_id")
private Long doctorId;
@Schema(description = "内容")
@TableField(value = "content")
private String content;
@Schema(description = "医说所属类型")
@TableField(value = "type")
private ArticleItemType type;
}

View File

@ -0,0 +1,38 @@
package com.atjy.model.entity;
import com.baomidou.mybatisplus.annotation.*;
import com.fasterxml.jackson.annotation.JsonIgnore;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.time.LocalDateTime;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class BaseEntity implements Serializable {
@Schema(description = "主键")
@TableId(value = "id", type = IdType.AUTO)
private Long id;
@Schema(description = "创建时间")
@TableField(value = "create_time", fill = FieldFill.INSERT)
@JsonIgnore
private LocalDateTime createTime;
@Schema(description = "更新时间")
@TableField(value = "update_time", fill = FieldFill.UPDATE)
@JsonIgnore
private LocalDateTime updateTime;
@Schema(description = "逻辑删除")
@TableField("is_deleted")
@TableLogic
@JsonIgnore
private Byte isDeleted;
}

View File

@ -0,0 +1,23 @@
package com.atjy.model.entity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Schema(description = "城市信息")
@TableName(value = "city_info")
@Data
public class CityInfo extends BaseEntity {
private static final long serialVersionUID = 1L;
@Schema(description = "城市名称")
@TableField(value = "name")
private String name;
@Schema(description = "所属省份id")
@TableField(value = "province_id")
private Integer provinceId;
}

View File

@ -0,0 +1,29 @@
package com.atjy.model.entity;
import com.baomidou.mybatisplus.annotation.*;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Data
@Schema(description = "咨询信息")
@TableName(value = "consultation_info")
public class ConsultInfo extends BaseEntity {
private static final long serialVersionUID = 1L;
@Schema(description = "用户id")
@TableField(value = "user_id")
private Long userId;
@Schema(description = "问题")
@TableField(value = "problem")
private String problem;
@Schema(description = "解答")
@TableField(value = "answer")
private String answer;
@Schema(description = "编号")
@TableField(value = "number")
private Integer number;
}

View File

@ -0,0 +1,22 @@
package com.atjy.model.entity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Schema(description = "科室信息")
@TableName(value = "department_info")
@Data
public class DepartmentInfo extends BaseEntity {
private static final long serialVersionUID = 1L;
@Schema(description = "科室名称")
@TableField(value = "name")
private String name;
@Schema(description = "所属科室")
@TableField(value = "belong")
private String belong;
}

View File

@ -0,0 +1,23 @@
package com.atjy.model.entity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Schema(description = "地区信息")
@TableName(value = "district_info")
@Data
public class DistrictInfo extends BaseEntity {
private static final long serialVersionUID = 1L;
@Schema(description = "区域名称")
@TableField(value = "name")
private String name;
@Schema(description = "所属城市id")
@TableField(value = "city_id")
private Integer cityId;
}

View File

@ -0,0 +1,26 @@
package com.atjy.model.entity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Data
@Schema(description = "医生-预约信息")
@TableName(value = "doctor_appointment")
public class DoctorAppointment extends BaseEntity{
private static final long serialVersionUID = 1L;
@Schema(description = "医生id")
@TableField(value = "doctor_id")
private Long doctorId;
@Schema(description = "预约时间id")
@TableField(value = "appointment_id")
private Long appointmentId;
@Schema(description = "费用")
@TableField(value = "fees")
private Long fees;
}

View File

@ -0,0 +1,47 @@
package com.atjy.model.entity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Schema(description = "医生信息")
@TableName(value = "doctor_info")
@Data
public class DoctorInfo extends BaseEntity {
private static final long serialVersionUID = 1L;
@Schema(description = "医生姓名")
@TableField(value = "doctor_name")
private String doctorName;
@Schema(description = "医院id")
@TableField(value = "hospital_id")
private Long hospitalId;
@Schema(description = "级别")
@TableField(value = "level")
private String level;
@Schema(description = "擅长领域")
@TableField(value = "expertise")
private String expertise;
@Schema(description = "头衔")
@TableField(value = "source")
private String source;
@Schema(description = "预约量")
@TableField(value = "appointment_number")
private Integer appointmentNumber;
@Schema(description = "科室id")
@TableField(value = "department_id")
private String departmentId;
@Schema(description = "简介")
@TableField(value = "briefly")
private String briefly;
}

View File

@ -0,0 +1,32 @@
package com.atjy.model.entity;
import com.atjy.model.enums.GraphItemType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Schema(description = "图片信息表")
@TableName(value = "graph_info")
@Data
public class GraphInfo extends BaseEntity {
private static final long serialVersionUID = 1L;
@Schema(description = "图片名称")
@TableField(value = "name")
private String name;
@Schema(description = "图片所属对象类型")
@TableField(value = "item_type")
private GraphItemType itemType;
@Schema(description = "图片所属对象id")
@TableField(value = "item_id")
private Long itemId;
@Schema(description = "图片地址")
@TableField(value = "url")
private String url;
}

View File

@ -0,0 +1,22 @@
package com.atjy.model.entity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Schema(description = "医院-科室信息")
@TableName(value = "hospital_department")
@Data
public class HospitalDepartment extends BaseEntity{
private static final long serialVersionUID = 1L;
@Schema(description = "医院id")
@TableField(value = "hospital_id")
private Long hospitalId;
@Schema(description = "科室id")
@TableField(value = "department_id")
private Long departmentId;
}

View File

@ -0,0 +1,62 @@
package com.atjy.model.entity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Schema(description = "医院信息")
@TableName(value = "hospital_info")
@Data
public class HospitalInfo extends BaseEntity{
private static final long serialVersionUID = 1L;
@Schema(description = "医院名称")
@TableField(value = "hospital_name")
private String hospitalName;
@Schema(description = "所处区域id")
@TableField(value = "district_id")
private Long districtId;
@Schema(description = "所处区域名称")
@TableField(value = "district_name")
private String districtName;
@Schema(description = "所处城市id")
@TableField(value = "city_id")
private Long cityId;
@Schema(description = "所处城市名称")
@TableField(value = "city_name")
private String cityName;
@Schema(description = "所处省份id")
@TableField(value = "province_id")
private Long provinceId;
@Schema(description = "所处省份名称")
@TableField(value = "province_name")
private String provinceName;
@Schema(description = "地址")
@TableField(value = "address")
private String address;
@Schema(description = "介绍")
@TableField(value = "introduction")
private String introduction;
@Schema(description = "预约量")
@TableField(value = "appointment_number")
private Long appointmentNumber;
@Schema(description = "预约电话")
@TableField(value = "phone")
private String phone;
@Schema(description = "等级")
@TableField(value = "level")
private String level;
}

View File

@ -0,0 +1,22 @@
package com.atjy.model.entity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Schema(description = "医院-标签信息")
@TableName(value = "hospital_label")
@Data
public class HospitalLabel extends BaseEntity{
private static final long serialVersionUID = 1L;
@Schema(description = "标签名称")
@TableField(value = "label_name")
private String labelName;
@Schema(description = "医院id")
@TableField(value = "hospital_id")
private Long hospitalId;
}

View File

@ -0,0 +1,18 @@
package com.atjy.model.entity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Schema(description = "省份信息")
@TableName(value = "province_info")
@Data
public class ProvinceInfo extends BaseEntity {
private static final long serialVersionUID = 1L;
@Schema(description = "省份名称")
@TableField(value = "name")
private String name;
}

View File

@ -0,0 +1,44 @@
package com.atjy.model.entity;
import com.atjy.model.enums.BaseStatus;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Schema(description = "管理员信息")
@TableName(value = "system_user")
@Data
public class SystemUser extends BaseEntity {
private static final long serialVersionUID = 1L;
@Schema(description = "用户名")
@TableField(value = "username")
private String username;
@Schema(description = "密码")
@TableField(value = "password", select = false)
private String password;
@Schema(description = "姓名")
@TableField(value = "name")
private String name;
@Schema(description = "手机号码")
@TableField(value = "phone")
private String phone;
@Schema(description = "头像地址")
@TableField(value = "avatar_url")
private String avatarUrl;
@Schema(description = "备注信息")
@TableField(value = "additional_info")
private String additionalInfo;
@Schema(description = "账号状态")
@TableField(value = "state")
private BaseStatus state;
}

View File

@ -0,0 +1,46 @@
package com.atjy.model.entity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Data
@Schema(description = "用户-预约信息")
@TableName(value = "user_appointment")
public class UserAppointment extends BaseEntity {
private static final long serialVersionUID = 1L;
@Schema(description = "用户id")
@TableField(value = "user_id")
private Long userId;
@Schema(description = "预约时间id")
@TableField(value = "appointment_id")
private Long appointmentId;
@Schema(description = "状态")
@TableField(value = "state")
private Byte state;
@Schema(description = "医生id")
@TableField(value = "doctor_id")
private Long doctorId;
@Schema(description = "费用")
@TableField(value = "fees")
private Long fees;
@Schema(description = "就诊人姓名")
@TableField(value = "name")
private String name;
@Schema(description = "就诊人手机号")
@TableField(value = "phone")
private String phone;
@Schema(description = "备注")
@TableField(value = "memo")
private String memo;
}

View File

@ -0,0 +1,26 @@
package com.atjy.model.entity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Schema(description = "用户-收藏信息")
@TableName(value = "user_collection")
@Data
public class UserCollection extends BaseEntity {
private static final long serialVersionUID = 1L;
@Schema(description = "用户id")
@TableField(value = "user_id")
private Long userId;
@Schema(description = "收藏id")
@TableField(value = "collection_id")
private Long collectionId;
@Schema(description = "类型")
@TableField(value = "type")
private Byte type;
}

View File

@ -0,0 +1,39 @@
package com.atjy.model.entity;
import com.atjy.model.enums.BaseStatus;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Schema(description = "用户信息")
@TableName(value = "user_info")
@Data
public class UserInfo extends BaseEntity {
private static final long serialVersionUID = 1L;
@Schema(description = "手机号码(用做登录用户名)")
@TableField(value = "phone")
private String phone;
@Schema(description = "密码")
@TableField(value = "password", select = false)
private String password;
@Schema(description = "头像id")
@TableField(value = "avatar_id")
private Long avatarId;
@Schema(description = "昵称")
@TableField(value = "nickname")
private String nickname;
@Schema(description = "账号状态")
@TableField(value = "state")
private BaseStatus state;
@Schema(description = "咨询数量")
@TableField(value = "consultation_number")
private Integer consultationNumber;
}

View File

@ -0,0 +1,33 @@
package com.atjy.model.enums;
import com.baomidou.mybatisplus.annotation.EnumValue;
import com.fasterxml.jackson.annotation.JsonValue;
public enum ArticleItemType implements BaseEnum {
USER(1, "抗疫专区"),
DOCTOR(2, "健康养生"),
HOSPITAL(3, "医疗动态");
@EnumValue
@JsonValue
private Integer code;
private String name;
@Override
public Integer getCode() {
return this.code;
}
@Override
public String getName() {
return name;
}
ArticleItemType(Integer code, String name) {
this.code = code;
this.name = name;
}
}

View File

@ -0,0 +1,8 @@
package com.atjy.model.enums;
public interface BaseEnum {
Integer getCode();
String getName();
}

View File

@ -0,0 +1,34 @@
package com.atjy.model.enums;
import com.baomidou.mybatisplus.annotation.EnumValue;
import com.fasterxml.jackson.annotation.JsonValue;
public enum BaseStatus implements BaseEnum {
ENABLE(1, "正常"),
DISABLE(0, "禁用");
@EnumValue
@JsonValue
private Integer code;
private String name;
BaseStatus(Integer code, String name) {
this.code = code;
this.name = name;
}
@Override
public Integer getCode() {
return this.code;
}
@Override
public String getName() {
return this.name;
}
}

View File

@ -0,0 +1,35 @@
package com.atjy.model.enums;
import com.baomidou.mybatisplus.annotation.EnumValue;
import com.fasterxml.jackson.annotation.JsonValue;
public enum GraphItemType implements BaseEnum {
USER(1, "用户"),
HOSPITAL(2, "医院"),
DOCTOR(3, "医生"),
ARTICLE(4, "医说");
@EnumValue
@JsonValue
private Integer code;
private String name;
@Override
public Integer getCode() {
return this.code;
}
@Override
public String getName() {
return name;
}
GraphItemType(Integer code, String name) {
this.code = code;
this.name = name;
}
}

135
pom.xml Normal file
View File

@ -0,0 +1,135 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.atjy</groupId>
<artifactId>hassle_free</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
<name>hassle_free</name>
<description>hassle_free</description>
<url/>
<licenses>
<license/>
</licenses>
<developers>
<developer/>
</developers>
<modules>
<module>model</module>
<module>web</module>
<module>common</module>
</modules>
<scm>
<connection/>
<developerConnection/>
<tag/>
<url/>
</scm>
<!-- 继承Spring Boot父项目 -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.3</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<swagger.version>2.9.2</swagger.version>
<junit.jupiter.version>5.10.2</junit.jupiter.version>
<mybatis-plus.version>3.5.7</mybatis-plus.version>
<jwt.version>0.11.2</jwt.version>
<easycaptcha.version>1.6.2</easycaptcha.version>
<minio.version>8.3.4</minio.version>
<knife4j.version>4.1.0</knife4j.version>
<aliyun.sms.version>2.0.23</aliyun.sms.version>
<dashscope-sdk.version>2.13.0</dashscope-sdk.version>
</properties>
<dependencyManagement>
<dependencies>
<!-- junit.jupiter-->
<!-- 官方文档https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-api -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>${junit.jupiter.version}</version>
</dependency>
<!--mybatis-plus-->
<!--官方文档https://baomidou.com/pages/bab2db/ -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-spring-boot3-starter</artifactId>
<version>${mybatis-plus.version}</version>
</dependency>
<!--knife4j文档-->
<!--官方文档https://doc.xiaominfo.com/docs/quick-start -->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId>
<version>${knife4j.version}</version>
</dependency>
<!--JWT登录认证相关-->
<!--官方文档https://github.com/jwtk/jjwt#install-jdk-maven -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>${jwt.version}</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<scope>runtime</scope>
<version>${jwt.version}</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<scope>runtime</scope>
<version>${jwt.version}</version>
</dependency>
<!--图形验证码-->
<!--官方文档https://gitee.com/ele-admin/EasyCaptcha -->
<dependency>
<groupId>com.github.whvcse</groupId>
<artifactId>easy-captcha</artifactId>
<version>${easycaptcha.version}</version>
</dependency>
<!--阿里云短信客户端,用于发送短信验证码-->
<!-- https://mvnrepository.com/artifact/com.aliyun/dysmsapi20170525 -->
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>dysmsapi20170525</artifactId>
<version>${aliyun.sms.version}</version>
</dependency>
<!--对象存储,用于存储图像等非结构化数据-->
<!--官方文档https://min.io/docs/minio/linux/developers/minio-drivers.html?ref=docs#java-sdk -->
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
<version>${minio.version}</version>
</dependency>
<!-- 通译千问-->
<!-- https://mvnrepository.com/artifact/com.alibaba/dashscope-sdk-java -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dashscope-sdk-java</artifactId>
<version>${dashscope-sdk.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>

38
web/.gitignore vendored Normal file
View File

@ -0,0 +1,38 @@
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/
### IntelliJ IDEA ###
.idea/modules.xml
.idea/jarRepositories.xml
.idea/compiler.xml
.idea/libraries/
*.iws
*.iml
*.ipr
### Eclipse ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
!**/src/main/**/build/
!**/src/test/**/build/
### VS Code ###
.vscode/
### Mac OS ###
.DS_Store

70
web/pom.xml Normal file
View File

@ -0,0 +1,70 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.atjy</groupId>
<artifactId>hassle_free</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>web</artifactId>
<packaging>pom</packaging>
<modules>
<module>web-admin</module>
<module>web-app</module>
</modules>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>com.atjy</groupId>
<artifactId>model</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.atjy</groupId>
<artifactId>common</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

38
web/web-admin/.gitignore vendored Normal file
View File

@ -0,0 +1,38 @@
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/
### IntelliJ IDEA ###
.idea/modules.xml
.idea/jarRepositories.xml
.idea/compiler.xml
.idea/libraries/
*.iws
*.iml
*.ipr
### Eclipse ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
!**/src/main/**/build/
!**/src/test/**/build/
### VS Code ###
.vscode/
### Mac OS ###
.DS_Store

21
web/web-admin/pom.xml Normal file
View File

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.atjy</groupId>
<artifactId>web</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>web-admin</artifactId>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
</project>

View File

@ -0,0 +1,16 @@
package com.atjy.web.admin;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;
@MapperScan("com.atjy.web.admin.mapper")
@SpringBootApplication
@EnableScheduling
public class WebAdminApplication {
public static void main(String[] args) {
SpringApplication.run(WebAdminApplication.class, args);
}
}

View File

@ -0,0 +1,33 @@
package com.atjy.web.admin.controller.graph;
import com.atjy.common.result.Result;
import com.atjy.web.admin.service.FileService;
import io.minio.errors.*;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
@Tag(name = "图片管理")
@RequestMapping("/admin/graph")
@RestController
public class GraphController {
@Autowired
private FileService service;
@Operation(summary = "上传文件")
@PostMapping("upload")
public Result<String> upload(@RequestParam MultipartFile file) throws ServerException, InsufficientDataException, ErrorResponseException, IOException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
String url = service.upload(file);
return Result.ok(url);
}
}

View File

@ -0,0 +1,44 @@
package com.atjy.web.admin.controller.login;
import com.atjy.common.login.LoginUserHolder;
import com.atjy.common.result.Result;
import com.atjy.common.utils.JwtUtil;
import com.atjy.web.admin.service.LoginService;
import com.atjy.web.admin.vo.login.CaptchaVo;
import com.atjy.web.admin.vo.login.LoginVo;
import com.atjy.web.admin.vo.system.user.SystemUserInfoVo;
import io.jsonwebtoken.Claims;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
@Tag(name = "登录管理")
@RestController
@RequestMapping("/admin")
public class LoginController {
@Autowired
private LoginService service;
@Operation(summary = "登录")
@PostMapping("login")
public Result<String> login(@RequestBody LoginVo loginVo) {
return service.login(loginVo);
}
@Operation(summary = "获取图形验证码")
@GetMapping("login/captcha")
public Result<CaptchaVo> getCaptcha() {
CaptchaVo captcha = service.getCaptcha();
return Result.ok(captcha);
}
@Operation(summary = "获取登陆用户个人信息")
@GetMapping("info")
public Result<SystemUserInfoVo> info() {
SystemUserInfoVo userInfo = service.getLoginUserInfo(LoginUserHolder.getLoginUser().getUserId());
return Result.ok(userInfo);
}
}

View File

@ -0,0 +1,47 @@
package com.atjy.web.admin.custom.config;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.info.License;
import org.springdoc.core.models.GroupedOpenApi;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class Knife4jConfiguration {
@Bean
public OpenAPI customOpenAPI() {
return new OpenAPI()
.info(new Info()
.title("医路无忧后端管理系统API")
.version("1.0")
.description("后端管理系统接口")
.termsOfService("http://doc.xiaominfo.com")
.license(new License().name("Apache 2.0")
.url("http://doc.xiaominfo.com")));
}
@Bean
public GroupedOpenApi loginAPI() {
return GroupedOpenApi.builder().group("登录信息").
pathsToMatch(
"/admin/login/**",
"/admin/info"
).
build();
}
@Bean
public GroupedOpenApi graphAPI() {
return GroupedOpenApi.builder().group("图片管理").
pathsToMatch(
"/admin/graph/**"
).
build();
}
}

View File

@ -0,0 +1,26 @@
package com.atjy.web.admin.custom.config;
import com.atjy.common.minio.MinioProperties;
import io.minio.MinioClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
@EnableConfigurationProperties(MinioProperties.class)
@ConditionalOnProperty(name = "minio.endpoint")
public class MinioConfiguration {
@Autowired
private MinioProperties properties;
@Bean
public MinioClient minioClient(){
return MinioClient.builder()
.endpoint(properties.getEndpoint())
.credentials(properties.getAccessKey(),properties.getSecretKey())
.build();
}
}

View File

@ -0,0 +1,32 @@
package com.atjy.web.admin.custom.config;
import com.atjy.web.admin.custom.converter.StringToBaseEnumConverterFactory;
import com.atjy.web.admin.custom.interceptor.AuthenticationInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.format.FormatterRegistry;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebMvcConfiguration implements WebMvcConfigurer {
@Autowired
private StringToBaseEnumConverterFactory stringToBaseEnumConverterFactory;
@Autowired
private AuthenticationInterceptor authenticationInterceptor;
@Override
public void addFormatters(FormatterRegistry registry) {
registry.addConverterFactory(this.stringToBaseEnumConverterFactory);
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(this.authenticationInterceptor)
.addPathPatterns("/admin/**")
.excludePathPatterns("/admin/login/**");
}
}

View File

@ -0,0 +1,25 @@
package com.atjy.web.admin.custom.converter;
import com.atjy.model.enums.BaseEnum;
import org.springframework.core.convert.converter.Converter;
import org.springframework.core.convert.converter.ConverterFactory;
import org.springframework.stereotype.Component;
@Component
public class StringToBaseEnumConverterFactory implements ConverterFactory<String, BaseEnum> {
@Override
public <T extends BaseEnum> Converter<String, T> getConverter(Class<T> targetType) {
return new Converter<String, T>() {
@Override
public T convert(String code) {
T[] enumConstants = targetType.getEnumConstants();
for (T enumConstant : enumConstants) {
if (enumConstant.getCode().equals(Integer.valueOf(code))) {
return enumConstant;
}
}
throw new IllegalArgumentException("code" + code + "非法");
}
};
}
}

View File

@ -0,0 +1,33 @@
package com.atjy.web.admin.custom.interceptor;
import com.atjy.common.login.LoginUser;
import com.atjy.common.login.LoginUserHolder;
import com.atjy.common.utils.JwtUtil;
import io.jsonwebtoken.Claims;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
@Component
public class AuthenticationInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String token = request.getHeader("token");
Claims claims = JwtUtil.parseToken(token);
Long userId = claims.get("userId", Long.class);
String username = claims.get("username", String.class);
LoginUserHolder.setLoginUser(new LoginUser(userId, username));
return true;
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
LoginUserHolder.clear();
}
}

View File

@ -0,0 +1,13 @@
package com.atjy.web.admin.mapper;
import com.atjy.model.entity.GraphInfo;
import com.atjy.model.enums.GraphItemType;
import com.atjy.web.admin.vo.graph.GraphVo;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import java.util.List;
public interface GraphInfoMapper extends BaseMapper<GraphInfo> {
List<GraphVo> selectListByItemTypeAndId(GraphItemType itemType, Long id);
}

View File

@ -0,0 +1,9 @@
package com.atjy.web.admin.mapper;
import com.atjy.model.entity.SystemUser;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
public interface SystemUserMapper extends BaseMapper<SystemUser> {
SystemUser selectOneByUsername(String username);
}

View File

@ -0,0 +1,21 @@
package com.atjy.web.admin.mybatisplus;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
@Component
public class MybatisMetaObjectHandler implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
this.strictInsertFill(metaObject, "createTime", LocalDateTime.class, LocalDateTime.now());
}
@Override
public void updateFill(MetaObject metaObject) {
this.strictUpdateFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now());
}
}

View File

@ -0,0 +1,20 @@
package com.atjy.web.admin.mybatisplus;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
@MapperScan("com.atjy.web.admin.mapper")
public class MybatisPlusConfiguration {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
}

View File

@ -0,0 +1,13 @@
package com.atjy.web.admin.service;
import io.minio.errors.*;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
public interface FileService {
String upload(MultipartFile file) throws ServerException, InsufficientDataException, ErrorResponseException, IOException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException;
}

View File

@ -0,0 +1,7 @@
package com.atjy.web.admin.service;
import com.atjy.model.entity.GraphInfo;
import com.baomidou.mybatisplus.extension.service.IService;
public interface GraphInfoService extends IService<GraphInfo> {
}

View File

@ -0,0 +1,14 @@
package com.atjy.web.admin.service;
import com.atjy.common.result.Result;
import com.atjy.web.admin.vo.login.CaptchaVo;
import com.atjy.web.admin.vo.login.LoginVo;
import com.atjy.web.admin.vo.system.user.SystemUserInfoVo;
public interface LoginService {
Result<String> login(LoginVo loginVo);
CaptchaVo getCaptcha();
SystemUserInfoVo getLoginUserInfo(Long userId);
}

View File

@ -0,0 +1,71 @@
package com.atjy.web.admin.service.impl;
import com.atjy.web.admin.service.FileService;
import com.atjy.common.minio.MinioProperties;
import io.minio.*;
import io.minio.errors.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.ErrorResponseException;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.UUID;
@Service
public class FileServiceImpl implements FileService {
@Autowired
private MinioClient minioClient;
@Autowired
private MinioProperties properties;
@Override
public String upload(MultipartFile file) throws InsufficientDataException, ErrorResponseException, IOException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException, io.minio.errors.ServerException, io.minio.errors.ErrorResponseException {
boolean bucketExists = minioClient.bucketExists(BucketExistsArgs.builder().bucket(properties.getBucketName()).build());
if (!bucketExists) {
minioClient.makeBucket(
MakeBucketArgs.builder()
.bucket(properties.getBucketName())
.build());
minioClient.setBucketPolicy(
SetBucketPolicyArgs.builder()
.bucket(properties.getBucketName())
.config(createBucketPolicyConfig(properties.getBucketName()))
.build());
}
String filename = new SimpleDateFormat("yyyyMMdd").format(new Date()) +
"/" + UUID.randomUUID() + "-" + file.getOriginalFilename();
minioClient.putObject(
PutObjectArgs.builder()
.bucket(properties.getBucketName())
.stream(file.getInputStream(), file.getSize(), -1)
.object(filename)
.contentType(file.getContentType())
.build());
String result = String.join("/", properties.getEndpoint(), properties.getBucketName(), filename);
return result;
}
private String createBucketPolicyConfig(String bucketName) {
return """
{
"Statement" : [ {
"Action" : "s3:GetObject",
"Effect" : "Allow",
"Principal" : "*",
"Resource" : "arn:aws:s3:::%s/*"
} ],
"Version" : "2012-10-17"
}
""".formatted(bucketName);
}
}

View File

@ -0,0 +1,13 @@
package com.atjy.web.admin.service.impl;
import com.atjy.model.entity.GraphInfo;
import com.atjy.web.admin.mapper.GraphInfoMapper;
import com.atjy.web.admin.service.GraphInfoService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
@Service
public class GraphInfoServiceImpl extends ServiceImpl<GraphInfoMapper, GraphInfo>
implements GraphInfoService {
}

View File

@ -0,0 +1,95 @@
package com.atjy.web.admin.service.impl;
import com.atjy.common.constant.RedisConstant;
import com.atjy.common.exception.HassleFreeException;
import com.atjy.common.result.Result;
import com.atjy.common.result.ResultCodeEnum;
import com.atjy.common.utils.JwtUtil;
import com.atjy.model.entity.SystemUser;
import com.atjy.model.enums.BaseStatus;
import com.atjy.web.admin.mapper.SystemUserMapper;
import com.atjy.web.admin.service.LoginService;
import com.atjy.web.admin.vo.login.CaptchaVo;
import com.atjy.web.admin.vo.login.LoginVo;
import com.atjy.web.admin.vo.system.user.SystemUserInfoVo;
import org.apache.commons.codec.digest.DigestUtils;
import com.wf.captcha.SpecCaptcha;
import com.wf.captcha.base.Captcha;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
@Service
public class LoginServiceImpl implements LoginService {
@Autowired
private StringRedisTemplate redisTemplate;
@Autowired
private SystemUserMapper systemUserMapper;
@Override
public Result<String> login(LoginVo loginVo) {
//1.判断是否输入了验证码
if (!StringUtils.hasText(loginVo.getCaptchaCode())) {
throw new HassleFreeException(ResultCodeEnum.ADMIN_CAPTCHA_CODE_NOT_FOUND);
}
//2.校验验证码
String code = redisTemplate.opsForValue().get(loginVo.getCaptchaKey());
if (code == null) {
return Result.fail(303, "验证码已过期");
}
if (!code.equals(loginVo.getCaptchaCode().toLowerCase())) {
return Result.fail(302, "验证码错误");
}
//3.校验用户是否存在
SystemUser systemUser = systemUserMapper.selectOneByUsername(loginVo.getUsername());
if (systemUser == null) {
return Result.fail(306, "用户不存在");
}
//4.校验用户是否被禁
if (systemUser.getState() == BaseStatus.DISABLE) {
return Result.fail(308, "该用户已被禁用");
}
//5.校验用户密码
if (!systemUser.getPassword().equals(DigestUtils.md5Hex(loginVo.getPassword()))) {
return Result.fail(307, "密码错误");
}
//6.创建并返回TOKEN
return Result.ok(JwtUtil.createToken(systemUser.getId(), systemUser.getUsername()));
}
@Override
public CaptchaVo getCaptcha() {
SpecCaptcha specCaptcha = new SpecCaptcha(130, 48, 4);
specCaptcha.setCharType(Captcha.TYPE_DEFAULT);
String code = specCaptcha.text().toLowerCase();
String key = RedisConstant.ADMIN_LOGIN_PREFIX + UUID.randomUUID();
String image = specCaptcha.toBase64();
redisTemplate.opsForValue().set(key, code, RedisConstant.ADMIN_LOGIN_CAPTCHA_TTL_SEC, TimeUnit.SECONDS);
return new CaptchaVo(image, key);
}
@Override
public SystemUserInfoVo getLoginUserInfo(Long userId) {
SystemUser systemUser = systemUserMapper.selectById(userId);
SystemUserInfoVo systemUserInfoVo = new SystemUserInfoVo();
systemUserInfoVo.setName(systemUser.getName());
systemUserInfoVo.setAvatarUrl(systemUser.getAvatarUrl());
return systemUserInfoVo;
}
}

View File

@ -0,0 +1,24 @@
package com.atjy.web.admin.vo.graph;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@Schema(description = "图片信息")
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class GraphVo {
@Schema(description = "图片名称")
private String name;
@Schema(description = "图片地址")
private String url;
}

View File

@ -0,0 +1,17 @@
package com.atjy.web.admin.vo.login;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Data;
@Data
@Schema(description = "图像验证码")
@AllArgsConstructor
public class CaptchaVo {
@Schema(description = "验证码图片信息")
private String image;
@Schema(description = "验证码key")
private String key;
}

View File

@ -0,0 +1,21 @@
package com.atjy.web.admin.vo.login;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Data
@Schema(description = "后台管理系统登录信息")
public class LoginVo {
@Schema(description = "用户名")
private String username;
@Schema(description = "密码")
private String password;
@Schema(description = "验证码key")
private String captchaKey;
@Schema(description = "验证码code")
private String captchaCode;
}

View File

@ -0,0 +1,8 @@
package com.atjy.web.admin.vo.login;
public class loginResult {
public String data(String result) {
return result;
}
}

View File

@ -0,0 +1,16 @@
package com.atjy.web.admin.vo.system.user;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Schema(description = "管理员基本信息")
@Data
public class SystemUserInfoVo {
@Schema(description = "用户姓名")
private String name;
@Schema(description = "用户头像")
private String avatarUrl;
}

View File

@ -0,0 +1,38 @@
server:
port: 8080
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
username: root
password: Atjy.000000
url: jdbc:mysql://192.168.47.101:3306/hassle_free?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2b8
hikari:
connection-test-query: SELECT 1 # 自动检测连接
connection-timeout: 60000 #数据库连接超时时间,默认30秒
idle-timeout: 500000 #空闲连接存活最大时间默认60000010分钟
max-lifetime: 540000 #此属性控制池中连接的最长生命周期值0表示无限生命周期默认1800000即30分钟
maximum-pool-size: 12 #连接池最大连接数默认是10
minimum-idle: 10 #最小空闲连接数量
pool-name: SPHHikariPool # 连接池名称
jackson:
time-zone: GMT+8
date-format: yyyy-MM-dd HH:mm:ss
data:
redis:
host: 192.168.47.101
port: 6379
database: 0
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
springdoc:
default-flat-param-object: true
minio:
endpoint: http://192.168.47.101:9000
access-key: minioadmin
secret-key: minioadmin
bucket-name: hassle-free

View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.atjy.web.admin.mapper.GraphInfoMapper">
<select id="selectListByItemTypeAndId" resultType="com.atjy.web.admin.vo.graph.GraphVo">
select name,
url
from graph_info
where is_deleted = 0
and item_type = #{itemType}
and item_id = #{id}
</select>
</mapper>

View File

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.atjy.web.admin.mapper.SystemUserMapper">
<select id="selectOneByUsername" resultType="com.atjy.model.entity.SystemUser">
select id,
username,
password,
name,
type,
phone,
avatar_url,
additional_info,
post_id,
state
from system_user
where is_deleted = 0
and username = #{username}
</select>
</mapper>

38
web/web-app/.gitignore vendored Normal file
View File

@ -0,0 +1,38 @@
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/
### IntelliJ IDEA ###
.idea/modules.xml
.idea/jarRepositories.xml
.idea/compiler.xml
.idea/libraries/
*.iws
*.iml
*.ipr
### Eclipse ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
!**/src/main/**/build/
!**/src/test/**/build/
### VS Code ###
.vscode/
### Mac OS ###
.DS_Store

40
web/web-app/pom.xml Normal file
View File

@ -0,0 +1,40 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.atjy</groupId>
<artifactId>web</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>web-app</artifactId>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dashscope-sdk-java</artifactId>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.14</version>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,17 @@
package com.atjy.web.app;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;
@MapperScan("com.atjy.web.app.mapper")
@SpringBootApplication
@EnableAsync
public class WebAppApplication {
public static void main(String[] args) {
SpringApplication.run(WebAppApplication.class, args);
}
}

View File

@ -0,0 +1,60 @@
package com.atjy.web.app.ai;
import com.alibaba.dashscope.aigc.generation.Generation;
import com.alibaba.dashscope.aigc.generation.GenerationParam;
import com.alibaba.dashscope.aigc.generation.GenerationResult;
import com.alibaba.dashscope.common.Message;
import com.alibaba.dashscope.common.Role;
import com.alibaba.dashscope.exception.ApiException;
import com.alibaba.dashscope.exception.InputRequiredException;
import com.alibaba.dashscope.exception.NoApiKeyException;
import com.atjy.web.app.mapper.ConsultMapper;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Ai {
public static List<Message> messages = new ArrayList<>();
public static boolean flag = true;
public static GenerationParam createGenerationParam(List<Message> messages) {
return GenerationParam.builder()
.model("qwen-plus")
.messages(messages)
.resultFormat(GenerationParam.ResultFormat.MESSAGE)
.build();
}
public static GenerationResult callGenerationWithMessages(GenerationParam param) throws ApiException, NoApiKeyException, InputRequiredException {
Generation gen = new Generation();
return gen.call(param);
}
private static Message createMessage(Role role, String content) {
return Message.builder().role(role.getValue()).content(content).build();
}
public static void addMessage() {
messages.add(createMessage(Role.SYSTEM, "You are a helpful assistant."));
}
public static String getAnswer(String problem) {
try {
messages.add(createMessage(Role.USER, problem));
GenerationParam param = createGenerationParam(messages);
GenerationResult result = callGenerationWithMessages(param);
messages.add(result.getOutput().getChoices().get(0).getMessage());
return result.getOutput().getChoices().get(0).getMessage().getContent();
} catch (ApiException | NoApiKeyException | InputRequiredException e) {
e.printStackTrace();
}
System.exit(0);
return null;
}
}

View File

@ -0,0 +1,34 @@
package com.atjy.web.app.controller.appointment;
import com.atjy.common.result.Result;
import com.atjy.web.app.service.AppointmentInfoService;
import com.atjy.web.app.vo.appointment.AppointmentInfoVo;
import com.atjy.web.app.vo.appointment.AppointmentOrderVo;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@Tag(name = "预约信息")
@RestController
@RequestMapping("/app/appointment")
public class Appointment {
@Autowired
private AppointmentInfoService service;
@Operation(summary = "获取预约详情")
@PostMapping("getAppointmentByIdAndTime")
public Result<AppointmentInfoVo> getAppointmentByIdAndTime(@RequestParam Long id, @RequestParam String date) {
return Result.ok(service.getAppointmentByIdAndTime(id, date));
}
@Operation(summary = "获取预约订单")
@PostMapping("getAppointmentOrderByIdAndTime")
public Result<AppointmentOrderVo> getAppointmentOrderByIdAndTime(@RequestParam Long id, @RequestParam String date) {
return Result.ok(service.getAppointmentOrderByIdAndTime(id,date));
}
}

View File

@ -0,0 +1,45 @@
package com.atjy.web.app.controller.article;
import com.atjy.common.result.Result;
import com.atjy.model.entity.ArticleInfo;
import com.atjy.model.enums.ArticleItemType;
import com.atjy.web.app.service.ArticleService;
import com.atjy.web.app.vo.article.ArticleInfoVo;
import com.atjy.web.app.vo.article.ArticleVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.parameters.RequestBody;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@Tag(name = "医说信息")
@RestController
@RequestMapping("/app/article")
public class ArticleController {
@Autowired
private ArticleService service;
@Operation(summary = "根据内容获取医说")
@PostMapping("getArticleByContent")
public Result<List<ArticleVo>> getArticleByContent(@RequestParam(required = false) String content) {
return Result.ok(service.getArticleByContent(content));
}
@Operation(summary = "获取医说详情")
@PostMapping("getArticleInfo")
public Result<ArticleInfoVo> getArticleInfo(@RequestParam Long articleId) {
ArticleInfoVo result = service.getArticle(articleId);
return Result.ok(result);
}
@Operation(summary = "获取不同类型医说")
@PostMapping("getArticleByType")
public Result<List<ArticleVo>> getArticleByType(@RequestParam String type) {
return Result.ok(service.getArticleByType(type));
}
}

View File

@ -0,0 +1,28 @@
package com.atjy.web.app.controller.consult;
import com.atjy.common.login.LoginUserHolder;
import com.atjy.common.result.Result;
import com.atjy.web.app.service.ConsultService;
import com.atjy.web.app.vo.consult.ProblemVo;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@Tag(name = "问诊管理")
@RestController
@RequestMapping("/app/ai")
public class AiConsultController {
@Autowired
private ConsultService service;
@Operation(summary = "ai咨询")
@PostMapping("Consult")
public Result<String> getAnswer(@RequestBody ProblemVo problem) {
Integer consultationNumber = service.getNumberByUserId(LoginUserHolder.getLoginUser().getUserId()) + 1;
String result = service.getAnswerToAi(problem.getProblem(), consultationNumber);
return Result.ok(result);
}
}

View File

@ -0,0 +1,46 @@
package com.atjy.web.app.controller.doctor;
import com.atjy.common.result.Result;
import com.atjy.web.app.service.DoctorService;
import com.atjy.web.app.vo.doctor.DoctorInfoVo;
import com.atjy.web.app.vo.doctor.DoctorTermsVo;
import com.atjy.web.app.vo.doctor.DoctorVo;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@Tag(name = "医生管理")
@RestController
@RequestMapping("/app/doctor")
public class DoctorController {
@Autowired
private DoctorService service;
@Operation(summary = "根据姓名获取医生")
@PostMapping("getDoctorByName")
public Result<List<DoctorVo>> getDoctorByName(@RequestParam(required = false) String name) {
return Result.ok(service.getDoctorByName(name));
}
@Operation(summary = "根据条件筛选医生")
@PostMapping("getDoctorByTerms")
public Result<List<DoctorVo>> getDoctorByTerms(@RequestBody DoctorTermsVo doctorTermsVo) {
return Result.ok(service.getDoctorByTerms(doctorTermsVo));
}
@Operation(summary = "获取医生详情")
@PostMapping("getDoctorById")
public Result<DoctorInfoVo> getDoctorById(@RequestParam Long doctorId) {
return Result.ok(service.getDoctorById(doctorId));
}
@Operation(summary = "根据医院id和科室和时间获取医生")
@PostMapping("getDoctorByIdAndDepartmentAndTime")
public Result<List<DoctorVo>> getDoctorByIdAndDepartmentAndTime(@RequestParam Long hospitalId, @RequestParam String department, @RequestParam(required = false) String date) {
return Result.ok(service.getDoctorByIdAndDepartmentAndTime(hospitalId, department, date));
}
}

View File

@ -0,0 +1,30 @@
package com.atjy.web.app.controller.homepage;
import com.atjy.common.result.Result;
import com.atjy.web.app.service.HomepageService;
import com.atjy.web.app.vo.doctor.DoctorVo;
import com.atjy.web.app.vo.homepage.HomepageVo;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@Tag(name = "首页管理")
@RestController
@RequestMapping("/app/homepage")
public class HomepageController {
@Autowired
private HomepageService service;
@Operation(summary = "根据区域id获取首页列表")
@PostMapping("getHomepageByDistrictId")
public Result<HomepageVo> getHomepageByDistrictId(@RequestParam Long districtId) {
return Result.ok(service.getHomepageByDistrictId(districtId));
}
}

View File

@ -0,0 +1,51 @@
package com.atjy.web.app.controller.hospital;
import com.atjy.common.result.Result;
import com.atjy.model.entity.HospitalInfo;
import com.atjy.web.app.service.HospitalService;
import com.atjy.web.app.vo.hospital.HospitalInfoVo;
import com.atjy.web.app.vo.hospital.HospitalTermsVo;
import com.atjy.web.app.vo.hospital.HospitalVo;
import com.atjy.web.app.vo.hospital.RegisteredVo;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@Tag(name = "医院管理")
@RestController
@RequestMapping("/app/hospital")
public class HospitalController {
@Autowired
private HospitalService service;
@Operation(summary = "根据名称获取医院")
@PostMapping("getHospitalByName")
public Result<List<HospitalVo>> getHospitalByName(@RequestParam(required = false) String name) {
List<HospitalVo> result = service.getHospitalByName(name);
return Result.ok(result);
}
@Operation(summary = "根据条件筛选医院")
@PostMapping("getHospitalByTerms")
public Result<List<HospitalVo>> getHospitalByTerms(@RequestBody HospitalTermsVo hospitalTerms) {
List<HospitalVo> result = service.getHospitalByTerms(hospitalTerms);
return Result.ok(result);
}
@Operation(summary = "获取医院详情")
@PostMapping("getHospitalById")
public Result<HospitalInfoVo> getHospitalById(@RequestParam Long hospitalId) {
return Result.ok(service.getHospitalById(hospitalId));
}
@Operation(summary = "获取挂号详情")
@PostMapping("getRegisteredById")
public Result<RegisteredVo> getRegisteredById(@RequestParam Long hospitalId) {
return Result.ok(service.getRegisteredById(hospitalId));
}
}

View File

@ -0,0 +1,41 @@
package com.atjy.web.app.controller.login;
import com.atjy.common.login.LoginUserHolder;
import com.atjy.common.result.Result;
import com.atjy.web.app.service.LoginService;
import com.atjy.web.app.vo.login.LoginVo;
import com.atjy.web.app.vo.login.UserInfoVo;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@Tag(name = "登录管理")
@RestController
@RequestMapping("/app")
public class LoginController {
@Autowired
private LoginService service;
@Operation(summary = "登录")
@PostMapping("login")
public Result<String> login(@RequestBody LoginVo loginVo) {
return service.login(loginVo);
}
@GetMapping("login/getCode")
@Operation(summary = "获取短信验证码")
public Result getCode(@RequestParam String phone) {
return service.getSMSCode(phone);
}
@GetMapping("info")
@Operation(summary = "获取登录用户信息")
public Result<UserInfoVo> info() {
UserInfoVo info = service.getUserInfoById(LoginUserHolder.getLoginUser().getUserId());
return Result.ok(info);
}
}

View File

@ -0,0 +1,47 @@
package com.atjy.web.app.controller.myself;
import com.atjy.common.login.LoginUserHolder;
import com.atjy.common.result.Result;
import com.atjy.web.app.service.UserAppointmentService;
import com.atjy.web.app.vo.appointment.AppointmentVo;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.List;
@Tag(name = "就诊信息")
@RestController
@RequestMapping("/app/center/appointment")
public class AppointmentController {
@Autowired
private UserAppointmentService service;
@Operation(summary = "获取全部就诊详情")
@GetMapping("getAllDiagnosis")
public Result<List<AppointmentVo>> getAllDiagnosis() {
List<AppointmentVo> waitDiagnosis = service.getWaitDiagnosis(LoginUserHolder.getLoginUser().getUserId());
List<AppointmentVo> alreadyDiagnosis = service.getAlreadyDiagnosis(LoginUserHolder.getLoginUser().getUserId());
alreadyDiagnosis.addAll(waitDiagnosis);
return Result.ok(alreadyDiagnosis);
}
@Operation(summary = "获取待就诊详情")
@GetMapping("getWaitDiagnosis")
public Result<List<AppointmentVo>> getWaitDiagnosis() {
return Result.ok(service.getWaitDiagnosis(LoginUserHolder.getLoginUser().getUserId()));
}
@Operation(summary = "获取已就诊详情")
@GetMapping("getAlreadyDiagnosis")
public Result<List<AppointmentVo>> getAlreadyDiagnosis() {
return Result.ok(service.getAlreadyDiagnosis(LoginUserHolder.getLoginUser().getUserId()));
}
}

View File

@ -0,0 +1,47 @@
package com.atjy.web.app.controller.myself;
import com.atjy.common.login.LoginUserHolder;
import com.atjy.common.result.Result;
import com.atjy.web.app.service.CollectionService;
import com.atjy.web.app.vo.article.ArticleVo;
import com.atjy.web.app.vo.doctor.DoctorVo;
import com.atjy.web.app.vo.hospital.HospitalVo;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@Tag(name = "收藏信息")
@RestController
@RequestMapping("/app/center/collection")
public class CollectionController {
@Autowired
private CollectionService service;
@Operation(summary = "获取医院详情")
@GetMapping("hospital")
public Result<List<HospitalVo>> getHospitalInfo() {
List<HospitalVo> result = service.selectHospitalInfoListByUserId(LoginUserHolder.getLoginUser().getUserId());
return Result.ok(result);
}
@Operation(summary = "获取医生详情")
@GetMapping("doctor")
public Result<List<DoctorVo>> getDoctorInfo() {
List<DoctorVo> result = service.selectDoctorInfoListByUserId(LoginUserHolder.getLoginUser().getUserId());
return Result.ok(result);
}
@Operation(summary = "获取医说详情")
@GetMapping("article")
public Result<List<ArticleVo>> getArticleInfo() {
List<ArticleVo> result = service.selectArticleInfoListByUserId(LoginUserHolder.getLoginUser().getUserId());
return Result.ok(result);
}
}

View File

@ -0,0 +1,30 @@
package com.atjy.web.app.controller.myself;
import com.atjy.common.login.LoginUserHolder;
import com.atjy.common.result.Result;
import com.atjy.web.app.service.ConsultService;
import com.atjy.web.app.vo.consult.ConsultInfoVo;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@Tag(name = "咨询信息")
@RestController
@RequestMapping("/app/center/logs")
public class ConsultController {
@Autowired
private ConsultService service;
@Operation(summary = "获取全部咨询详情")
@GetMapping("consult")
public Result<List<ConsultInfoVo>> getAllConsult() {
List<ConsultInfoVo> result = service.getAllConsultByUserId(LoginUserHolder.getLoginUser().getUserId());
return Result.ok(result);
}
}

View File

@ -0,0 +1,81 @@
package com.atjy.web.app.custom.config;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.info.License;
import org.springdoc.core.models.GroupedOpenApi;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class Knife4jConfiguration {
@Bean
public OpenAPI customOpenAPI() {
return new OpenAPI()
.info(new Info()
.title("医路无忧App系统API")
.version("1.0")
.description("用户端APP接口")
.termsOfService("http://doc.xiaominfo.com")
.license(new License().name("Apache 2.0")
.url("http://doc.xiaominfo.com")));
}
@Bean
public GroupedOpenApi loginAPI() {
return GroupedOpenApi.builder().group("登录信息").
pathsToMatch("/app/login/**", "/app/info").
build();
}
@Bean
public GroupedOpenApi interrogationAPI() {
return GroupedOpenApi.builder().group("问诊信息").
pathsToMatch("/app/ai/**").
build();
}
@Bean
public GroupedOpenApi myselfAPI() {
return GroupedOpenApi.builder().group("个人中心信息").
pathsToMatch("/app/center/**").
build();
}
@Bean
public GroupedOpenApi articleAPI() {
return GroupedOpenApi.builder().group("医说信息").
pathsToMatch("/app/article/**").
build();
}
@Bean
public GroupedOpenApi doctorAPI() {
return GroupedOpenApi.builder().group("医生信息").
pathsToMatch("/app/doctor/**").
build();
}
@Bean
public GroupedOpenApi hospitalAPI() {
return GroupedOpenApi.builder().group("医院信息").
pathsToMatch("/app/hospital/**").
build();
}
@Bean
public GroupedOpenApi homepageAPI() {
return GroupedOpenApi.builder().group("首页信息").
pathsToMatch("/app/homepage/**").
build();
}
@Bean
public GroupedOpenApi appointmentAPI() {
return GroupedOpenApi.builder().group("预约信息").
pathsToMatch("/app/appointment/**").
build();
}
}

View File

@ -0,0 +1,21 @@
package com.atjy.web.app.custom.config;
import com.atjy.web.app.custom.interceptor.AuthenticationInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebMvcConfiguration implements WebMvcConfigurer {
@Autowired
private AuthenticationInterceptor authenticationInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(this.authenticationInterceptor)
.addPathPatterns("/app/**")
.excludePathPatterns("/app/login/**");
}
}

View File

@ -0,0 +1,31 @@
package com.atjy.web.app.custom.interceptor;
import com.atjy.common.login.LoginUser;
import com.atjy.common.login.LoginUserHolder;
import com.atjy.common.utils.JwtUtil;
import io.jsonwebtoken.Claims;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
@Component
public class AuthenticationInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
String token = request.getHeader("token");
Claims claims = JwtUtil.parseToken(token);
Long userId = claims.get("userId", Long.class);
String username = claims.get("username", String.class);
LoginUserHolder.setLoginUser(new LoginUser(userId, username));
return true;
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
LoginUserHolder.clear();
}
}

View File

@ -0,0 +1,7 @@
package com.atjy.web.app.mapper;
import com.atjy.model.entity.AppointmentInfo;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
public interface AppointmentInfoMapper extends BaseMapper<AppointmentInfo> {
}

View File

@ -0,0 +1,13 @@
package com.atjy.web.app.mapper;
import com.atjy.model.entity.ArticleInfo;
import com.atjy.web.app.vo.article.ArticleVo;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import java.util.List;
public interface ArticleMapper extends BaseMapper<ArticleInfo> {
List<ArticleVo> selectListByDoctorId(Long doctorId);
List<ArticleVo> selectListByDoctorIdList(List<Long> doctorIdList);
}

View File

@ -0,0 +1,12 @@
package com.atjy.web.app.mapper;
import com.atjy.model.entity.CityInfo;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
public interface CityInfoMapper extends BaseMapper<CityInfo> {
}

View File

@ -0,0 +1,17 @@
package com.atjy.web.app.mapper;
import com.atjy.model.entity.UserCollection;
import com.atjy.web.app.vo.article.ArticleVo;
import com.atjy.web.app.vo.doctor.DoctorVo;
import com.atjy.web.app.vo.hospital.HospitalVo;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import java.util.List;
public interface CollectionMapper extends BaseMapper<UserCollection> {
List<HospitalVo> selectHospitalListByUserId(Long userId);
List<ArticleVo> selectArticleInfoListByUserId(Long userId);
List<DoctorVo> selectDoctorInfoListByUserId(Long userId);
}

View File

@ -0,0 +1,16 @@
package com.atjy.web.app.mapper;
import com.atjy.model.entity.ConsultInfo;
import com.atjy.web.app.vo.consult.ConsultInfoVo;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import java.util.List;
public interface ConsultMapper extends BaseMapper<ConsultInfo> {
List<ConsultInfoVo> getAllConsultByUserId(Long userId);
Integer getNumberByUserId(Long userId);
}

View File

@ -0,0 +1,10 @@
package com.atjy.web.app.mapper;
import com.atjy.model.entity.DepartmentInfo;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import java.util.List;
public interface DepartmentInfoMapper extends BaseMapper<DepartmentInfo> {
List<DepartmentInfo> selectListByHospitalId(Long hospitalId);
}

View File

@ -0,0 +1,7 @@
package com.atjy.web.app.mapper;
import com.atjy.model.entity.DepartmentInfo;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
public interface DepartmentMapper extends BaseMapper<DepartmentInfo> {
}

View File

@ -0,0 +1,12 @@
package com.atjy.web.app.mapper;
import com.atjy.model.entity.DistrictInfo;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
public interface DistrictInfoMapper extends BaseMapper<DistrictInfo> {
}

View File

@ -0,0 +1,12 @@
package com.atjy.web.app.mapper;
import com.atjy.model.entity.DoctorAppointment;
import com.atjy.web.app.vo.appointment.AppointmentTimeVo;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import java.util.List;
public interface DoctorAppointmentMapper extends BaseMapper<DoctorAppointment> {
List<AppointmentTimeVo> selectListByDoctorId(Long doctorId);
}

View File

@ -0,0 +1,28 @@
package com.atjy.web.app.mapper;
import com.atjy.model.entity.DoctorInfo;
import com.atjy.web.app.vo.doctor.DoctorSmallVo;
import com.atjy.web.app.vo.doctor.DoctorTermsVo;
import com.atjy.web.app.vo.doctor.DoctorVo;
import com.atjy.web.app.vo.hospital.HospitalVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import java.util.List;
public interface DoctorMapper extends BaseMapper<DoctorInfo> {
List<DoctorSmallVo> selectListDoctorSmallVo(Long hospitalId);
List<DoctorVo> getDoctorByTerms(DoctorTermsVo doctorTermsVo);
List<DoctorVo> selectListByHospitalIdList(List<Long> list);
List<DoctorVo> selectListByHospitalIdListAndExpertise(List<Long> list, String expertise);
List<DoctorVo> getDoctorByIdAndDepartment(Long hospitalId, String department);
List<DoctorVo> getDoctorByIdAndDepartmentAndTime(Long hospitalId, String department, List<Long> list);
String selectDepartment(Long id);
}

View File

@ -0,0 +1,14 @@
package com.atjy.web.app.mapper;
import com.atjy.model.entity.GraphInfo;
import com.atjy.model.enums.GraphItemType;
import com.atjy.web.app.vo.graph.GraphVo;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import java.util.List;
public interface GraphInfoMapper extends BaseMapper<GraphInfo> {
List<GraphVo> selectListByItemTypeAndId(GraphItemType itemType, Long id);
}

View File

@ -0,0 +1,10 @@
package com.atjy.web.app.mapper;
import com.atjy.model.entity.HospitalDepartment;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import java.util.List;
public interface HospitalDepartmentMapper extends BaseMapper<HospitalDepartment> {
List<String> selectDepartmentList(Long hospitalId);
}

View File

@ -0,0 +1,10 @@
package com.atjy.web.app.mapper;
import com.atjy.model.entity.HospitalLabel;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import java.util.List;
public interface HospitalLabelMapper extends BaseMapper<HospitalLabel> {
List<String> selectListByHospitalId(Long id);
}

View File

@ -0,0 +1,13 @@
package com.atjy.web.app.mapper;
import com.atjy.model.entity.HospitalInfo;
import com.atjy.web.app.vo.hospital.HospitalTermsVo;
import com.atjy.web.app.vo.hospital.HospitalVo;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import java.util.List;
public interface HospitalMapper extends BaseMapper<HospitalInfo> {
List<HospitalVo> getHospitalByTerms(HospitalTermsVo hospitalTerms);
}

View File

@ -0,0 +1,12 @@
package com.atjy.web.app.mapper;
import com.atjy.model.entity.ProvinceInfo;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
public interface ProvinceInfoMapper extends BaseMapper<ProvinceInfo> {
}

Some files were not shown because too many files have changed in this diff Show More