1
This commit is contained in:
commit
b377c87a1a
47
sa-admin/pom.xml
Normal file
47
sa-admin/pom.xml
Normal file
@ -0,0 +1,47 @@
|
||||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
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>net.lab1024</groupId>
|
||||
<artifactId>sa-parent</artifactId>
|
||||
<version>3.0.0</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<artifactId>sa-admin</artifactId>
|
||||
<version>3.0.0</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>sa-admin</name>
|
||||
<description>sa-admin project</description>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<dependency>
|
||||
<groupId>net.lab1024</groupId>
|
||||
<artifactId>sa-base</artifactId>
|
||||
<version>3.0.0</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<configuration>
|
||||
<mainClass>net.lab1024.sa.admin.AdminApplication</mainClass>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>repackage</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
@ -0,0 +1,40 @@
|
||||
package net.lab1024.sa.admin;
|
||||
|
||||
import net.lab1024.sa.base.listener.Ip2RegionListener;
|
||||
import net.lab1024.sa.base.listener.LogVariableListener;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.mybatis.spring.annotation.MapperScan;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration;
|
||||
import org.springframework.cache.annotation.EnableCaching;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.EnableAspectJAutoProxy;
|
||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||
|
||||
/**
|
||||
* SmartAdmin 项目启动类
|
||||
*
|
||||
* @Author 1024创新实验室-主任:卓大
|
||||
* @Date 2022-08-29 21:00:58
|
||||
* @Wechat zhuoda1024
|
||||
* @Email lab1024@163.com
|
||||
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>
|
||||
*/
|
||||
@EnableCaching
|
||||
@EnableScheduling
|
||||
@EnableAspectJAutoProxy(proxyTargetClass = true, exposeProxy = true)
|
||||
@ComponentScan(AdminApplication.COMPONENT_SCAN)
|
||||
@MapperScan(value = AdminApplication.COMPONENT_SCAN, annotationClass = Mapper.class)
|
||||
@SpringBootApplication(exclude = {UserDetailsServiceAutoConfiguration.class})
|
||||
public class AdminApplication {
|
||||
|
||||
public static final String COMPONENT_SCAN = "net.lab1024.sa";
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication application = new SpringApplication(AdminApplication.class);
|
||||
// 添加 日志监听器,使 log4j2-spring.xml 可以间接读取到配置文件的属性
|
||||
application.addListeners(new LogVariableListener(), new Ip2RegionListener());
|
||||
application.run(args);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,28 @@
|
||||
package net.lab1024.sa.admin.config;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Data
|
||||
@Component
|
||||
public class AppConfig {
|
||||
|
||||
@Value("${app.apiUrl}")
|
||||
private String apiUrl;
|
||||
|
||||
@Value("${app.secretKey}")
|
||||
private String secretKey;
|
||||
|
||||
@Value("${app.imagePrefix}")
|
||||
private String imagePrefix;
|
||||
|
||||
@Value("${app.platform}")
|
||||
private String platform;
|
||||
|
||||
@Value("${app.platformPointAccount}")
|
||||
private String platformPointAccount;
|
||||
|
||||
@Value("${app.access-token}")
|
||||
private String accessToken;
|
||||
}
|
||||
@ -0,0 +1,16 @@
|
||||
package net.lab1024.sa.admin.config;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Data
|
||||
@Component
|
||||
public class DySmsConfig {
|
||||
|
||||
@Value("${aliyun.sms.access-key:}")
|
||||
private String accessKey;
|
||||
|
||||
@Value("${aliyun.sms.access-secret:}")
|
||||
private String accessSecret;
|
||||
}
|
||||
@ -0,0 +1,13 @@
|
||||
package net.lab1024.sa.admin.config;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Data
|
||||
@Component
|
||||
public class EnvConfig {
|
||||
|
||||
@Value("${spring.profiles.active:prod}")
|
||||
private String active;
|
||||
}
|
||||
@ -0,0 +1,41 @@
|
||||
package net.lab1024.sa.admin.config;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
import net.lab1024.sa.admin.interceptor.AdminInterceptor;
|
||||
import net.lab1024.sa.base.config.SwaggerConfig;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
|
||||
/**
|
||||
* web相关配置
|
||||
*
|
||||
* @Author 1024创新实验室-主任: 卓大
|
||||
* @Date 2021-09-02 20:21:10
|
||||
* @Wechat zhuoda1024
|
||||
* @Email lab1024@163.com
|
||||
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>
|
||||
*/
|
||||
@Configuration
|
||||
public class MvcConfig implements WebMvcConfigurer {
|
||||
|
||||
@Resource
|
||||
private AdminInterceptor adminInterceptor;
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void addInterceptors(InterceptorRegistry registry) {
|
||||
registry.addInterceptor(adminInterceptor)
|
||||
.excludePathPatterns(SwaggerConfig.SWAGGER_WHITELIST)
|
||||
.addPathPatterns("/**");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addResourceHandlers(ResourceHandlerRegistry registry) {
|
||||
registry.addResourceHandler("doc.html").addResourceLocations("classpath:/META-INF/resources/");
|
||||
registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,25 @@
|
||||
package net.lab1024.sa.admin.config;
|
||||
|
||||
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
|
||||
import org.apache.ibatis.reflection.MetaObject;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneId;
|
||||
|
||||
@Component
|
||||
public class MyMetaObjectHandler implements MetaObjectHandler {
|
||||
|
||||
private static final ZoneId BEIJING_ZONE = ZoneId.of("Asia/Shanghai");
|
||||
|
||||
@Override
|
||||
public void insertFill(MetaObject metaObject) {
|
||||
this.strictInsertFill(metaObject, "createdAt", LocalDateTime.class, LocalDateTime.now(BEIJING_ZONE));
|
||||
this.strictInsertFill(metaObject, "updatedAt", LocalDateTime.class, LocalDateTime.now(BEIJING_ZONE));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateFill(MetaObject metaObject) {
|
||||
this.strictUpdateFill(metaObject, "updatedAt", LocalDateTime.class, LocalDateTime.now());
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,28 @@
|
||||
package net.lab1024.sa.admin.config;
|
||||
|
||||
import net.lab1024.sa.base.module.support.operatelog.core.OperateLogAspect;
|
||||
import net.lab1024.sa.base.module.support.operatelog.core.OperateLogConfig;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* 操作日志切面 配置
|
||||
*
|
||||
* @Author 1024创新实验室: 罗伊
|
||||
* @Date 2022-05-30 21:22:12
|
||||
* @Wechat zhuoda1024
|
||||
* @Email lab1024@163.com
|
||||
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>
|
||||
*/
|
||||
@Configuration
|
||||
public class OperateLogAspectConfig extends OperateLogAspect{
|
||||
|
||||
/**
|
||||
* 配置信息
|
||||
*/
|
||||
@Override
|
||||
public OperateLogConfig getOperateLogConfig() {
|
||||
return OperateLogConfig.builder().corePoolSize(1).queueCapacity(10000).build();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,25 @@
|
||||
package net.lab1024.sa.admin.config;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Data
|
||||
@Component
|
||||
public class OssConfig {
|
||||
|
||||
@Value("${file.storage.cloud.endpoint}")
|
||||
private String endpoint;
|
||||
|
||||
@Value("${file.storage.cloud.access-key}")
|
||||
private String accessKey;
|
||||
|
||||
@Value("${file.storage.cloud.secret-key}")
|
||||
private String accessKeySecret;
|
||||
|
||||
@Value("${file.storage.cloud.bucket-name}")
|
||||
private String bucket;
|
||||
|
||||
@Value("${file.storage.cloud.url-prefix}")
|
||||
private String customDomainName;
|
||||
}
|
||||
@ -0,0 +1,73 @@
|
||||
package net.lab1024.sa.admin.config;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||
import org.springframework.data.redis.connection.RedisPassword;
|
||||
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
|
||||
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.data.redis.serializer.StringRedisSerializer;
|
||||
|
||||
|
||||
@Configuration
|
||||
@RequiredArgsConstructor
|
||||
public class RedisConfiguration {
|
||||
// 开发环境Redis配置
|
||||
@Value("${spring.data.redis.database:0}")
|
||||
private String database;
|
||||
|
||||
@Value("${spring.data.redis.host:localhost}")
|
||||
private String host;
|
||||
|
||||
@Value("${spring.data.redis.port:6379}")
|
||||
private Integer port;
|
||||
|
||||
@Value("${spring.data.redis.password:}")
|
||||
private String password;
|
||||
|
||||
// 生产环境Redis配置(如果没有配置,使用开发环境配置)
|
||||
@Value("${spring.data.prod-redis.host:${spring.data.redis.host:localhost}}")
|
||||
private String prodHost;
|
||||
|
||||
@Value("${spring.data.prod-redis.port:${spring.data.redis.port:6379}}")
|
||||
private Integer prodPort;
|
||||
|
||||
@Value("${spring.data.prod-redis.database:${spring.data.redis.database:0}}")
|
||||
private String prodDatabase;
|
||||
|
||||
@Value("${spring.data.prod-redis.password:${spring.data.redis.password:}}")
|
||||
private String prodPassword;
|
||||
|
||||
// 移除redisTemplate的定义,使用框架自带的
|
||||
|
||||
@Bean
|
||||
@Qualifier("prodRedisTemplate")
|
||||
public RedisTemplate<String, Object> prodRedisTemplate(RedisConnectionFactory connectionFactory) {
|
||||
RedisStandaloneConfiguration configuration = new RedisStandaloneConfiguration();
|
||||
configuration.setHostName(prodHost);
|
||||
configuration.setPort(prodPort);
|
||||
configuration.setDatabase(Integer.parseInt(prodDatabase));
|
||||
if (prodPassword != null && !prodPassword.isEmpty()) {
|
||||
configuration.setPassword(RedisPassword.of(prodPassword));
|
||||
}
|
||||
|
||||
LettuceConnectionFactory factory = new LettuceConnectionFactory(configuration);
|
||||
factory.afterPropertiesSet();
|
||||
|
||||
RedisTemplate<String, Object> template = new RedisTemplate<>();
|
||||
template.setConnectionFactory(factory);
|
||||
|
||||
// 使用String序列化方式
|
||||
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
|
||||
template.setKeySerializer(stringRedisSerializer);
|
||||
template.setValueSerializer(stringRedisSerializer);
|
||||
template.setHashKeySerializer(stringRedisSerializer);
|
||||
template.setHashValueSerializer(stringRedisSerializer);
|
||||
|
||||
return template;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,16 @@
|
||||
package net.lab1024.sa.admin.config;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Data
|
||||
@Component
|
||||
public class WxMaConfig {
|
||||
|
||||
@Value("${wechat.miniapp.appid}")
|
||||
private String appid;
|
||||
|
||||
@Value("${wechat.miniapp.secret}")
|
||||
private String secret;
|
||||
}
|
||||
@ -0,0 +1,68 @@
|
||||
package net.lab1024.sa.admin.constant;
|
||||
|
||||
import net.lab1024.sa.base.constant.CacheKeyConst;
|
||||
|
||||
/**
|
||||
* 缓存 key
|
||||
*
|
||||
* @Author 1024创新实验室-主任:卓大
|
||||
* @Date 2022-01-07 18:59:22
|
||||
* @Wechat zhuoda1024
|
||||
* @Email lab1024@163.com
|
||||
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>
|
||||
*/
|
||||
public class AdminCacheConst extends CacheKeyConst {
|
||||
|
||||
public static class Department {
|
||||
|
||||
/**
|
||||
* 部门列表
|
||||
*/
|
||||
public static final String DEPARTMENT_LIST_CACHE = "department_list_cache";
|
||||
|
||||
/**
|
||||
* 部门树
|
||||
*/
|
||||
public static final String DEPARTMENT_TREE_CACHE = "department_tree_cache";
|
||||
|
||||
/**
|
||||
* 某个部门以及下级的id列表
|
||||
*/
|
||||
public static final String DEPARTMENT_SELF_CHILDREN_CACHE = "department_self_children_cache";
|
||||
|
||||
/**
|
||||
* 部门路径 缓存
|
||||
*/
|
||||
public static final String DEPARTMENT_PATH_CACHE = "department_path_cache";
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 分类相关缓存
|
||||
*/
|
||||
public static class Category {
|
||||
|
||||
public static final String CATEGORY_ENTITY = "category_cache";
|
||||
|
||||
public static final String CATEGORY_SUB = "category_sub_cache";
|
||||
|
||||
public static final String CATEGORY_TREE = "category_tree_cache";
|
||||
}
|
||||
|
||||
/**
|
||||
* 登录相关
|
||||
*/
|
||||
public static class Login {
|
||||
|
||||
/**
|
||||
* 请求用户信息
|
||||
*/
|
||||
public static final String REQUEST_EMPLOYEE = "login_request_employee";
|
||||
|
||||
/**
|
||||
* 请求用户信息权限
|
||||
*/
|
||||
public static final String USER_PERMISSION = "login_user_permission";
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,17 @@
|
||||
package net.lab1024.sa.admin.constant;
|
||||
|
||||
import net.lab1024.sa.base.constant.RedisKeyConst;
|
||||
|
||||
/**
|
||||
* redis key 常量类
|
||||
*
|
||||
* @Author 1024创新实验室-主任:卓大
|
||||
* @Date 2022-01-07 18:59:22
|
||||
* @Wechat zhuoda1024
|
||||
* @Email lab1024@163.com
|
||||
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>
|
||||
*/
|
||||
public class AdminRedisKeyConst extends RedisKeyConst {
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,59 @@
|
||||
package net.lab1024.sa.admin.constant;
|
||||
|
||||
import net.lab1024.sa.base.constant.SwaggerTagConst;
|
||||
|
||||
/**
|
||||
* swagger
|
||||
*
|
||||
* @Author 1024创新实验室:罗伊
|
||||
* @Date 2022-01-07 18:59:22
|
||||
* @Wechat zhuoda1024
|
||||
* @Email lab1024@163.com
|
||||
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>
|
||||
*/
|
||||
public class AdminSwaggerTagConst extends SwaggerTagConst {
|
||||
|
||||
public static class Business {
|
||||
public static final String MANAGER_CATEGORY = "ERP进销存-分类管理";
|
||||
|
||||
public static final String MANAGER_GOODS = "ERP进销存-商品管理";
|
||||
|
||||
public static final String OA_BANK = "OA办公-银行卡信息";
|
||||
|
||||
public static final String OA_ENTERPRISE = "OA办公-企业";
|
||||
|
||||
public static final String OA_INVOICE = "OA办公-发票信息";
|
||||
|
||||
public static final String OA_NOTICE = "OA办公-通知公告";
|
||||
|
||||
}
|
||||
|
||||
|
||||
public static class System {
|
||||
|
||||
public static final String SYSTEM_LOGIN = "系统-员工登录";
|
||||
|
||||
public static final String SYSTEM_EMPLOYEE = "系统-员工管理";
|
||||
|
||||
public static final String SYSTEM_DEPARTMENT = "系统-部门管理";
|
||||
|
||||
public static final String SYSTEM_MENU = "系统-菜单";
|
||||
|
||||
public static final String SYSTEM_DATA_SCOPE = "系统-系统-数据范围";
|
||||
|
||||
public static final String SYSTEM_ROLE = "系统-角色";
|
||||
|
||||
public static final String SYSTEM_ROLE_DATA_SCOPE = "系统-角色-数据范围";
|
||||
|
||||
public static final String SYSTEM_ROLE_EMPLOYEE = "系统-角色-员工";
|
||||
|
||||
public static final String SYSTEM_ROLE_MENU = "系统-角色-菜单";
|
||||
|
||||
public static final String SYSTEM_POSITION = "系统-职务管理";
|
||||
|
||||
public static final String SYSTEM_MESSAGE = "系统-消息";
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,77 @@
|
||||
package net.lab1024.sa.admin.extend.aliyun;
|
||||
|
||||
import com.aliyun.dysmsapi20170525.Client;
|
||||
import com.aliyun.dysmsapi20170525.models.SendSmsRequest;
|
||||
import com.aliyun.dysmsapi20170525.models.SendSmsResponse;
|
||||
import com.aliyun.tea.TeaException;
|
||||
import com.aliyun.teaopenapi.models.Config;
|
||||
import com.aliyun.teautil.models.RuntimeOptions;
|
||||
import net.lab1024.sa.admin.config.DySmsConfig;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
public class DySms {
|
||||
@Resource
|
||||
private DySmsConfig dySmsConfig;
|
||||
|
||||
private static final String endpoint = "dysmsapi.aliyuncs.com";
|
||||
private static final String signName = "肝胆相照";
|
||||
|
||||
/**
|
||||
* 创建短信客户端
|
||||
*/
|
||||
private Client createClient() throws Exception {
|
||||
Config config = new Config()
|
||||
.setAccessKeyId(dySmsConfig.getAccessKey())
|
||||
.setAccessKeySecret(dySmsConfig.getAccessSecret())
|
||||
.setEndpoint(endpoint);
|
||||
return new Client(config);
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送短信
|
||||
*
|
||||
* @param phoneNumber 手机号
|
||||
* @param templateCode 模板CODE
|
||||
* @param sceneDesc 场景说明,用于日志或调试
|
||||
* @param templateParam 模板参数
|
||||
*/
|
||||
public void sendSms(String phoneNumber, String templateCode, String sceneDesc, Map<String, Object> templateParam) {
|
||||
try {
|
||||
Client client = createClient();
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
String paramJson = objectMapper.writeValueAsString(templateParam);
|
||||
|
||||
SendSmsRequest request = new SendSmsRequest()
|
||||
.setPhoneNumbers(phoneNumber)
|
||||
.setSignName(signName)
|
||||
.setTemplateCode(templateCode)
|
||||
.setTemplateParam(paramJson);
|
||||
|
||||
// 只用标准的RuntimeOptions,不加任何自定义字段
|
||||
RuntimeOptions runtime = new RuntimeOptions();
|
||||
|
||||
SendSmsResponse response = client.sendSmsWithOptions(request, runtime);
|
||||
|
||||
if (response.getBody() == null || !"OK".equals(response.getBody().getCode())) {
|
||||
log.error("短信发送失败,手机号:{},场景:{},返回信息:{}", phoneNumber, sceneDesc, response.getBody() != null ? response.getBody().getMessage() : "无返回体");
|
||||
throw new RuntimeException("短信发送失败: " + (response.getBody() != null ? response.getBody().getMessage() : "无返回体"));
|
||||
} else {
|
||||
log.info("短信发送成功,手机号:{},场景:{},返回信息:{}", phoneNumber, sceneDesc, response.getBody().getMessage());
|
||||
}
|
||||
|
||||
} catch (TeaException e) {
|
||||
log.error("阿里云短信发送异常,手机号:{},场景:{},错误信息:{}", phoneNumber, sceneDesc, e.getMessage(), e);
|
||||
throw new RuntimeException("阿里云短信发送异常", e);
|
||||
} catch (Exception e) {
|
||||
log.error("短信发送异常,手机号:{},场景:{},错误信息:{}", phoneNumber, sceneDesc, e.getMessage(), e);
|
||||
throw new RuntimeException("短信发送异常", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1 @@
|
||||
// 此文件已移动到 config 目录,请使用 net.lab1024.sa.admin.config.DySmsConfig
|
||||
@ -0,0 +1,116 @@
|
||||
package net.lab1024.sa.admin.extend.aliyun;
|
||||
|
||||
import com.aliyun.oss.OSS;
|
||||
import com.aliyun.oss.OSSClientBuilder;
|
||||
import com.aliyun.oss.model.OSSObject;
|
||||
import com.aliyun.oss.model.ObjectMetadata;
|
||||
import com.aliyun.oss.model.PutObjectRequest;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.lab1024.sa.admin.config.OssConfig;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
public class Oss {
|
||||
private static OssConfig ossConfig;
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(Oss.class);
|
||||
|
||||
public Oss(OssConfig ossConfig) {
|
||||
Oss.ossConfig = ossConfig;
|
||||
}
|
||||
|
||||
public static OSS createClient() {
|
||||
return new OSSClientBuilder().build(ossConfig.getEndpoint(), ossConfig.getAccessKey(), ossConfig.getAccessKeySecret());
|
||||
}
|
||||
|
||||
public static boolean putObject(String fileName, byte[] content) {
|
||||
if (content == null || content.length == 0) {
|
||||
logger.warn("Failed to upload object to OSS: content is null or empty, fileName={}", fileName);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (fileName == null || fileName.trim().isEmpty()) {
|
||||
logger.warn("Failed to upload object to OSS: fileName is null or empty");
|
||||
return false;
|
||||
}
|
||||
|
||||
OSS client = createClient();
|
||||
ByteArrayInputStream inputStream = new ByteArrayInputStream(content);
|
||||
|
||||
try {
|
||||
// 推断 Content-Type
|
||||
String contentType = determineContentType(fileName);
|
||||
|
||||
// 创建对象元数据
|
||||
ObjectMetadata metadata = new ObjectMetadata();
|
||||
metadata.setContentLength(content.length);
|
||||
metadata.setContentType(contentType);
|
||||
|
||||
// 执行上传
|
||||
PutObjectRequest request = new PutObjectRequest(ossConfig.getBucket(), fileName, inputStream, metadata);
|
||||
client.putObject(request);
|
||||
|
||||
logger.info("Successfully uploaded object to OSS: bucket={}, fileName={}, size={} bytes",
|
||||
ossConfig.getBucket(), fileName, content.length);
|
||||
return true;
|
||||
|
||||
} catch (Exception e) {
|
||||
logger.error("Failed to upload object to OSS. fileName={}, error={}", fileName, e.getMessage(), e);
|
||||
return false;
|
||||
} finally {
|
||||
try {
|
||||
inputStream.close(); // 可以不关(ByteArrayInputStream 空操作),但建议写上
|
||||
} catch (IOException ignored) { }
|
||||
client.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
private static String determineContentType(String fileName) {
|
||||
if (fileName == null) return "application/octet-stream";
|
||||
|
||||
int lastDotIndex = fileName.lastIndexOf('.');
|
||||
if (lastDotIndex < 0) {
|
||||
return "application/octet-stream";
|
||||
}
|
||||
|
||||
String ext = fileName.substring(lastDotIndex + 1).toLowerCase();
|
||||
|
||||
return switch (ext) {
|
||||
case "jpg", "jpeg" -> "image/jpeg";
|
||||
case "png" -> "image/png";
|
||||
case "gif" -> "image/gif";
|
||||
case "bmp" -> "image/bmp";
|
||||
case "webp" -> "image/webp";
|
||||
case "pdf" -> "application/pdf";
|
||||
case "txt" -> "text/plain";
|
||||
case "html", "htm" -> "text/html";
|
||||
case "xml" -> "application/xml";
|
||||
case "json" -> "application/json";
|
||||
case "mp4" -> "video/mp4";
|
||||
case "avi" -> "video/x-msvideo";
|
||||
case "mp3" -> "audio/mpeg";
|
||||
default -> "application/octet-stream";
|
||||
};
|
||||
}
|
||||
|
||||
// 下载文件为 byte[]
|
||||
public static byte[] getObjectToByte(String fileName) {
|
||||
OSS client = createClient();
|
||||
try (OSSObject ossObject = client.getObject(ossConfig.getBucket(), fileName);
|
||||
InputStream content = ossObject.getObjectContent()) {
|
||||
return content.readAllBytes();
|
||||
} catch (Exception e) {
|
||||
log.error("OSS 下载失败: fileName={}, error={}", fileName, e.getMessage(), e);
|
||||
return null;
|
||||
} finally {
|
||||
client.shutdown();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1 @@
|
||||
// 此文件已移动到 config 目录,请使用 net.lab1024.sa.admin.config.OssConfig
|
||||
@ -0,0 +1 @@
|
||||
// 此文件已移动到 config 目录,请使用 net.lab1024.sa.admin.config.AppConfig
|
||||
164
sa-admin/src/main/java/net/lab1024/sa/admin/extend/app/Base.java
Normal file
164
sa-admin/src/main/java/net/lab1024/sa/admin/extend/app/Base.java
Normal file
@ -0,0 +1,164 @@
|
||||
package net.lab1024.sa.admin.extend.app;
|
||||
|
||||
import cn.hutool.http.HttpRequest;
|
||||
import cn.hutool.http.HttpResponse;
|
||||
import net.lab1024.sa.base.common.exception.BusinessException;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import javax.crypto.Mac;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
@Slf4j
|
||||
public class Base {
|
||||
private static final ObjectMapper objectMapper = new ObjectMapper();
|
||||
|
||||
/**
|
||||
* 生成签名
|
||||
* @param params 需要签名的参数(支持嵌套 Map)
|
||||
* @param secretKey 密钥
|
||||
* @return 签名字符串
|
||||
*/
|
||||
public static String genSignature(Map<String, Object> params, String secretKey) {
|
||||
try {
|
||||
// Step 1: 对 Map 进行递归排序
|
||||
Map<String, Object> sortedMap = sortMapRecursively(params);
|
||||
|
||||
// Step 2: 转为 JSON 字符串
|
||||
String json = objectMapper.writeValueAsString(sortedMap);
|
||||
|
||||
// Step 3: 使用 HMAC-SHA256 签名
|
||||
return hmacSha256(json, secretKey);
|
||||
} catch (JsonProcessingException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 对 Map<String, Object> 进行递归排序(key 排序),支持嵌套 Map 和 List
|
||||
*/
|
||||
public static Map<String, Object> sortMapRecursively(Map<String, Object> data) {
|
||||
Map<String, Object> sortedMap = new TreeMap<>(); // TreeMap 会自动按 key 排序
|
||||
|
||||
for (Map.Entry<String, Object> entry : data.entrySet()) {
|
||||
String key = entry.getKey();
|
||||
Object value = entry.getValue();
|
||||
|
||||
if (value instanceof Map) {
|
||||
// 如果是嵌套 map,递归排序
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Object> nestedMap = (Map<String, Object>) value;
|
||||
sortedMap.put(key, sortMapRecursively(nestedMap));
|
||||
} else if (value instanceof List) {
|
||||
// 如果是列表,检查每一项是否是 map,如果是则排序
|
||||
@SuppressWarnings("unchecked")
|
||||
List<Object> list = (List<Object>) value;
|
||||
List<Object> sortedList = new ArrayList<>();
|
||||
for (Object item : list) {
|
||||
if (item instanceof Map) {
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Object> nestedItemMap = (Map<String, Object>) item;
|
||||
sortedList.add(sortMapRecursively(nestedItemMap));
|
||||
} else {
|
||||
sortedList.add(item);
|
||||
}
|
||||
}
|
||||
sortedMap.put(key, sortedList);
|
||||
} else {
|
||||
// 普通字段,直接插入
|
||||
sortedMap.put(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
return sortedMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* HMAC-SHA256 加密
|
||||
*/
|
||||
private static String hmacSha256(String data, String key) {
|
||||
try {
|
||||
Mac sha256_HMAC = Mac.getInstance("HmacSHA256");
|
||||
SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "HmacSHA256");
|
||||
sha256_HMAC.init(secretKeySpec);
|
||||
byte[] result = sha256_HMAC.doFinal(data.getBytes(StandardCharsets.UTF_8));
|
||||
|
||||
// 转为 16 进制字符串
|
||||
StringBuilder hexString = new StringBuilder();
|
||||
for (byte b : result) {
|
||||
String hex = Integer.toHexString(0xff & b);
|
||||
if (hex.length() == 1) hexString.append('0');
|
||||
hexString.append(hex);
|
||||
}
|
||||
return hexString.toString();
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送 POST JSON 请求
|
||||
* @param url 请求地址
|
||||
* @param jsonData JSON 字符串
|
||||
* @param headers 请求头
|
||||
* @return 响应字符串
|
||||
*/
|
||||
public String postJson(String url, String jsonData, Map<String, String> headers) {
|
||||
HttpRequest request = HttpRequest.post(url)
|
||||
.body(jsonData)
|
||||
.header("Content-Type", "application/json");
|
||||
|
||||
if (headers != null) {
|
||||
headers.forEach(request::header);
|
||||
}
|
||||
|
||||
try (HttpResponse response = request.execute()) {
|
||||
return response.body();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验签名(使用已反序列化的 dto 对象)
|
||||
* @param request HttpServletRequest(用于获取 appId 和 sign)
|
||||
* @param secretKey 签名用的密钥
|
||||
* @param dto 请求对象(如 addClinicalVideoApp)
|
||||
* @param mapper ObjectMapper 实例(用于序列化 dto)
|
||||
*/
|
||||
public void checkSign(HttpServletRequest request, String secretKey, Object dto, ObjectMapper mapper) {
|
||||
try {
|
||||
String appId = request.getHeader("appId");
|
||||
String sign = request.getHeader("sign");
|
||||
|
||||
if (appId == null || appId.isEmpty()) {
|
||||
throw new BusinessException("请求未授权(缺少 appId)");
|
||||
}
|
||||
if (sign == null || sign.isEmpty()) {
|
||||
throw new BusinessException("缺少签名");
|
||||
}
|
||||
|
||||
// 转换 dto 为 Map<String, Object> 用于签名生成
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Object> params = mapper.convertValue(dto, Map.class);
|
||||
|
||||
// 生成签名
|
||||
String serverSign = genSignature(params, secretKey);
|
||||
System.out.println("客户端签名: " + sign);
|
||||
System.out.println("服务端签名: " + serverSign);
|
||||
|
||||
if (!sign.equals(serverSign)) {
|
||||
throw new BusinessException("签名错误");
|
||||
}
|
||||
} catch (BusinessException e) {
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
throw new BusinessException("签名校验失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,48 @@
|
||||
package net.lab1024.sa.admin.extend.app.Hospital;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class GetHospitalByUuidResponse
|
||||
{
|
||||
/** 接口调用状态。200:正常;其它值:调用出错 */
|
||||
private int code;
|
||||
|
||||
/** 结果说明。如果接口调用出错,那么返回错误描述。成功则返回 ok */
|
||||
private String msg;
|
||||
|
||||
/** 接口返回的用户信息数据 */
|
||||
private GetHospitalByUuidData data;
|
||||
|
||||
/** 接口是否调用成功 */
|
||||
private boolean success;
|
||||
|
||||
/** 错误信息或提示信息 */
|
||||
private String message;
|
||||
|
||||
|
||||
/**
|
||||
* - 详细数据
|
||||
*/
|
||||
@Data
|
||||
public static class GetHospitalByUuidData {
|
||||
|
||||
/** 医院唯一标识 */
|
||||
private String uuid;
|
||||
|
||||
/** 科室 */
|
||||
private String name;
|
||||
|
||||
/** 等级 */
|
||||
private String level;
|
||||
|
||||
/** 省份 */
|
||||
private String prov_name;
|
||||
|
||||
/** 城市 */
|
||||
private String city_name;
|
||||
|
||||
/** 医生数量 */
|
||||
private Integer expert_num;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,68 @@
|
||||
package net.lab1024.sa.admin.extend.app.Hospital;
|
||||
|
||||
import cn.hutool.http.HttpRequest;
|
||||
import cn.hutool.http.HttpResponse;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import net.lab1024.sa.admin.config.AppConfig;
|
||||
import net.lab1024.sa.base.common.exception.BusinessException;
|
||||
import net.lab1024.sa.admin.extend.app.Base;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
public class Hospital extends Base {
|
||||
@Resource
|
||||
private AppConfig appConfig;
|
||||
|
||||
// 根据医院唯一标识获取医院数据
|
||||
public GetHospitalByUuidResponse getHospitalByUuid(String hospitalIden) throws BusinessException {
|
||||
String timestamp = String.valueOf(System.currentTimeMillis() / 1000);
|
||||
|
||||
// 处理参数
|
||||
Map<String, Object> requestData = new HashMap<>();
|
||||
requestData.put("hospital_uuid", hospitalIden);
|
||||
requestData.put("platform", appConfig.getPlatform());
|
||||
requestData.put("timestamp", timestamp);
|
||||
|
||||
// 生成签名
|
||||
String sign = genSignature(requestData,appConfig.getSecretKey());
|
||||
|
||||
String url = appConfig.getApiUrl() + "/expert-api/getHospitalByUuid";
|
||||
String jsonBody = JSONUtil.toJsonStr(requestData);
|
||||
log.info("获取app数据参数:{}",jsonBody);
|
||||
|
||||
try(HttpResponse response = HttpRequest.post(url)
|
||||
.header("Content-Type", "application/json")
|
||||
.header("sign", sign)
|
||||
.body(jsonBody)
|
||||
.execute()){
|
||||
|
||||
if (response.getStatus() != 200) {
|
||||
throw new BusinessException("失败");
|
||||
}
|
||||
|
||||
// 反序列化 JSON
|
||||
GetHospitalByUuidResponse result = JSONUtil.toBean(response.body(), GetHospitalByUuidResponse.class);
|
||||
log.info("获取app数据返回:{}",result);
|
||||
if (result.getCode() != 200){
|
||||
if (!Objects.equals(result.getMsg(), "")){
|
||||
throw new BusinessException(result.getMsg());
|
||||
}else{
|
||||
throw new BusinessException("失败");
|
||||
}
|
||||
}
|
||||
|
||||
if (result.getData() == null){
|
||||
throw new BusinessException("失败");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,66 @@
|
||||
package net.lab1024.sa.admin.extend.app.Reward;
|
||||
|
||||
import cn.hutool.http.HttpRequest;
|
||||
import cn.hutool.http.HttpResponse;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import net.lab1024.sa.admin.config.AppConfig;
|
||||
import net.lab1024.sa.base.common.exception.BusinessException;
|
||||
import net.lab1024.sa.admin.extend.app.Base;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
public class Reward extends Base {
|
||||
@Resource
|
||||
private AppConfig appConfig;
|
||||
|
||||
// 打赏积分
|
||||
public RewardResponse RewardPoint(String userUuid,Integer point,String authorUuid) throws BusinessException {
|
||||
String timestamp = String.valueOf(System.currentTimeMillis() / 1000);
|
||||
|
||||
// 处理参数
|
||||
Map<String, Object> requestData = new HashMap<>();
|
||||
requestData.put("user_uuid", userUuid);
|
||||
requestData.put("bonusPoints", point);
|
||||
requestData.put("recipients", authorUuid);
|
||||
requestData.put("platform", appConfig.getPlatform());
|
||||
requestData.put("timestamp", timestamp);
|
||||
|
||||
// 生成签名
|
||||
String sign = genSignature(requestData,appConfig.getSecretKey());
|
||||
|
||||
String url = appConfig.getApiUrl() + "/expert-api/admireBonusPoints";
|
||||
String jsonBody = JSONUtil.toJsonStr(requestData);
|
||||
log.info("获取app数据参数:{}",jsonBody);
|
||||
|
||||
try(HttpResponse response = HttpRequest.post(url)
|
||||
.header("Content-Type", "application/json")
|
||||
.header("sign", sign)
|
||||
.body(jsonBody)
|
||||
.execute()){
|
||||
|
||||
if (response.getStatus() != 200) {
|
||||
throw new BusinessException("失败");
|
||||
}
|
||||
|
||||
// 反序列化 JSON
|
||||
RewardResponse result = JSONUtil.toBean(response.body(), RewardResponse.class);
|
||||
log.info("获取app数据返回:{}",result);
|
||||
if (result.getCode() != 200){
|
||||
if (!Objects.equals(result.getMsg(), "")){
|
||||
throw new BusinessException(result.getMsg());
|
||||
}else{
|
||||
throw new BusinessException("失败");
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
package net.lab1024.sa.admin.extend.app.Reward;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class RewardResponse
|
||||
{
|
||||
/** 接口调用状态。200:正常;其它值:调用出错 */
|
||||
private int code;
|
||||
|
||||
/** 结果说明。如果接口调用出错,那么返回错误描述。成功则返回 ok */
|
||||
private String msg;
|
||||
|
||||
/** 接口是否调用成功 */
|
||||
private boolean success;
|
||||
|
||||
/** 错误信息或提示信息 */
|
||||
private String message;
|
||||
|
||||
}
|
||||
@ -0,0 +1,22 @@
|
||||
package net.lab1024.sa.admin.extend.app.Score;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class ReportUserScoreResponse
|
||||
{
|
||||
/** 接口调用状态。200:正常;其它值:调用出错 */
|
||||
private int code;
|
||||
|
||||
/** 结果说明。如果接口调用出错,那么返回错误描述。成功则返回 ok */
|
||||
private String msg;
|
||||
|
||||
/** 接口是否调用成功 */
|
||||
private boolean success;
|
||||
|
||||
/** 错误信息或提示信息 */
|
||||
private String message;
|
||||
|
||||
/** 接口返回的数据 */
|
||||
private Integer data;
|
||||
}
|
||||
@ -0,0 +1,66 @@
|
||||
package net.lab1024.sa.admin.extend.app.Score;
|
||||
|
||||
import cn.hutool.http.HttpRequest;
|
||||
import cn.hutool.http.HttpResponse;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import net.lab1024.sa.admin.config.AppConfig;
|
||||
import net.lab1024.sa.base.common.exception.BusinessException;
|
||||
import net.lab1024.sa.admin.extend.app.Base;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
public class Score extends Base {
|
||||
@Resource
|
||||
private AppConfig appConfig;
|
||||
|
||||
// 上报用户积分
|
||||
public ReportUserScoreResponse ReportUserScore(String uuid,Integer bonuspoints,String bonuspointsNote) throws BusinessException {
|
||||
String timestamp = String.valueOf(System.currentTimeMillis() / 1000);
|
||||
|
||||
// 处理参数
|
||||
Map<String, Object> requestData = new HashMap<>();
|
||||
requestData.put("bonuspoints_note", bonuspointsNote);
|
||||
requestData.put("bonuspoints", bonuspoints);
|
||||
requestData.put("user_uuid", uuid);
|
||||
requestData.put("platform", appConfig.getPlatform());
|
||||
requestData.put("timestamp", timestamp);
|
||||
|
||||
// 生成签名
|
||||
String sign = genSignature(requestData,appConfig.getSecretKey());
|
||||
|
||||
String url = appConfig.getApiUrl() + "/expert-api/addBonusPoints";
|
||||
String jsonBody = JSONUtil.toJsonStr(requestData);
|
||||
log.info("获取app数据参数:{}",jsonBody);
|
||||
|
||||
try(HttpResponse response = HttpRequest.post(url)
|
||||
.header("Content-Type", "application/json")
|
||||
.header("sign", sign)
|
||||
.body(jsonBody)
|
||||
.execute()){
|
||||
|
||||
if (response.getStatus() != 200) {
|
||||
throw new BusinessException("失败");
|
||||
}
|
||||
|
||||
// 反序列化 JSON
|
||||
ReportUserScoreResponse result = JSONUtil.toBean(response.body(), ReportUserScoreResponse.class);
|
||||
log.info("获取app数据返回:{}",result);
|
||||
if (result.getCode() != 200){
|
||||
if (!Objects.equals(result.getMsg(), "")){
|
||||
throw new BusinessException(result.getMsg());
|
||||
}else{
|
||||
throw new BusinessException("失败");
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,56 @@
|
||||
package net.lab1024.sa.admin.extend.app.UserInfo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class GetUserInfoResponse {
|
||||
/** 接口调用状态。200:正常;其它值:调用出错 */
|
||||
private int code;
|
||||
|
||||
/** 结果说明。如果接口调用出错,那么返回错误描述。成功则返回 ok */
|
||||
private String msg;
|
||||
|
||||
/** 接口返回的用户信息数据 */
|
||||
private ResponsData data;
|
||||
|
||||
/** 接口是否调用成功 */
|
||||
private boolean success;
|
||||
|
||||
/** 错误信息或提示信息 */
|
||||
private String message;
|
||||
|
||||
|
||||
@Data
|
||||
public static class ResponsData {
|
||||
|
||||
/** app唯一标识 */
|
||||
private String uuid;
|
||||
|
||||
/** 科室 */
|
||||
private String officeName;
|
||||
|
||||
/** 姓名 */
|
||||
private String realname;
|
||||
|
||||
/** 医院唯一标识 */
|
||||
private String hospitalUuid;
|
||||
|
||||
/** 手机号 */
|
||||
private String mobile;
|
||||
|
||||
/** 头像地址 */
|
||||
private String img_host;
|
||||
|
||||
/** 头像地址 */
|
||||
private String photo;
|
||||
|
||||
/** 创建时间 */
|
||||
private String createDate;
|
||||
|
||||
/** 职称 */
|
||||
private String positionName;
|
||||
|
||||
/** 省份 */
|
||||
private String provName;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,206 @@
|
||||
package net.lab1024.sa.admin.extend.app.UserInfo;
|
||||
|
||||
import cn.hutool.http.HttpRequest;
|
||||
import cn.hutool.http.HttpResponse;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import net.lab1024.sa.admin.extend.app.Base;
|
||||
import net.lab1024.sa.admin.config.AppConfig;
|
||||
import net.lab1024.sa.base.common.exception.BusinessException;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
public class UserInfo extends Base {
|
||||
@Resource
|
||||
private AppConfig appConfig;
|
||||
|
||||
// 根据手机号获取信息V3
|
||||
public GetUserInfoResponse getUserInfoByMobile(String mobile) throws BusinessException {
|
||||
String timestamp = String.valueOf(System.currentTimeMillis() / 1000);
|
||||
|
||||
// 处理参数
|
||||
Map<String, Object> requestData = new HashMap<>();
|
||||
requestData.put("mobile", mobile);
|
||||
requestData.put("platform", appConfig.getPlatform());
|
||||
requestData.put("timestamp", timestamp);
|
||||
|
||||
// 生成签名
|
||||
String sign = genSignature(requestData,appConfig.getSecretKey());
|
||||
|
||||
String url = appConfig.getApiUrl() + "/expert-api/getInfoByMobileV3";
|
||||
String jsonBody = JSONUtil.toJsonStr(requestData);
|
||||
log.info("获取app数据参数:{}",jsonBody);
|
||||
|
||||
try(HttpResponse response = HttpRequest.post(url)
|
||||
.header("Content-Type", "application/json")
|
||||
.header("sign", sign)
|
||||
.body(jsonBody)
|
||||
.execute()){
|
||||
|
||||
if (response.getStatus() != 200) {
|
||||
throw new BusinessException("失败");
|
||||
}
|
||||
|
||||
// 反序列化 JSON
|
||||
GetUserInfoResponse result = JSONUtil.toBean(response.body(), GetUserInfoResponse.class);
|
||||
log.info("获取app数据返回:{}",result);
|
||||
if (result.getCode() != 200){
|
||||
if (!Objects.equals(result.getMsg(), "")){
|
||||
throw new BusinessException(result.getMsg());
|
||||
}else{
|
||||
throw new BusinessException("失败");
|
||||
}
|
||||
}
|
||||
|
||||
if (result.getData() == null){
|
||||
throw new BusinessException("失败");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
// 根据token获取信息V3
|
||||
public GetUserInfoResponse getUserInfoByToken(String appToken) throws BusinessException {
|
||||
String timestamp = String.valueOf(System.currentTimeMillis() / 1000);
|
||||
|
||||
// 处理参数
|
||||
Map<String, Object> requestData = new HashMap<>();
|
||||
requestData.put("token", appToken);
|
||||
requestData.put("platform", appConfig.getPlatform());
|
||||
requestData.put("timestamp", timestamp);
|
||||
|
||||
// 生成签名
|
||||
String sign = genSignature(requestData,appConfig.getSecretKey());
|
||||
|
||||
String url = appConfig.getApiUrl() + "/expert-api/getInfoByToken";
|
||||
String jsonBody = JSONUtil.toJsonStr(requestData);
|
||||
log.info("获取app数据参数:{}",jsonBody);
|
||||
|
||||
try(HttpResponse response = HttpRequest.post(url)
|
||||
.header("Content-Type", "application/json")
|
||||
.header("sign", sign)
|
||||
.body(jsonBody)
|
||||
.execute()){
|
||||
|
||||
if (response.getStatus() != 200) {
|
||||
throw new BusinessException("失败");
|
||||
}
|
||||
|
||||
// 反序列化 JSON
|
||||
GetUserInfoResponse result = JSONUtil.toBean(response.body(), GetUserInfoResponse.class);
|
||||
log.info("获取app数据返回:{}",result);
|
||||
if (result.getCode() != 200){
|
||||
if (!Objects.equals(result.getMsg(), "")){
|
||||
throw new BusinessException(result.getMsg());
|
||||
}else{
|
||||
throw new BusinessException("失败");
|
||||
}
|
||||
}
|
||||
|
||||
if (result.getData() == null){
|
||||
throw new BusinessException("失败");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
// 根据唯一标识获取信息V3
|
||||
public GetUserInfoResponse getUserInfoByUuid(String uuid) throws BusinessException {
|
||||
String timestamp = String.valueOf(System.currentTimeMillis() / 1000);
|
||||
|
||||
// 处理参数
|
||||
Map<String, Object> requestData = new HashMap<>();
|
||||
requestData.put("user_uuid", uuid);
|
||||
requestData.put("platform", appConfig.getPlatform());
|
||||
requestData.put("timestamp", timestamp);
|
||||
|
||||
// 生成签名
|
||||
String sign = genSignature(requestData,appConfig.getSecretKey());
|
||||
|
||||
String url = appConfig.getApiUrl() + "/expert-api/getInfoByUuid";
|
||||
String jsonBody = JSONUtil.toJsonStr(requestData);
|
||||
log.info("获取app数据参数:{}",jsonBody);
|
||||
|
||||
try(HttpResponse response = HttpRequest.post(url)
|
||||
.header("Content-Type", "application/json")
|
||||
.header("sign", sign)
|
||||
.body(jsonBody)
|
||||
.execute()){
|
||||
|
||||
if (response.getStatus() != 200) {
|
||||
throw new BusinessException("失败");
|
||||
}
|
||||
|
||||
// 反序列化 JSON
|
||||
GetUserInfoResponse result = JSONUtil.toBean(response.body(), GetUserInfoResponse.class);
|
||||
log.info("获取app数据返回:{}",result);
|
||||
if (result.getCode() != 200){
|
||||
if (!Objects.equals(result.getMsg(), "")){
|
||||
throw new BusinessException(result.getMsg());
|
||||
}else{
|
||||
throw new BusinessException("失败");
|
||||
}
|
||||
}
|
||||
|
||||
if (result.getData() == null){
|
||||
throw new BusinessException("失败");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
// 根据姓名获取信息
|
||||
public GetUserInfoResponse getUserInfoByName(String doctorName) throws BusinessException {
|
||||
String timestamp = String.valueOf(System.currentTimeMillis() / 1000);
|
||||
|
||||
// 处理参数
|
||||
Map<String, Object> requestData = new HashMap<>();
|
||||
requestData.put("user_name", doctorName);
|
||||
requestData.put("platform", appConfig.getPlatform());
|
||||
requestData.put("timestamp", timestamp);
|
||||
|
||||
// 生成签名
|
||||
String sign = genSignature(requestData,appConfig.getSecretKey());
|
||||
|
||||
String url = appConfig.getApiUrl() + "/expert-api/getInfoByName";
|
||||
String jsonBody = JSONUtil.toJsonStr(requestData);
|
||||
log.info("获取app数据参数:{}",jsonBody);
|
||||
|
||||
try(HttpResponse response = HttpRequest.post(url)
|
||||
.header("Content-Type", "application/json")
|
||||
.header("sign", sign)
|
||||
.body(jsonBody)
|
||||
.execute()){
|
||||
|
||||
if (response.getStatus() != 200) {
|
||||
throw new BusinessException("失败");
|
||||
}
|
||||
|
||||
// 反序列化 JSON
|
||||
GetUserInfoResponse result = JSONUtil.toBean(response.body(), GetUserInfoResponse.class);
|
||||
log.info("获取app数据返回:{}",result);
|
||||
if (result.getCode() != 200){
|
||||
if (!Objects.equals(result.getMsg(), "")){
|
||||
throw new BusinessException(result.getMsg());
|
||||
}else{
|
||||
throw new BusinessException("失败");
|
||||
}
|
||||
}
|
||||
|
||||
if (result.getData() == null){
|
||||
throw new BusinessException("失败");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,64 @@
|
||||
package net.lab1024.sa.admin.extend.app.UserPoint;
|
||||
|
||||
import cn.hutool.http.HttpRequest;
|
||||
import cn.hutool.http.HttpResponse;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import net.lab1024.sa.admin.config.AppConfig;
|
||||
import net.lab1024.sa.base.common.exception.BusinessException;
|
||||
import net.lab1024.sa.admin.extend.app.Base;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
public class UserPoint extends Base {
|
||||
@Resource
|
||||
private AppConfig appConfig;
|
||||
|
||||
// 获取用户积分
|
||||
public UserPointResponse GetUserPoint(String uuid) throws BusinessException {
|
||||
String timestamp = String.valueOf(System.currentTimeMillis() / 1000);
|
||||
|
||||
// 处理参数
|
||||
Map<String, Object> requestData = new HashMap<>();
|
||||
requestData.put("user_uuid", uuid);
|
||||
requestData.put("platform", appConfig.getPlatform());
|
||||
requestData.put("timestamp", timestamp);
|
||||
|
||||
// 生成签名
|
||||
String sign = genSignature(requestData,appConfig.getSecretKey());
|
||||
|
||||
String url = appConfig.getApiUrl() + "/expert-api/getBonusPoints";
|
||||
String jsonBody = JSONUtil.toJsonStr(requestData);
|
||||
log.info("获取app数据参数:{}",jsonBody);
|
||||
|
||||
try(HttpResponse response = HttpRequest.post(url)
|
||||
.header("Content-Type", "application/json")
|
||||
.header("sign", sign)
|
||||
.body(jsonBody)
|
||||
.execute()){
|
||||
|
||||
if (response.getStatus() != 200) {
|
||||
throw new BusinessException("失败");
|
||||
}
|
||||
|
||||
// 反序列化 JSON
|
||||
UserPointResponse result = JSONUtil.toBean(response.body(), UserPointResponse.class);
|
||||
log.info("获取app数据返回:{}",result);
|
||||
if (result.getCode() != 200){
|
||||
if (!Objects.equals(result.getMsg(), "")){
|
||||
throw new BusinessException(result.getMsg());
|
||||
}else{
|
||||
throw new BusinessException("失败");
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,22 @@
|
||||
package net.lab1024.sa.admin.extend.app.UserPoint;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class UserPointResponse
|
||||
{
|
||||
/** 接口调用状态。200:正常;其它值:调用出错 */
|
||||
private int code;
|
||||
|
||||
/** 结果说明。如果接口调用出错,那么返回错误描述。成功则返回 ok */
|
||||
private String msg;
|
||||
|
||||
/** 接口是否调用成功 */
|
||||
private boolean success;
|
||||
|
||||
/** 错误信息或提示信息 */
|
||||
private String message;
|
||||
|
||||
/** 接口返回的数据 */
|
||||
private Integer data;
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
package net.lab1024.sa.admin.extend.app.Video;
|
||||
|
||||
import net.lab1024.sa.admin.extend.app.Base;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
public class Video extends Base {
|
||||
|
||||
}
|
||||
@ -0,0 +1,55 @@
|
||||
package net.lab1024.sa.admin.extend.app.label;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class GetLabelsResponse
|
||||
{
|
||||
/** 接口调用状态。200:正常;其它值:调用出错 */
|
||||
private int code;
|
||||
|
||||
/** 结果说明。如果接口调用出错,那么返回错误描述。成功则返回 ok */
|
||||
private String msg;
|
||||
|
||||
/** 接口返回的用户信息数据 */
|
||||
private List<GetLabelsData> data;
|
||||
|
||||
/** 接口是否调用成功 */
|
||||
private boolean success;
|
||||
|
||||
/** 错误信息或提示信息 */
|
||||
private String message;
|
||||
|
||||
|
||||
/**
|
||||
* 根据统一标签列表 - 详细数据
|
||||
*/
|
||||
@Data
|
||||
public static class GetLabelsData {
|
||||
|
||||
/**
|
||||
* 标签名称
|
||||
*/
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* id
|
||||
*/
|
||||
private String id;
|
||||
|
||||
/**
|
||||
* 子标签数量
|
||||
*/
|
||||
@JsonProperty("children_size")
|
||||
private Integer childrenSize;
|
||||
|
||||
/**
|
||||
* p_id
|
||||
*/
|
||||
@JsonProperty("p_id")
|
||||
private String pId;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,68 @@
|
||||
package net.lab1024.sa.admin.extend.app.label;
|
||||
|
||||
import cn.hutool.http.HttpRequest;
|
||||
import cn.hutool.http.HttpResponse;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import net.lab1024.sa.admin.config.AppConfig;
|
||||
import net.lab1024.sa.base.common.exception.BusinessException;
|
||||
import net.lab1024.sa.admin.extend.app.Base;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
public class Label extends Base {
|
||||
@Resource
|
||||
private AppConfig appConfig;
|
||||
|
||||
// 根据医院唯一标识获取医院数据
|
||||
public GetLabelsResponse getLabels(String p_id) throws BusinessException {
|
||||
String timestamp = String.valueOf(System.currentTimeMillis() / 1000);
|
||||
|
||||
// 处理参数
|
||||
Map<String, Object> requestData = new HashMap<>();
|
||||
requestData.put("p_id", p_id);
|
||||
requestData.put("platform", appConfig.getPlatform());
|
||||
requestData.put("timestamp", timestamp);
|
||||
|
||||
// 生成签名
|
||||
String sign = genSignature(requestData,appConfig.getSecretKey());
|
||||
|
||||
String url = appConfig.getApiUrl() + "/expert-api/getLabels";
|
||||
String jsonBody = JSONUtil.toJsonStr(requestData);
|
||||
log.info("获取app数据参数:{}",jsonBody);
|
||||
|
||||
try(HttpResponse response = HttpRequest.post(url)
|
||||
.header("Content-Type", "application/json")
|
||||
.header("sign", sign)
|
||||
.body(jsonBody)
|
||||
.execute()){
|
||||
|
||||
if (response.getStatus() != 200) {
|
||||
throw new BusinessException("失败");
|
||||
}
|
||||
|
||||
// 反序列化 JSON
|
||||
GetLabelsResponse result = JSONUtil.toBean(response.body(), GetLabelsResponse.class);
|
||||
log.info("获取app数据返回:{}",result);
|
||||
if (result.getCode() != 200){
|
||||
if (!Objects.equals(result.getMsg(), "")){
|
||||
throw new BusinessException(result.getMsg());
|
||||
}else{
|
||||
throw new BusinessException("失败");
|
||||
}
|
||||
}
|
||||
|
||||
if (result.getData() == null){
|
||||
throw new BusinessException("失败");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1 @@
|
||||
// 此文件已移动到 config 目录,请使用 net.lab1024.sa.admin.config.EnvConfig
|
||||
@ -0,0 +1 @@
|
||||
// 此文件已移动到 config 目录,请使用 net.lab1024.sa.admin.config.WxMaConfig
|
||||
@ -0,0 +1,64 @@
|
||||
package net.lab1024.sa.admin.extend.weChat;
|
||||
|
||||
|
||||
import cn.binarywang.wx.miniapp.config.impl.WxMaDefaultConfigImpl;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@Slf4j
|
||||
public class WxMaRedisConfig extends WxMaDefaultConfigImpl {
|
||||
|
||||
private final RedisTemplate<String, Object> redisTemplate;
|
||||
private final RedisTemplate<String, Object> prodRedisTemplate;
|
||||
|
||||
public WxMaRedisConfig(RedisTemplate<String, Object> redisTemplate, RedisTemplate<String, Object> prodRedisTemplate) {
|
||||
this.redisTemplate = redisTemplate;
|
||||
this.prodRedisTemplate = prodRedisTemplate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAccessToken() {
|
||||
String redisKey = "wx:ma:access_token:" + this.getAppid();
|
||||
String token = (String) redisTemplate.opsForValue().get(redisKey);
|
||||
if (token != null) {
|
||||
return token;
|
||||
}
|
||||
|
||||
// 2. 再尝试从 prodRedis 获取
|
||||
token = (String) prodRedisTemplate.opsForValue().get(redisKey);
|
||||
if (token != null) {
|
||||
return token;
|
||||
}
|
||||
|
||||
synchronized (this) {
|
||||
token = (String) redisTemplate.opsForValue().get(redisKey);
|
||||
if (token != null) return token;
|
||||
|
||||
token = (String) prodRedisTemplate.opsForValue().get(redisKey);
|
||||
if (token != null) return token;
|
||||
|
||||
try {
|
||||
String newToken = super.getAccessToken(); // 强制刷新
|
||||
long expireSeconds = this.getExpiresTime() - 200L;
|
||||
|
||||
redisTemplate.opsForValue().set(redisKey, newToken, expireSeconds, TimeUnit.SECONDS);
|
||||
prodRedisTemplate.opsForValue().set(redisKey, newToken, expireSeconds, TimeUnit.SECONDS);
|
||||
return newToken;
|
||||
} catch (Exception e) {
|
||||
log.error("获取access_token失败", e);
|
||||
throw new RuntimeException("获取access_token失败", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateAccessToken(String accessToken, int expiresInSeconds) {
|
||||
String redisKey = "wx:ma:access_token:" + this.getAppid();
|
||||
long expireSeconds = Math.max(expiresInSeconds - 200L, 1L);
|
||||
|
||||
redisTemplate.opsForValue().set(redisKey, accessToken, expireSeconds, TimeUnit.SECONDS);
|
||||
prodRedisTemplate.opsForValue().set(redisKey, accessToken, expireSeconds, TimeUnit.SECONDS);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,43 @@
|
||||
package net.lab1024.sa.admin.extend.weChat;
|
||||
|
||||
import cn.binarywang.wx.miniapp.api.WxMaService;
|
||||
import cn.binarywang.wx.miniapp.api.impl.WxMaServiceImpl;
|
||||
import net.lab1024.sa.admin.config.WxMaConfig;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
|
||||
@Configuration
|
||||
public class WxMaServiceConfig {
|
||||
private final RedisTemplate<String, Object> devRedis;
|
||||
private final RedisTemplate<String, Object> prodRedis;
|
||||
|
||||
@Resource
|
||||
private WxMaConfig wxMaConfig;
|
||||
|
||||
public WxMaServiceConfig(
|
||||
@Qualifier("redisTemplate") RedisTemplate<String, Object> devRedis,
|
||||
@Qualifier("prodRedisTemplate") RedisTemplate<String, Object> prodRedis
|
||||
) {
|
||||
this.devRedis = devRedis;
|
||||
this.prodRedis = prodRedis;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public WxMaService wxMaService() {
|
||||
WxMaRedisConfig redisConfig = new WxMaRedisConfig(devRedis, prodRedis);
|
||||
redisConfig.setAppid(wxMaConfig.getAppid());
|
||||
redisConfig.setSecret(wxMaConfig.getSecret());
|
||||
|
||||
WxMaServiceImpl service = new WxMaServiceImpl();
|
||||
service.setWxMaConfig(redisConfig);
|
||||
return service;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,88 @@
|
||||
package net.lab1024.sa.admin.extend.weChat;
|
||||
|
||||
|
||||
import cn.binarywang.wx.miniapp.api.WxMaQrcodeService;
|
||||
import cn.binarywang.wx.miniapp.api.WxMaService;
|
||||
import cn.binarywang.wx.miniapp.bean.WxMaCodeLineColor;
|
||||
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
|
||||
import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo;
|
||||
import net.lab1024.sa.admin.config.EnvConfig;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import me.chanjar.weixin.common.error.WxErrorException;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class WxMaServiceUtils {
|
||||
private final WxMaService wxMaService;
|
||||
|
||||
@Resource
|
||||
private EnvConfig envConfig;
|
||||
|
||||
/**
|
||||
* 通过 code 换取 session 信息(openid/unionid)
|
||||
*/
|
||||
public WxMaJscode2SessionResult getSessionInfo(String code) {
|
||||
try {
|
||||
return wxMaService.getUserService().getSessionInfo(code);
|
||||
} catch (WxErrorException e) {
|
||||
log.error("获取 session 失败", e);
|
||||
throw new RuntimeException("微信 session 获取失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 解密手机号信息
|
||||
*/
|
||||
public WxMaPhoneNumberInfo getPhoneNumber(String code) {
|
||||
try {
|
||||
return wxMaService.getUserService().getPhoneNumber(code); // 注意:此方法为新版本推荐方法
|
||||
} catch (WxErrorException e) {
|
||||
log.error("获取手机号失败", e);
|
||||
throw new RuntimeException("微信手机号获取失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前 access_token(仅调试或日志用)
|
||||
*/
|
||||
public String getAccessToken() {
|
||||
try {
|
||||
return wxMaService.getAccessToken();
|
||||
} catch (WxErrorException e) {
|
||||
log.error("获取 access_token 失败", e);
|
||||
throw new RuntimeException("获取 access_token 失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取永久小程序码(base64 或保存成文件都可以)
|
||||
* @param scene 场景值(最长32个可见字符,只能是数字、英文、下划线、减号)
|
||||
* @param page 跳转页面路径(如 pages/index/index)
|
||||
* @return 二进制图片数据(image/jpeg)
|
||||
*/
|
||||
public byte[] getUnlimitedQrcode(String scene, String page) {
|
||||
boolean checkPath = false; // 不校验 page 是否存在
|
||||
String envVersion = "release"; // 可选:trial、develop、release
|
||||
if (Objects.equals(envConfig.getActive(), "dev")){
|
||||
envVersion = "trial";
|
||||
}
|
||||
|
||||
int width = 430;
|
||||
boolean autoColor = true;
|
||||
WxMaCodeLineColor lineColor = new WxMaCodeLineColor();
|
||||
boolean isHyaline = true;
|
||||
|
||||
try {
|
||||
WxMaQrcodeService qrcodeService = wxMaService.getQrcodeService();
|
||||
return qrcodeService.createWxaCodeUnlimitBytes(scene,page,checkPath,envVersion,width,autoColor,lineColor,isHyaline);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("获取小程序码失败", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,143 @@
|
||||
package net.lab1024.sa.admin.interceptor;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaIgnore;
|
||||
import cn.dev33.satoken.exception.SaTokenException;
|
||||
import cn.dev33.satoken.stp.StpUtil;
|
||||
import cn.dev33.satoken.strategy.SaAnnotationStrategy;
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.lab1024.sa.admin.module.system.login.domain.RequestEmployee;
|
||||
import net.lab1024.sa.admin.module.system.login.service.LoginService;
|
||||
import net.lab1024.sa.base.common.annoation.NoNeedLogin;
|
||||
import net.lab1024.sa.base.common.code.SystemErrorCode;
|
||||
import net.lab1024.sa.base.common.code.UserErrorCode;
|
||||
import net.lab1024.sa.base.common.domain.ResponseDTO;
|
||||
import net.lab1024.sa.base.common.util.SmartRequestUtil;
|
||||
import net.lab1024.sa.base.common.util.SmartResponseUtil;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.method.HandlerMethod;
|
||||
import org.springframework.web.servlet.HandlerInterceptor;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
* admin 拦截器
|
||||
*
|
||||
* @Author 1024创新实验室-主任:卓大
|
||||
* @Date 2023/7/26 20:20:33
|
||||
* @Wechat zhuoda1024
|
||||
* @Email lab1024@163.com
|
||||
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>,Since 2012
|
||||
*/
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class AdminInterceptor implements HandlerInterceptor {
|
||||
|
||||
@Resource
|
||||
private LoginService loginService;
|
||||
|
||||
@Override
|
||||
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
|
||||
|
||||
// OPTIONS请求直接return
|
||||
if (HttpMethod.OPTIONS.toString().equals(request.getMethod())) {
|
||||
response.setStatus(HttpStatus.NO_CONTENT.value());
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean isHandler = handler instanceof HandlerMethod;
|
||||
if (!isHandler) {
|
||||
return true;
|
||||
}
|
||||
|
||||
try {
|
||||
// --------------- 第一步: 根据token 获取用户 ---------------
|
||||
|
||||
String tokenValue = StpUtil.getTokenValue();
|
||||
String loginId = (String) StpUtil.getLoginIdByToken(tokenValue);
|
||||
RequestEmployee requestEmployee = loginService.getLoginEmployee(loginId, request);
|
||||
|
||||
// --------------- 第二步: 校验 登录 ---------------
|
||||
|
||||
Method method = ((HandlerMethod) handler).getMethod();
|
||||
NoNeedLogin noNeedLogin = ((HandlerMethod) handler).getMethodAnnotation(NoNeedLogin.class);
|
||||
if (noNeedLogin != null) {
|
||||
checkActiveTimeout(requestEmployee);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (requestEmployee == null) {
|
||||
SmartResponseUtil.write(response, ResponseDTO.error(UserErrorCode.LOGIN_STATE_INVALID));
|
||||
return false;
|
||||
}
|
||||
|
||||
// 检测token 活跃频率
|
||||
checkActiveTimeout(requestEmployee);
|
||||
|
||||
|
||||
// --------------- 第三步: 校验 权限 ---------------
|
||||
|
||||
SmartRequestUtil.setRequestUser(requestEmployee);
|
||||
if (SaAnnotationStrategy.instance.isAnnotationPresent.apply(method, SaIgnore.class)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 如果是超级管理员的话,不需要校验权限
|
||||
if (requestEmployee.getAdministratorFlag()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
SaAnnotationStrategy.instance.checkMethodAnnotation.accept(method);
|
||||
|
||||
} catch (SaTokenException e) {
|
||||
/*
|
||||
* sa-token 异常状态码
|
||||
* 具体请看: https://sa-token.cc/doc.html#/fun/exception-code
|
||||
*/
|
||||
int code = e.getCode();
|
||||
if (code == 11041 || code == 11051) {
|
||||
SmartResponseUtil.write(response, ResponseDTO.error(UserErrorCode.NO_PERMISSION));
|
||||
} else if (code == 11016) {
|
||||
SmartResponseUtil.write(response, ResponseDTO.error(UserErrorCode.LOGIN_ACTIVE_TIMEOUT));
|
||||
} else if (code >= 11011 && code <= 11015) {
|
||||
SmartResponseUtil.write(response, ResponseDTO.error(UserErrorCode.LOGIN_STATE_INVALID));
|
||||
} else {
|
||||
SmartResponseUtil.write(response, ResponseDTO.error(UserErrorCode.PARAM_ERROR));
|
||||
}
|
||||
return false;
|
||||
} catch (Throwable e) {
|
||||
SmartResponseUtil.write(response, ResponseDTO.error(SystemErrorCode.SYSTEM_ERROR));
|
||||
log.error(e.getMessage(), e);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 通过验证
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 检测:token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结
|
||||
*/
|
||||
private void checkActiveTimeout(RequestEmployee requestEmployee) {
|
||||
// 用户不在线,也不用检测
|
||||
if (requestEmployee == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
StpUtil.checkActiveTimeout();
|
||||
StpUtil.updateLastActiveToNow();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
|
||||
// 清除上下文
|
||||
SmartRequestUtil.remove();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,53 @@
|
||||
package net.lab1024.sa.admin.module.business.area.controller;
|
||||
|
||||
import net.lab1024.sa.admin.module.business.area.domain.form.AreaQueryForm;
|
||||
import net.lab1024.sa.admin.module.business.area.domain.vo.AreaVO;
|
||||
import net.lab1024.sa.admin.module.business.area.service.AreaService;
|
||||
import net.lab1024.sa.base.common.domain.ResponseDTO;
|
||||
import net.lab1024.sa.base.common.domain.PageResult;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.validation.Valid;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 省市区 Controller
|
||||
*
|
||||
* @Author xing
|
||||
* @Date 2025-08-04 15:00:58
|
||||
* @Copyright gdxz
|
||||
*/
|
||||
|
||||
@RestController
|
||||
@Tag(name = "省市区")
|
||||
public class AreaController {
|
||||
|
||||
@Resource
|
||||
private AreaService areaService;
|
||||
|
||||
@Operation(summary = "分页查询 @author xing")
|
||||
@PostMapping("/area/queryPage")
|
||||
@SaCheckPermission("area:query")
|
||||
public ResponseDTO<PageResult<AreaVO>> queryPage(@RequestBody @Valid AreaQueryForm queryForm) {
|
||||
return ResponseDTO.ok(areaService.queryPage(queryForm));
|
||||
}
|
||||
|
||||
|
||||
@Operation(summary = "获取省份 @author xing")
|
||||
@GetMapping("/area/provList")
|
||||
@SaCheckPermission("area:query")
|
||||
public ResponseDTO<List<AreaVO>> provList() {
|
||||
return ResponseDTO.ok(areaService.provList());
|
||||
}
|
||||
|
||||
@Operation(summary = "获取市区 @author xing")
|
||||
@GetMapping("/area/cityList/{parent}")
|
||||
@SaCheckPermission("area:query")
|
||||
public ResponseDTO<List<AreaVO>> cityList(@PathVariable Long parent) {
|
||||
return ResponseDTO.ok(areaService.cityList(parent));
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,47 @@
|
||||
package net.lab1024.sa.admin.module.business.area.dao;
|
||||
|
||||
import java.util.List;
|
||||
import net.lab1024.sa.admin.module.business.area.domain.entity.AreaEntity;
|
||||
import net.lab1024.sa.admin.module.business.area.domain.form.AreaQueryForm;
|
||||
import net.lab1024.sa.admin.module.business.area.domain.vo.AreaVO;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 省市区 Dao
|
||||
*
|
||||
* @Author xing
|
||||
* @Date 2025-08-04 15:00:58
|
||||
* @Copyright gdxz
|
||||
*/
|
||||
|
||||
@Mapper
|
||||
public interface AreaDao extends BaseMapper<AreaEntity> {
|
||||
|
||||
/**
|
||||
* 分页 查询
|
||||
*
|
||||
* @param page
|
||||
* @param queryForm
|
||||
* @return
|
||||
*/
|
||||
List<AreaVO> queryPage(Page page, @Param("queryForm") AreaQueryForm queryForm);
|
||||
|
||||
/**
|
||||
* 获取省份列表
|
||||
* @return
|
||||
*/
|
||||
@Select("select * from t_area where parent is null")
|
||||
List<AreaVO> provList();
|
||||
|
||||
/**
|
||||
* 获取城市列表
|
||||
* @return
|
||||
*/
|
||||
@Select("select * from t_area where parent = #{parent}")
|
||||
List<AreaVO> cityList(long parent);
|
||||
}
|
||||
@ -0,0 +1,62 @@
|
||||
package net.lab1024.sa.admin.module.business.area.domain.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import java.time.LocalDateTime;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 省市区 实体类
|
||||
*
|
||||
* @Author xing
|
||||
* @Date 2025-08-04 15:00:58
|
||||
* @Copyright gdxz
|
||||
*/
|
||||
|
||||
@Data
|
||||
@TableName("area")
|
||||
public class AreaEntity {
|
||||
|
||||
/**
|
||||
* 主键
|
||||
*/
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private LocalDateTime createDate;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
private LocalDateTime modifyDate;
|
||||
|
||||
/**
|
||||
* 排序
|
||||
*/
|
||||
private Integer orders;
|
||||
|
||||
/**
|
||||
* 全名
|
||||
*/
|
||||
private String fullName;
|
||||
|
||||
/**
|
||||
* 名称
|
||||
*/
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 树路径
|
||||
*/
|
||||
private String treePath;
|
||||
|
||||
/**
|
||||
* 父节点
|
||||
*/
|
||||
private Long parent;
|
||||
|
||||
}
|
||||
@ -0,0 +1,26 @@
|
||||
package net.lab1024.sa.admin.module.business.area.domain.form;
|
||||
|
||||
import net.lab1024.sa.base.common.domain.PageParam;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
/**
|
||||
* 省市区 分页查询表单
|
||||
*
|
||||
* @Author xing
|
||||
* @Date 2025-08-04 15:00:58
|
||||
* @Copyright gdxz
|
||||
*/
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
public class AreaQueryForm extends PageParam {
|
||||
|
||||
@Schema(description = "名称")
|
||||
private String keywords;
|
||||
|
||||
@Schema(description = "上级城市")
|
||||
private Long parent;
|
||||
|
||||
}
|
||||
@ -0,0 +1,43 @@
|
||||
package net.lab1024.sa.admin.module.business.area.domain.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import java.time.LocalDateTime;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 省市区 列表VO
|
||||
*
|
||||
* @Author xing
|
||||
* @Date 2025-08-04 15:00:58
|
||||
* @Copyright gdxz
|
||||
*/
|
||||
|
||||
@Data
|
||||
public class AreaVO {
|
||||
|
||||
|
||||
@Schema(description = "主键")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
private LocalDateTime createDate;
|
||||
|
||||
@Schema(description = "更新时间")
|
||||
private LocalDateTime modifyDate;
|
||||
|
||||
@Schema(description = "排序")
|
||||
private Integer orders;
|
||||
|
||||
@Schema(description = "全名")
|
||||
private String fullName;
|
||||
|
||||
@Schema(description = "名称")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "树路径")
|
||||
private String treePath;
|
||||
|
||||
@Schema(description = "父节点")
|
||||
private Long parent;
|
||||
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
package net.lab1024.sa.admin.module.business.area.manager;
|
||||
|
||||
import net.lab1024.sa.admin.module.business.area.domain.entity.AreaEntity;
|
||||
import net.lab1024.sa.admin.module.business.area.dao.AreaDao;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* 省市区 Manager
|
||||
*
|
||||
* @Author xing
|
||||
* @Date 2025-08-04 15:00:58
|
||||
* @Copyright gdxz
|
||||
*/
|
||||
@Service
|
||||
public class AreaManager extends ServiceImpl<AreaDao, AreaEntity> {
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,49 @@
|
||||
package net.lab1024.sa.admin.module.business.area.service;
|
||||
|
||||
import java.util.List;
|
||||
import net.lab1024.sa.admin.module.business.area.dao.AreaDao;
|
||||
import net.lab1024.sa.admin.module.business.area.domain.entity.AreaEntity;
|
||||
import net.lab1024.sa.admin.module.business.area.domain.form.AreaQueryForm;
|
||||
import net.lab1024.sa.admin.module.business.area.domain.vo.AreaVO;
|
||||
import net.lab1024.sa.base.common.util.SmartBeanUtil;
|
||||
import net.lab1024.sa.base.common.util.SmartPageUtil;
|
||||
import net.lab1024.sa.base.common.domain.ResponseDTO;
|
||||
import net.lab1024.sa.base.common.domain.PageResult;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
|
||||
/**
|
||||
* 省市区 Service
|
||||
*
|
||||
* @Author xing
|
||||
* @Date 2025-08-04 15:00:58
|
||||
* @Copyright gdxz
|
||||
*/
|
||||
|
||||
@Service
|
||||
public class AreaService {
|
||||
|
||||
@Resource
|
||||
private AreaDao areaDao;
|
||||
|
||||
/**
|
||||
* 分页查询
|
||||
*/
|
||||
public PageResult<AreaVO> queryPage(AreaQueryForm queryForm) {
|
||||
Page<?> page = SmartPageUtil.convert2PageQuery(queryForm);
|
||||
List<AreaVO> list = areaDao.queryPage(page, queryForm);
|
||||
return SmartPageUtil.convert2PageResult(page, list);
|
||||
}
|
||||
|
||||
public List<AreaVO> provList() {
|
||||
return areaDao.provList();
|
||||
}
|
||||
|
||||
public List<AreaVO> cityList(Long parent) {
|
||||
return areaDao.cityList(parent);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,48 @@
|
||||
package net.lab1024.sa.admin.module.business.basicHospital.controller;
|
||||
|
||||
import net.lab1024.sa.admin.module.business.basicHospital.domain.form.BasicHospitalQueryForm;
|
||||
import net.lab1024.sa.admin.module.business.basicHospital.domain.form.BasicHospitalQueryListForm;
|
||||
import net.lab1024.sa.admin.module.business.basicHospital.domain.vo.BasicHospitalVO;
|
||||
import net.lab1024.sa.admin.module.business.basicHospital.service.BasicHospitalService;
|
||||
import net.lab1024.sa.base.common.domain.ResponseDTO;
|
||||
import net.lab1024.sa.base.common.domain.PageResult;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.validation.Valid;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 基础数据-医院 Controller
|
||||
*
|
||||
* @Author xing
|
||||
* @Date 2025-08-04 14:06:17
|
||||
* @Copyright gdxz
|
||||
*/
|
||||
|
||||
@RestController
|
||||
@Tag(name = "基础数据-医院")
|
||||
public class BasicHospitalController {
|
||||
|
||||
@Resource
|
||||
private BasicHospitalService basicHospitalService;
|
||||
|
||||
@Operation(summary = "分页查询 @author xing")
|
||||
@PostMapping("/basicHospital/queryPage")
|
||||
@SaCheckPermission("basicHospital:query")
|
||||
public ResponseDTO<PageResult<BasicHospitalVO>> queryPage(@RequestBody @Valid BasicHospitalQueryForm queryForm) {
|
||||
return ResponseDTO.ok(basicHospitalService.queryPage(queryForm));
|
||||
}
|
||||
|
||||
@Operation(summary = "列表查询 @author xing")
|
||||
@PostMapping("/basicHospital/queryList")
|
||||
@SaCheckPermission("basicHospital:list")
|
||||
public ResponseDTO<List<BasicHospitalVO>> queryList(@RequestBody @Valid BasicHospitalQueryListForm queryForm) {
|
||||
return ResponseDTO.ok(basicHospitalService.queryList(queryForm));
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,41 @@
|
||||
package net.lab1024.sa.admin.module.business.basicHospital.dao;
|
||||
|
||||
import java.util.List;
|
||||
import net.lab1024.sa.admin.module.business.basicHospital.domain.entity.BasicHospitalEntity;
|
||||
import net.lab1024.sa.admin.module.business.basicHospital.domain.form.BasicHospitalQueryForm;
|
||||
import net.lab1024.sa.admin.module.business.basicHospital.domain.form.BasicHospitalQueryListForm;
|
||||
import net.lab1024.sa.admin.module.business.basicHospital.domain.vo.BasicHospitalVO;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 基础数据-医院 Dao
|
||||
*
|
||||
* @Author xing
|
||||
* @Date 2025-08-04 14:06:17
|
||||
* @Copyright gdxz
|
||||
*/
|
||||
|
||||
@Mapper
|
||||
public interface BasicHospitalDao extends BaseMapper<BasicHospitalEntity> {
|
||||
|
||||
/**
|
||||
* 分页 查询
|
||||
*
|
||||
* @param page
|
||||
* @param queryForm
|
||||
* @return
|
||||
*/
|
||||
List<BasicHospitalVO> queryPage(Page page, @Param("queryForm") BasicHospitalQueryForm queryForm);
|
||||
|
||||
/**
|
||||
* 列表 查询
|
||||
*
|
||||
* @param queryForm
|
||||
* @return
|
||||
*/
|
||||
List<BasicHospitalVO> queryList(@Param("queryForm") BasicHospitalQueryListForm queryForm);
|
||||
}
|
||||
@ -0,0 +1,81 @@
|
||||
package net.lab1024.sa.admin.module.business.basicHospital.domain.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import java.time.LocalDateTime;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 基础数据-医院 实体类
|
||||
*
|
||||
* @Author xing
|
||||
* @Date 2025-08-04 14:06:17
|
||||
* @Copyright gdxz
|
||||
*/
|
||||
|
||||
@Data
|
||||
@TableName("basic_hospital")
|
||||
public class BasicHospitalEntity {
|
||||
|
||||
/**
|
||||
* 主键id
|
||||
*/
|
||||
@TableId
|
||||
private Long hospitalId;
|
||||
|
||||
/**
|
||||
* app唯一标识
|
||||
*/
|
||||
private String hospitalIden;
|
||||
|
||||
/**
|
||||
* 医院名称
|
||||
*/
|
||||
private String hospitalName;
|
||||
|
||||
/**
|
||||
* 来源(2:肝胆相照 3:佳动例)
|
||||
*/
|
||||
private Integer source;
|
||||
|
||||
/**
|
||||
* 医院等级
|
||||
*/
|
||||
private String hospitalLevel;
|
||||
|
||||
/**
|
||||
* 医生数量
|
||||
*/
|
||||
private Integer doctorNumber;
|
||||
|
||||
/**
|
||||
* 省份
|
||||
*/
|
||||
private String province;
|
||||
|
||||
/**
|
||||
* 城市
|
||||
*/
|
||||
private String city;
|
||||
|
||||
/**
|
||||
* 区县
|
||||
*/
|
||||
private String county;
|
||||
|
||||
/**
|
||||
* 地址
|
||||
*/
|
||||
private String address;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private LocalDateTime createdAt;
|
||||
|
||||
/**
|
||||
* 修改时间
|
||||
*/
|
||||
private LocalDateTime updatedAt;
|
||||
|
||||
}
|
||||
@ -0,0 +1,28 @@
|
||||
package net.lab1024.sa.admin.module.business.basicHospital.domain.form;
|
||||
|
||||
import net.lab1024.sa.base.common.domain.PageParam;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import net.lab1024.sa.base.common.swagger.SchemaEnum;
|
||||
import net.lab1024.sa.base.common.validator.enumeration.CheckEnum;
|
||||
|
||||
/**
|
||||
* 基础数据-医院 分页查询表单
|
||||
*
|
||||
* @Author xing
|
||||
* @Date 2025-08-04 14:06:17
|
||||
* @Copyright gdxz
|
||||
*/
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
public class BasicHospitalQueryForm extends PageParam {
|
||||
|
||||
@Schema(description = "医院名称")
|
||||
private String keywords;
|
||||
|
||||
@Schema(description = "医院等级")
|
||||
private String hospitalLevel;
|
||||
|
||||
}
|
||||
@ -0,0 +1,29 @@
|
||||
package net.lab1024.sa.admin.module.business.basicHospital.domain.form;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import net.lab1024.sa.base.common.domain.PageParam;
|
||||
|
||||
/**
|
||||
* 基础数据-医院 列表查询表单
|
||||
*
|
||||
* @Author xing
|
||||
* @Date 2025-08-04 14:06:17
|
||||
* @Copyright gdxz
|
||||
*/
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
public class BasicHospitalQueryListForm {
|
||||
|
||||
@Schema(description = "医院名称")
|
||||
private String keywords;
|
||||
|
||||
@Schema(description = "医院等级")
|
||||
private String hospitalLevel;
|
||||
|
||||
@Schema(description = "数量")
|
||||
private Integer limit = 10;
|
||||
|
||||
}
|
||||
@ -0,0 +1,55 @@
|
||||
package net.lab1024.sa.admin.module.business.basicHospital.domain.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import java.time.LocalDateTime;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 基础数据-医院 列表VO
|
||||
*
|
||||
* @Author xing
|
||||
* @Date 2025-08-04 14:06:17
|
||||
* @Copyright gdxz
|
||||
*/
|
||||
|
||||
@Data
|
||||
public class BasicHospitalVO {
|
||||
|
||||
|
||||
@Schema(description = "主键id")
|
||||
private Long hospitalId;
|
||||
|
||||
@Schema(description = "app唯一标识")
|
||||
private String hospitalIden;
|
||||
|
||||
@Schema(description = "医院名称")
|
||||
private String hospitalName;
|
||||
|
||||
@Schema(description = "来源(2:肝胆相照 3:佳动例)")
|
||||
private Integer source;
|
||||
|
||||
@Schema(description = "医院等级")
|
||||
private String hospitalLevel;
|
||||
|
||||
@Schema(description = "医生数量")
|
||||
private Integer doctorNumber;
|
||||
|
||||
@Schema(description = "省份")
|
||||
private String province;
|
||||
|
||||
@Schema(description = "城市")
|
||||
private String city;
|
||||
|
||||
@Schema(description = "区县")
|
||||
private String county;
|
||||
|
||||
@Schema(description = "地址")
|
||||
private String address;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
private LocalDateTime createdAt;
|
||||
|
||||
@Schema(description = "修改时间")
|
||||
private LocalDateTime updatedAt;
|
||||
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
package net.lab1024.sa.admin.module.business.basicHospital.manager;
|
||||
|
||||
import net.lab1024.sa.admin.module.business.basicHospital.domain.entity.BasicHospitalEntity;
|
||||
import net.lab1024.sa.admin.module.business.basicHospital.dao.BasicHospitalDao;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* 基础数据-医院 Manager
|
||||
*
|
||||
* @Author xing
|
||||
* @Date 2025-08-04 14:06:17
|
||||
* @Copyright gdxz
|
||||
*/
|
||||
@Service
|
||||
public class BasicHospitalManager extends ServiceImpl<BasicHospitalDao, BasicHospitalEntity> {
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,48 @@
|
||||
package net.lab1024.sa.admin.module.business.basicHospital.service;
|
||||
|
||||
import java.util.List;
|
||||
import net.lab1024.sa.admin.module.business.basicHospital.dao.BasicHospitalDao;
|
||||
import net.lab1024.sa.admin.module.business.basicHospital.domain.entity.BasicHospitalEntity;
|
||||
import net.lab1024.sa.admin.module.business.basicHospital.domain.form.BasicHospitalQueryForm;
|
||||
import net.lab1024.sa.admin.module.business.basicHospital.domain.form.BasicHospitalQueryListForm;
|
||||
import net.lab1024.sa.admin.module.business.basicHospital.domain.vo.BasicHospitalVO;
|
||||
import net.lab1024.sa.base.common.util.SmartBeanUtil;
|
||||
import net.lab1024.sa.base.common.util.SmartPageUtil;
|
||||
import net.lab1024.sa.base.common.domain.ResponseDTO;
|
||||
import net.lab1024.sa.base.common.domain.PageResult;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
|
||||
/**
|
||||
* 基础数据-医院 Service
|
||||
*
|
||||
* @Author xing
|
||||
* @Date 2025-08-04 14:06:17
|
||||
* @Copyright gdxz
|
||||
*/
|
||||
|
||||
@Service
|
||||
public class BasicHospitalService {
|
||||
|
||||
@Resource
|
||||
private BasicHospitalDao basicHospitalDao;
|
||||
|
||||
/**
|
||||
* 分页查询
|
||||
*/
|
||||
public PageResult<BasicHospitalVO> queryPage(BasicHospitalQueryForm queryForm) {
|
||||
Page<?> page = SmartPageUtil.convert2PageQuery(queryForm);
|
||||
List<BasicHospitalVO> list = basicHospitalDao.queryPage(page, queryForm);
|
||||
return SmartPageUtil.convert2PageResult(page, list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 列表查询
|
||||
*/
|
||||
public List<BasicHospitalVO> queryList(BasicHospitalQueryListForm queryForm) {
|
||||
return basicHospitalDao.queryList(queryForm);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,40 @@
|
||||
package net.lab1024.sa.admin.module.business.basicSensitiveWord.controller;
|
||||
|
||||
import net.lab1024.sa.admin.module.business.basicSensitiveWord.domain.form.BasicSensitiveWordQueryForm;
|
||||
import net.lab1024.sa.admin.module.business.basicSensitiveWord.domain.vo.BasicSensitiveWordVO;
|
||||
import net.lab1024.sa.admin.module.business.basicSensitiveWord.service.BasicSensitiveWordService;
|
||||
import net.lab1024.sa.base.common.domain.ResponseDTO;
|
||||
import net.lab1024.sa.base.common.domain.PageResult;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.validation.Valid;
|
||||
|
||||
/**
|
||||
* 基础数据-敏感词 Controller
|
||||
*
|
||||
* @Author xing
|
||||
* @Date 2025-08-11 00:32:07
|
||||
* @Copyright gdxz
|
||||
*/
|
||||
|
||||
@RestController
|
||||
@Tag(name = "基础数据-敏感词")
|
||||
public class BasicSensitiveWordController {
|
||||
|
||||
@Resource
|
||||
private BasicSensitiveWordService basicSensitiveWordService;
|
||||
|
||||
@Operation(summary = "分页查询 @author xing")
|
||||
@PostMapping("/basicSensitiveWord/queryPage")
|
||||
@SaCheckPermission("basicSensitiveWord:query")
|
||||
public ResponseDTO<PageResult<BasicSensitiveWordVO>> queryPage(@RequestBody @Valid BasicSensitiveWordQueryForm queryForm) {
|
||||
return ResponseDTO.ok(basicSensitiveWordService.queryPage(queryForm));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,33 @@
|
||||
package net.lab1024.sa.admin.module.business.basicSensitiveWord.dao;
|
||||
|
||||
import java.util.List;
|
||||
import net.lab1024.sa.admin.module.business.basicSensitiveWord.domain.entity.BasicSensitiveWordEntity;
|
||||
import net.lab1024.sa.admin.module.business.basicSensitiveWord.domain.form.BasicSensitiveWordQueryForm;
|
||||
import net.lab1024.sa.admin.module.business.basicSensitiveWord.domain.vo.BasicSensitiveWordVO;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 基础数据-敏感词 Dao
|
||||
*
|
||||
* @Author xing
|
||||
* @Date 2025-08-11 00:32:07
|
||||
* @Copyright gdxz
|
||||
*/
|
||||
|
||||
@Mapper
|
||||
public interface BasicSensitiveWordDao extends BaseMapper<BasicSensitiveWordEntity> {
|
||||
|
||||
/**
|
||||
* 分页 查询
|
||||
*
|
||||
* @param page
|
||||
* @param queryForm
|
||||
* @return
|
||||
*/
|
||||
List<BasicSensitiveWordVO> queryPage(Page page, @Param("queryForm") BasicSensitiveWordQueryForm queryForm);
|
||||
|
||||
}
|
||||
@ -0,0 +1,41 @@
|
||||
package net.lab1024.sa.admin.module.business.basicSensitiveWord.domain.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import java.time.LocalDateTime;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 基础数据-敏感词 实体类
|
||||
*
|
||||
* @Author xing
|
||||
* @Date 2025-08-11 00:32:07
|
||||
* @Copyright gdxz
|
||||
*/
|
||||
|
||||
@Data
|
||||
@TableName("basic_sensitive_word")
|
||||
public class BasicSensitiveWordEntity {
|
||||
|
||||
/**
|
||||
* 主键id
|
||||
*/
|
||||
@TableId
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 敏感词
|
||||
*/
|
||||
private String word;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private LocalDateTime createdAt;
|
||||
|
||||
/**
|
||||
* 修改时间
|
||||
*/
|
||||
private LocalDateTime updatedAt;
|
||||
|
||||
}
|
||||
@ -0,0 +1,19 @@
|
||||
package net.lab1024.sa.admin.module.business.basicSensitiveWord.domain.form;
|
||||
|
||||
import net.lab1024.sa.base.common.domain.PageParam;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
/**
|
||||
* 基础数据-敏感词 分页查询表单
|
||||
*
|
||||
* @Author xing
|
||||
* @Date 2025-08-11 00:32:07
|
||||
* @Copyright gdxz
|
||||
*/
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
public class BasicSensitiveWordQueryForm extends PageParam {
|
||||
|
||||
}
|
||||
@ -0,0 +1,31 @@
|
||||
package net.lab1024.sa.admin.module.business.basicSensitiveWord.domain.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import java.time.LocalDateTime;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 基础数据-敏感词 列表VO
|
||||
*
|
||||
* @Author xing
|
||||
* @Date 2025-08-11 00:32:07
|
||||
* @Copyright gdxz
|
||||
*/
|
||||
|
||||
@Data
|
||||
public class BasicSensitiveWordVO {
|
||||
|
||||
|
||||
@Schema(description = "主键id")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "敏感词")
|
||||
private String word;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
private LocalDateTime createdAt;
|
||||
|
||||
@Schema(description = "修改时间")
|
||||
private LocalDateTime updatedAt;
|
||||
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
package net.lab1024.sa.admin.module.business.basicSensitiveWord.manager;
|
||||
|
||||
import net.lab1024.sa.admin.module.business.basicSensitiveWord.domain.entity.BasicSensitiveWordEntity;
|
||||
import net.lab1024.sa.admin.module.business.basicSensitiveWord.dao.BasicSensitiveWordDao;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* 基础数据-敏感词 Manager
|
||||
*
|
||||
* @Author xing
|
||||
* @Date 2025-08-11 00:32:07
|
||||
* @Copyright gdxz
|
||||
*/
|
||||
@Service
|
||||
public class BasicSensitiveWordManager extends ServiceImpl<BasicSensitiveWordDao, BasicSensitiveWordEntity> {
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,159 @@
|
||||
package net.lab1024.sa.admin.module.business.basicSensitiveWord.service;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import net.lab1024.sa.admin.module.business.basicSensitiveWord.dao.BasicSensitiveWordDao;
|
||||
import net.lab1024.sa.admin.module.business.basicSensitiveWord.domain.entity.BasicSensitiveWordEntity;
|
||||
import net.lab1024.sa.admin.module.business.basicSensitiveWord.domain.form.BasicSensitiveWordQueryForm;
|
||||
import net.lab1024.sa.admin.module.business.basicSensitiveWord.domain.vo.BasicSensitiveWordVO;
|
||||
import net.lab1024.sa.base.common.util.SmartBeanUtil;
|
||||
import net.lab1024.sa.base.common.util.SmartPageUtil;
|
||||
import net.lab1024.sa.base.common.domain.ResponseDTO;
|
||||
import net.lab1024.sa.base.common.domain.PageResult;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
|
||||
/**
|
||||
* 基础数据-敏感词 Service
|
||||
*
|
||||
* @Author xing
|
||||
* @Date 2025-08-11 00:32:07
|
||||
* @Copyright gdxz
|
||||
*/
|
||||
|
||||
@Service
|
||||
public class BasicSensitiveWordService {
|
||||
|
||||
@Resource
|
||||
private BasicSensitiveWordDao basicSensitiveWordDao;
|
||||
|
||||
@Resource
|
||||
private RedisTemplate<String, String> redisTemplate;
|
||||
|
||||
private final ObjectMapper objectMapper = new ObjectMapper();
|
||||
|
||||
/**
|
||||
* 分页查询
|
||||
*/
|
||||
public PageResult<BasicSensitiveWordVO> queryPage(BasicSensitiveWordQueryForm queryForm) {
|
||||
Page<?> page = SmartPageUtil.convert2PageQuery(queryForm);
|
||||
List<BasicSensitiveWordVO> list = basicSensitiveWordDao.queryPage(page, queryForm);
|
||||
return SmartPageUtil.convert2PageResult(page, list);
|
||||
}
|
||||
|
||||
private static final String REDIS_SENSITIVE_WORD_KEY = "sensitive:word:list";
|
||||
private static final long REDIS_EXPIRE_MINUTES = 30;
|
||||
|
||||
|
||||
|
||||
// 主过滤方法
|
||||
public FilterResult filter(String comment) {
|
||||
List<String> wordList = loadSensitiveWords();
|
||||
if (wordList == null || wordList.isEmpty()) {
|
||||
return new FilterResult(comment, 0);
|
||||
}
|
||||
|
||||
TrieNode root = buildTrie(wordList);
|
||||
return doFilter(comment, root);
|
||||
}
|
||||
|
||||
// 加载敏感词(可替换为数据库查询)
|
||||
private List<String> loadSensitiveWords() {
|
||||
List<String> wordList = new ArrayList<>();
|
||||
|
||||
// 尝试从 Redis 获取
|
||||
String wordJson = redisTemplate.opsForValue().get(REDIS_SENSITIVE_WORD_KEY);
|
||||
if (wordJson != null && !wordJson.isEmpty()) {
|
||||
try {
|
||||
// 反序列化 JSON 字符串为 List<String>
|
||||
wordList = objectMapper.readValue(wordJson, new TypeReference<List<String>>() {});
|
||||
} catch (Exception e) {
|
||||
return wordList;
|
||||
}
|
||||
}else{
|
||||
// Redis 无数据,则查询 DB
|
||||
LambdaQueryWrapper<BasicSensitiveWordEntity> queryWrapper = new LambdaQueryWrapper<>();
|
||||
List<BasicSensitiveWordEntity> basicSensitiveWords = basicSensitiveWordDao.selectList(queryWrapper); // 你自己的 DAO 方法
|
||||
if (basicSensitiveWords != null && !basicSensitiveWords.isEmpty()) {
|
||||
wordList = basicSensitiveWords.stream()
|
||||
.map(BasicSensitiveWordEntity::getWord)
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
try {
|
||||
String wordListJson = objectMapper.writeValueAsString(wordList);
|
||||
redisTemplate.opsForValue().set(REDIS_SENSITIVE_WORD_KEY, wordListJson, Duration.ofMinutes(REDIS_EXPIRE_MINUTES));
|
||||
} catch (Exception e) {
|
||||
return wordList;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return wordList;
|
||||
}
|
||||
|
||||
// 构建字典树
|
||||
private TrieNode buildTrie(List<String> words) {
|
||||
TrieNode root = new TrieNode();
|
||||
for (String word : words) {
|
||||
TrieNode node = root;
|
||||
for (char ch : word.toCharArray()) {
|
||||
node.children.putIfAbsent(ch, new TrieNode());
|
||||
node = node.children.get(ch);
|
||||
}
|
||||
node.isEnd = true;
|
||||
}
|
||||
return root;
|
||||
}
|
||||
|
||||
// 实际过滤逻辑
|
||||
private FilterResult doFilter(String comment, TrieNode root) {
|
||||
char[] chars = comment.toCharArray();
|
||||
int isSensitive = 0;
|
||||
|
||||
for (int i = 0; i < chars.length; i++) {
|
||||
TrieNode node = root;
|
||||
int j = i;
|
||||
while (j < chars.length && node.children.containsKey(chars[j])) {
|
||||
node = node.children.get(chars[j]);
|
||||
if (node.isEnd) {
|
||||
for (int k = i; k <= j; k++) {
|
||||
chars[k] = '*';
|
||||
}
|
||||
isSensitive = 1;
|
||||
break;
|
||||
}
|
||||
j++;
|
||||
}
|
||||
}
|
||||
|
||||
return new FilterResult(new String(chars), isSensitive);
|
||||
}
|
||||
|
||||
// Trie 节点内部类
|
||||
private static class TrieNode {
|
||||
boolean isEnd = false;
|
||||
Map<Character, TrieNode> children = new HashMap<>();
|
||||
}
|
||||
|
||||
// 返回结果封装
|
||||
public static class FilterResult {
|
||||
public final String comment;
|
||||
public final int hasSensitive;
|
||||
|
||||
public FilterResult(String comment, int hasSensitive) {
|
||||
this.comment = comment;
|
||||
this.hasSensitive = hasSensitive;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,245 @@
|
||||
package net.lab1024.sa.admin.module.business.caseClinical.service;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import net.lab1024.sa.admin.module.business.caseClinicalVideo.dao.CaseClinicalVideoDao;
|
||||
import net.lab1024.sa.admin.module.business.statsCaseClinical.dao.StatsCaseClinicalDao;
|
||||
import jakarta.annotation.Resource;
|
||||
import net.lab1024.sa.admin.module.business.caseClinicalArticle.dao.CaseClinicalArticleDao;
|
||||
import net.lab1024.sa.admin.module.business.statsCaseClinical.dao.StatsCaseClinicalDoctorDao;
|
||||
import net.lab1024.sa.admin.module.business.statsCaseClinical.dao.StatsCaseClinicalHospitalDao;
|
||||
import net.lab1024.sa.admin.module.business.statsCaseClinical.dao.StatsCaseClinicalLabelDao;
|
||||
import net.lab1024.sa.admin.module.business.statsCaseClinical.domain.entity.StatsCaseClinicalDoctorEntity;
|
||||
import net.lab1024.sa.admin.module.business.statsCaseClinical.domain.entity.StatsCaseClinicalHospitalEntity;
|
||||
import net.lab1024.sa.admin.module.business.statsCaseClinical.domain.entity.StatsCaseClinicalLabelEntity;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Service
|
||||
public class CaseClinicalService {
|
||||
@Resource
|
||||
private CaseClinicalArticleDao caseClinicalArticleDao;
|
||||
|
||||
@Resource
|
||||
private CaseClinicalVideoDao caseClinicalVideoDao;
|
||||
|
||||
@Resource
|
||||
private StatsCaseClinicalDoctorDao statsCaseClinicalDoctorDao;
|
||||
|
||||
@Resource
|
||||
private StatsCaseClinicalHospitalDao statsCaseClinicalHospitalDao;
|
||||
|
||||
@Resource
|
||||
private StatsCaseClinicalLabelDao statsCaseClinicalLabelDao;
|
||||
|
||||
/**
|
||||
* 新增标签统计
|
||||
* @param labelIden
|
||||
* @param labelName
|
||||
* @param type 类型 1:文章 2:视频
|
||||
* @param lastPushDate
|
||||
* @return
|
||||
*/
|
||||
@Transactional
|
||||
public StatsCaseClinicalLabelEntity IncStatsCaseClinicalLabel(String labelIden, String labelName, Integer type, LocalDateTime lastPushDate){
|
||||
LambdaQueryWrapper<StatsCaseClinicalLabelEntity> mapQueryWrapper = new LambdaQueryWrapper<>();
|
||||
mapQueryWrapper.eq(StatsCaseClinicalLabelEntity::getLabelIden, labelIden);
|
||||
StatsCaseClinicalLabelEntity statsCaseClinicalLabel = statsCaseClinicalLabelDao.selectOne(mapQueryWrapper);
|
||||
if (statsCaseClinicalLabel == null) {
|
||||
statsCaseClinicalLabel = new StatsCaseClinicalLabelEntity();
|
||||
statsCaseClinicalLabel.setLabelIden(labelIden);
|
||||
statsCaseClinicalLabel.setLabelName(labelName);
|
||||
if (type == 1){
|
||||
statsCaseClinicalLabel.setArticleNum(1);
|
||||
}else if(type == 2){
|
||||
statsCaseClinicalLabel.setVideoNum(1);
|
||||
}
|
||||
if (lastPushDate!=null){
|
||||
statsCaseClinicalLabel.setLastPushDate(lastPushDate);
|
||||
}
|
||||
statsCaseClinicalLabelDao.insert(statsCaseClinicalLabel);
|
||||
}else{
|
||||
if (type == 1){
|
||||
statsCaseClinicalLabelDao.inc(statsCaseClinicalLabel.getLabelIden(),"article_num",1);
|
||||
}else{
|
||||
statsCaseClinicalLabelDao.inc(statsCaseClinicalLabel.getLabelIden(),"video_num",1);
|
||||
}
|
||||
}
|
||||
|
||||
return statsCaseClinicalLabel;
|
||||
}
|
||||
|
||||
/**
|
||||
* 减少标签统计
|
||||
* @param labelIden
|
||||
* @param type 类型 1:文章 2:视频
|
||||
* @return
|
||||
*/
|
||||
@Transactional
|
||||
public StatsCaseClinicalLabelEntity DecStatsCaseClinicalLabel(String labelIden,Integer type){
|
||||
LambdaQueryWrapper<StatsCaseClinicalLabelEntity> mapQueryWrapper = new LambdaQueryWrapper<>();
|
||||
mapQueryWrapper.eq(StatsCaseClinicalLabelEntity::getLabelIden, labelIden);
|
||||
StatsCaseClinicalLabelEntity statsCaseClinicalLabel = statsCaseClinicalLabelDao.selectOne(mapQueryWrapper);
|
||||
if (statsCaseClinicalLabel == null) {
|
||||
return null;
|
||||
}else{
|
||||
if (type == 1){
|
||||
// 最后一篇文章发表时间
|
||||
LocalDateTime lastPushDate = caseClinicalArticleDao.selectLastArticlePushDateByLabelId(labelIden);
|
||||
if (lastPushDate != null){
|
||||
statsCaseClinicalLabel.setLastPushDate(lastPushDate);
|
||||
statsCaseClinicalLabelDao.updateById(statsCaseClinicalLabel);
|
||||
}
|
||||
|
||||
statsCaseClinicalLabelDao.dec(statsCaseClinicalLabel.getLabelIden(),"article_num",1);
|
||||
}else{
|
||||
// 最后一篇文章发表时间
|
||||
LocalDateTime lastPushDate = caseClinicalVideoDao.selectLastVideoPushDateByLabelId(labelIden);
|
||||
if (lastPushDate != null){
|
||||
statsCaseClinicalLabel.setLastPushDate(lastPushDate);
|
||||
statsCaseClinicalLabelDao.updateById(statsCaseClinicalLabel);
|
||||
}
|
||||
statsCaseClinicalLabelDao.dec(statsCaseClinicalLabel.getLabelIden(),"video_num",1);
|
||||
}
|
||||
}
|
||||
|
||||
return statsCaseClinicalLabel;
|
||||
}
|
||||
|
||||
// 新增医生统计
|
||||
@Transactional
|
||||
public StatsCaseClinicalDoctorEntity IncStatsCaseClinicalDoctor(String doctorId, Integer type, LocalDateTime lastPushDate){
|
||||
LambdaQueryWrapper<StatsCaseClinicalDoctorEntity> mapQueryWrapper = new LambdaQueryWrapper<>();
|
||||
mapQueryWrapper.eq(StatsCaseClinicalDoctorEntity::getDoctorId, doctorId);
|
||||
StatsCaseClinicalDoctorEntity statsCaseClinicalDoctor = statsCaseClinicalDoctorDao.selectOne(mapQueryWrapper);
|
||||
if (statsCaseClinicalDoctor == null) {
|
||||
statsCaseClinicalDoctor = new StatsCaseClinicalDoctorEntity();
|
||||
statsCaseClinicalDoctor.setDoctorId(Long.valueOf(doctorId));
|
||||
|
||||
if (type == 1){
|
||||
statsCaseClinicalDoctor.setArticleNum(1);
|
||||
}else if(type == 2){
|
||||
statsCaseClinicalDoctor.setVideoNum(1);
|
||||
}
|
||||
if (lastPushDate!=null){
|
||||
statsCaseClinicalDoctor.setLastPushDate(lastPushDate);
|
||||
}
|
||||
statsCaseClinicalDoctorDao.insert(statsCaseClinicalDoctor);
|
||||
}else{
|
||||
if (type == 1){
|
||||
statsCaseClinicalDoctorDao.inc(statsCaseClinicalDoctor.getDoctorId(),"article_num",1);
|
||||
}else{
|
||||
statsCaseClinicalDoctorDao.inc(statsCaseClinicalDoctor.getDoctorId(),"video_num",1);
|
||||
}
|
||||
}
|
||||
|
||||
return statsCaseClinicalDoctor;
|
||||
}
|
||||
|
||||
/**
|
||||
* 减少医生统计
|
||||
* @param doctorId
|
||||
* @param type 类型 1:文章 2:视频
|
||||
* @return
|
||||
*/
|
||||
@Transactional
|
||||
public StatsCaseClinicalDoctorEntity DecStatsCaseClinicalDoctor(String doctorId,Integer type){
|
||||
LambdaQueryWrapper<StatsCaseClinicalDoctorEntity> mapQueryWrapper = new LambdaQueryWrapper<>();
|
||||
mapQueryWrapper.eq(StatsCaseClinicalDoctorEntity::getDoctorId, doctorId);
|
||||
StatsCaseClinicalDoctorEntity statsCaseClinicalDoctor = statsCaseClinicalDoctorDao.selectOne(mapQueryWrapper);
|
||||
if (statsCaseClinicalDoctor == null) {
|
||||
return null;
|
||||
}else{
|
||||
if (type == 1){
|
||||
// 最后一篇文章发表时间
|
||||
LocalDateTime lastPushDate = caseClinicalArticleDao.selectLastArticlePushDateByDoctorId(Long.valueOf(doctorId));
|
||||
if (lastPushDate != null){
|
||||
statsCaseClinicalDoctor.setLastPushDate(lastPushDate);
|
||||
statsCaseClinicalDoctorDao.updateById(statsCaseClinicalDoctor);
|
||||
}
|
||||
|
||||
statsCaseClinicalDoctorDao.dec(statsCaseClinicalDoctor.getDoctorId(),"article_num",1);
|
||||
}else{
|
||||
// 最后一篇文章发表时间
|
||||
LocalDateTime lastPushDate = caseClinicalVideoDao.selectLastVideoPushDateByDoctorId(Long.valueOf(doctorId));
|
||||
if (lastPushDate != null){
|
||||
statsCaseClinicalDoctor.setLastPushDate(lastPushDate);
|
||||
statsCaseClinicalDoctorDao.updateById(statsCaseClinicalDoctor);
|
||||
}
|
||||
statsCaseClinicalDoctorDao.dec(statsCaseClinicalDoctor.getDoctorId(),"video_num",1);
|
||||
}
|
||||
}
|
||||
|
||||
return statsCaseClinicalDoctor;
|
||||
}
|
||||
|
||||
// 新增医院统计
|
||||
@Transactional
|
||||
public StatsCaseClinicalHospitalEntity IncStatsCaseClinicalHospital(String hospitalId, Integer type, LocalDateTime lastPushDate){
|
||||
LambdaQueryWrapper<StatsCaseClinicalHospitalEntity> mapQueryWrapper = new LambdaQueryWrapper<>();
|
||||
mapQueryWrapper.eq(StatsCaseClinicalHospitalEntity::getHospitalId, hospitalId);
|
||||
StatsCaseClinicalHospitalEntity statsCaseClinicalHospital = statsCaseClinicalHospitalDao.selectOne(mapQueryWrapper);
|
||||
if (statsCaseClinicalHospital == null) {
|
||||
statsCaseClinicalHospital = new StatsCaseClinicalHospitalEntity();
|
||||
statsCaseClinicalHospital.setHospitalId(Long.valueOf(hospitalId));
|
||||
|
||||
if (type == 1){
|
||||
statsCaseClinicalHospital.setArticleNum(1);
|
||||
}else if(type == 2){
|
||||
statsCaseClinicalHospital.setVideoNum(1);
|
||||
}
|
||||
|
||||
if (lastPushDate!=null){
|
||||
statsCaseClinicalHospital.setLastPushDate(lastPushDate);
|
||||
}
|
||||
statsCaseClinicalHospitalDao.insert(statsCaseClinicalHospital);
|
||||
}else{
|
||||
if (type == 1){
|
||||
statsCaseClinicalHospitalDao.inc(statsCaseClinicalHospital.getHospitalId(),"article_num",1);
|
||||
}else{
|
||||
statsCaseClinicalHospitalDao.inc(statsCaseClinicalHospital.getHospitalId(),"video_num",1);
|
||||
}
|
||||
}
|
||||
|
||||
return statsCaseClinicalHospital;
|
||||
}
|
||||
|
||||
/**
|
||||
* 减少医院统计
|
||||
* @param hospitalId
|
||||
* @param type 类型 1:文章 2:视频
|
||||
* @return
|
||||
*/
|
||||
@Transactional
|
||||
public StatsCaseClinicalHospitalEntity DecStatsCaseClinicalHospital(String hospitalId,Integer type){
|
||||
LambdaQueryWrapper<StatsCaseClinicalHospitalEntity> mapQueryWrapper = new LambdaQueryWrapper<>();
|
||||
mapQueryWrapper.eq(StatsCaseClinicalHospitalEntity::getHospitalId, hospitalId);
|
||||
StatsCaseClinicalHospitalEntity statsCaseClinicalHospital = statsCaseClinicalHospitalDao.selectOne(mapQueryWrapper);
|
||||
if (statsCaseClinicalHospital == null) {
|
||||
return null;
|
||||
}else{
|
||||
if (type == 1){
|
||||
// 最后一篇文章发表时间
|
||||
LocalDateTime lastPushDate = caseClinicalArticleDao.selectLastArticlePushDateByHospitalId(Long.valueOf(hospitalId));
|
||||
if (lastPushDate != null){
|
||||
statsCaseClinicalHospital.setLastPushDate(lastPushDate);
|
||||
statsCaseClinicalHospitalDao.updateById(statsCaseClinicalHospital);
|
||||
}
|
||||
|
||||
statsCaseClinicalHospitalDao.dec(statsCaseClinicalHospital.getHospitalId(),"article_num",1);
|
||||
}else{
|
||||
// 最后一篇文章发表时间
|
||||
LocalDateTime lastPushDate = caseClinicalVideoDao.selectLastVideoPushDateByHospitalId(Long.valueOf(hospitalId));
|
||||
if (lastPushDate != null){
|
||||
statsCaseClinicalHospital.setLastPushDate(lastPushDate);
|
||||
statsCaseClinicalHospitalDao.updateById(statsCaseClinicalHospital);
|
||||
}
|
||||
statsCaseClinicalHospitalDao.dec(statsCaseClinicalHospital.getHospitalId(),"video_num",1);
|
||||
}
|
||||
}
|
||||
|
||||
return statsCaseClinicalHospital;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,113 @@
|
||||
package net.lab1024.sa.admin.module.business.caseClinicalArticle.controller;
|
||||
|
||||
import com.amazonaws.Response;
|
||||
import net.lab1024.sa.admin.extend.app.label.GetLabelsResponse;
|
||||
import net.lab1024.sa.admin.module.business.caseClinicalArticle.domain.form.CaseClinicalArticleAddForm;
|
||||
import net.lab1024.sa.admin.module.business.caseClinicalArticle.domain.form.CaseClinicalArticleLabelQueryListForm;
|
||||
import net.lab1024.sa.admin.module.business.caseClinicalArticle.domain.form.CaseClinicalArticleQueryForm;
|
||||
import net.lab1024.sa.admin.module.business.caseClinicalArticle.domain.form.CaseClinicalArticleUpdateForm;
|
||||
import net.lab1024.sa.admin.module.business.caseClinicalArticle.domain.form.CaseClinicalArticleStatusUpdateForm;
|
||||
import net.lab1024.sa.admin.module.business.caseClinicalArticle.domain.vo.AppCaseClinicalArticleLabelVO;
|
||||
import net.lab1024.sa.admin.module.business.caseClinicalArticle.domain.vo.CaseClinicalArticleVO;
|
||||
import net.lab1024.sa.admin.module.business.caseClinicalArticle.service.CaseClinicalArticleLabelService;
|
||||
import net.lab1024.sa.admin.module.business.caseClinicalArticle.service.CaseClinicalArticleService;
|
||||
import net.lab1024.sa.base.common.domain.ValidateList;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import net.lab1024.sa.base.common.domain.ResponseDTO;
|
||||
import net.lab1024.sa.base.common.domain.PageResult;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.validation.Valid;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 病例库-临床-文章 Controller
|
||||
*
|
||||
* @Author xing
|
||||
* @Date 2025-08-04 10:17:15
|
||||
* @Copyright gdxz
|
||||
*/
|
||||
|
||||
@RestController
|
||||
@Tag(name = "病例库-临床-文章")
|
||||
public class CaseClinicalArticleController {
|
||||
|
||||
@Resource
|
||||
private CaseClinicalArticleService caseClinicalArticleService;
|
||||
|
||||
@Resource
|
||||
private CaseClinicalArticleLabelService caseClinicalArticleLabelService;
|
||||
|
||||
@Operation(summary = "分页查询 @author xing")
|
||||
@PostMapping("/caseClinicalArticle/queryPage")
|
||||
@SaCheckPermission("caseClinicalArticle:query")
|
||||
public ResponseDTO<PageResult<CaseClinicalArticleVO>> queryPage(@RequestBody @Valid CaseClinicalArticleQueryForm queryForm) {
|
||||
return ResponseDTO.ok(caseClinicalArticleService.queryPage(queryForm));
|
||||
}
|
||||
|
||||
@Operation(summary = "添加 @author xing")
|
||||
@PostMapping("/caseClinicalArticle/add")
|
||||
@SaCheckPermission("caseClinicalArticle:add")
|
||||
public ResponseDTO<String> add(@RequestBody @Valid CaseClinicalArticleAddForm addForm) {
|
||||
return caseClinicalArticleService.add(addForm);
|
||||
}
|
||||
|
||||
@Operation(summary = "更新 @author xing")
|
||||
@PostMapping("/caseClinicalArticle/update")
|
||||
@SaCheckPermission("caseClinicalArticle:update")
|
||||
public ResponseDTO<String> update(@RequestBody @Valid CaseClinicalArticleUpdateForm updateForm) {
|
||||
return caseClinicalArticleService.update(updateForm);
|
||||
}
|
||||
|
||||
@Operation(summary = "批量删除 @author xing")
|
||||
@PostMapping("/caseClinicalArticle/batchDelete")
|
||||
@SaCheckPermission("caseClinicalArticle:delete")
|
||||
public ResponseDTO<String> batchDelete(@RequestBody ValidateList<Long> idList) {
|
||||
return caseClinicalArticleService.batchDelete(idList);
|
||||
}
|
||||
|
||||
@Operation(summary = "单个删除 @author xing")
|
||||
@GetMapping("/caseClinicalArticle/delete/{articleId}")
|
||||
@SaCheckPermission("caseClinicalArticle:delete")
|
||||
public ResponseDTO<String> batchDelete(@PathVariable Long articleId) {
|
||||
return caseClinicalArticleService.delete(articleId);
|
||||
}
|
||||
|
||||
@Operation(summary = "生成文章分享二维码 @author xing")
|
||||
@PostMapping("/caseClinicalArticle/addUnlimitedQrcode/{articleId}")
|
||||
@SaCheckPermission("caseClinicalArticle:addUnlimitedQrcode")
|
||||
public ResponseDTO<String> addUnlimitedQrcode(@PathVariable Long articleId) {
|
||||
caseClinicalArticleService.addUnlimitedQrcode(articleId);
|
||||
return ResponseDTO.ok();
|
||||
}
|
||||
|
||||
@Operation(summary = "获取文章详情 @author xing")
|
||||
@GetMapping("/caseClinicalArticle/getDetail/{articleId}")
|
||||
@SaCheckPermission("caseClinicalArticle:query")
|
||||
public ResponseDTO<CaseClinicalArticleVO> getDetail(@PathVariable Long articleId) {
|
||||
return caseClinicalArticleService.getDetail(articleId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取疾病标签列表
|
||||
*/
|
||||
@Operation(summary = "获取疾病标签列表 @author xing")
|
||||
@GetMapping("/caseClinicalLabel/queryList")
|
||||
@SaCheckPermission("caseClinicalArticle:query")
|
||||
public ResponseDTO<List<AppCaseClinicalArticleLabelVO>> getCaseLabel(@RequestParam(defaultValue = "0") String pId) {
|
||||
return caseClinicalArticleLabelService.getCaseLabel(pId);
|
||||
}
|
||||
|
||||
@Operation(summary = "修改状态 @author xing")
|
||||
@PostMapping("/caseClinicalArticle/status/update")
|
||||
@SaCheckPermission("caseClinicalArticle:update")
|
||||
public ResponseDTO<String> statusUpdate(@RequestBody @Valid CaseClinicalArticleStatusUpdateForm updateForm) {
|
||||
return caseClinicalArticleService.updateStatus(updateForm.getArticleId(), updateForm.getStatus());
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,78 @@
|
||||
package net.lab1024.sa.admin.module.business.caseClinicalArticle.dao;
|
||||
|
||||
import net.lab1024.sa.admin.module.business.caseClinicalArticle.domain.entity.CaseClinicalArticleEntity;
|
||||
import net.lab1024.sa.admin.module.business.caseClinicalArticle.domain.form.CaseClinicalArticleQueryForm;
|
||||
import net.lab1024.sa.admin.module.business.caseClinicalArticle.domain.vo.CaseClinicalArticleVO;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.apache.ibatis.annotations.Update;
|
||||
|
||||
/**
|
||||
* 病例库-临床-文章 Dao
|
||||
*
|
||||
* @Author xing
|
||||
* @Date 2025-08-04 10:17:15
|
||||
* @Copyright gdxz
|
||||
*/
|
||||
|
||||
@Mapper
|
||||
public interface CaseClinicalArticleDao extends BaseMapper<CaseClinicalArticleEntity> {
|
||||
|
||||
/**
|
||||
* 分页 查询
|
||||
*
|
||||
* @param page
|
||||
* @param queryForm
|
||||
* @return
|
||||
*/
|
||||
List<CaseClinicalArticleVO> queryPage(Page page, @Param("queryForm") CaseClinicalArticleQueryForm queryForm);
|
||||
|
||||
/**
|
||||
* Inc 自增
|
||||
* @param articleId 文章 ID
|
||||
* @param field 字段名称
|
||||
* @param numeral 增加的数值
|
||||
* @return 更新的行数
|
||||
*/
|
||||
@Update("UPDATE stats_case_clinical SET ${field} = ${field} + #{numeral} WHERE stats_id = #{statsId}")
|
||||
int inc(@Param("statsId") Long articleId, @Param("field") String field, @Param("numeral") int numeral);
|
||||
|
||||
/**
|
||||
* Dec 自减
|
||||
*
|
||||
* @param articleId 文章 ID
|
||||
* @param field 字段名称
|
||||
* @param numeral 减少的数值
|
||||
* @return 更新的行数
|
||||
*/
|
||||
@Update("UPDATE stats_case_clinical " +
|
||||
"SET ${field} = CASE WHEN ${field} >= #{numeral} THEN ${field} - #{numeral} ELSE 0 END " +
|
||||
"WHERE stats_id = #{statsId}")
|
||||
int dec(@Param("statsId") Long articleId, @Param("field") String field, @Param("numeral") int numeral);
|
||||
|
||||
/**
|
||||
* 根据医院ID查询该医院最后一篇文章的发表时间
|
||||
* @param hospitalId 医院ID
|
||||
* @return 最新发表时间,无数据时返回 null
|
||||
*/
|
||||
LocalDateTime selectLastArticlePushDateByHospitalId(@Param("hospitalId") Long hospitalId);
|
||||
|
||||
/**
|
||||
* 根据医生ID查询该医生最后一篇文章的发表时间
|
||||
* @param doctorId 医院ID
|
||||
* @return 最新发表时间,无数据时返回 null
|
||||
*/
|
||||
LocalDateTime selectLastArticlePushDateByDoctorId(@Param("doctorId") Long doctorId);
|
||||
|
||||
/**
|
||||
* 根据医院ID查询该医院最后一篇文章的发表时间
|
||||
* @param labelIden 标签唯一标识
|
||||
* @return 最新发表时间,无数据时返回 null
|
||||
*/
|
||||
LocalDateTime selectLastArticlePushDateByLabelId(@Param("labelIden") String labelIden);
|
||||
}
|
||||
@ -0,0 +1,24 @@
|
||||
package net.lab1024.sa.admin.module.business.caseClinicalArticle.dao;
|
||||
|
||||
import java.util.List;
|
||||
import net.lab1024.sa.admin.module.business.caseClinicalArticle.domain.entity.CaseClinicalArticleLabelEntity;
|
||||
import net.lab1024.sa.admin.module.business.caseClinicalArticle.domain.vo.CaseClinicalArticleLabelVO;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 病例库-临床-文章-标签 Dao
|
||||
*
|
||||
* @Author xing
|
||||
* @Date 2025-08-06 17:41:09
|
||||
* @Copyright gdxz
|
||||
*/
|
||||
|
||||
@Mapper
|
||||
public interface CaseClinicalArticleLabelDao extends BaseMapper<CaseClinicalArticleLabelEntity> {
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,105 @@
|
||||
package net.lab1024.sa.admin.module.business.caseClinicalArticle.domain.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.FieldFill;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
import lombok.Data;
|
||||
import net.lab1024.sa.admin.module.business.caseClinicalArticleAuthor.domain.entity.CaseClinicalArticleAuthorEntity;
|
||||
|
||||
/**
|
||||
* 病例库-临床-文章 实体类
|
||||
*
|
||||
* @Author xing
|
||||
* @Date 2025-08-04 10:17:15
|
||||
* @Copyright gdxz
|
||||
*/
|
||||
|
||||
@Data
|
||||
@TableName("case_clinical_article")
|
||||
public class CaseClinicalArticleEntity {
|
||||
|
||||
/**
|
||||
* 主键id
|
||||
*/
|
||||
@TableId
|
||||
private Long articleId;
|
||||
|
||||
/**
|
||||
* 标题
|
||||
*/
|
||||
private String articleTitle;
|
||||
|
||||
/**
|
||||
* 状态(1:正常 2:禁用)
|
||||
*/
|
||||
private Integer articleStatus;
|
||||
|
||||
/**
|
||||
* 删除状态(0:否 1:是)
|
||||
*/
|
||||
private Integer deleteStatus;
|
||||
|
||||
/**
|
||||
* 阅读量
|
||||
*/
|
||||
private Integer readNum;
|
||||
|
||||
/**
|
||||
* 收藏量
|
||||
*/
|
||||
private Integer collectNum;
|
||||
|
||||
/**
|
||||
* 评论数
|
||||
*/
|
||||
private Integer commentNum;
|
||||
|
||||
/**
|
||||
* 证书图片
|
||||
*/
|
||||
private String certImage;
|
||||
|
||||
/**
|
||||
* 发表时间
|
||||
*/
|
||||
private LocalDateTime pushDate;
|
||||
|
||||
/**
|
||||
* 是否外部链接(0:否 1:是)
|
||||
*/
|
||||
private Integer isLink;
|
||||
|
||||
/**
|
||||
* 外部链接地址
|
||||
*/
|
||||
private String isLinkUrl;
|
||||
|
||||
/**
|
||||
* 分享二维码地址
|
||||
*/
|
||||
@TableField("share_qrcode")
|
||||
private String shareQrcode;
|
||||
|
||||
/**
|
||||
* 内容
|
||||
*/
|
||||
private String articleContent;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private LocalDateTime createdAt;
|
||||
|
||||
/**
|
||||
* 修改时间
|
||||
*/
|
||||
private LocalDateTime updatedAt;
|
||||
|
||||
// 作者
|
||||
@TableField(exist = false)
|
||||
private List<CaseClinicalArticleAuthorEntity> caseClinicalArticleAuthor;
|
||||
}
|
||||
@ -0,0 +1,51 @@
|
||||
package net.lab1024.sa.admin.module.business.caseClinicalArticle.domain.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import java.time.LocalDateTime;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 病例库-临床-文章-标签 实体类
|
||||
*
|
||||
* @Author xing
|
||||
* @Date 2025-08-06 17:41:09
|
||||
* @Copyright gdxz
|
||||
*/
|
||||
|
||||
@Data
|
||||
@TableName("case_clinical_article_label")
|
||||
public class CaseClinicalArticleLabelEntity {
|
||||
|
||||
/**
|
||||
* 主键id
|
||||
*/
|
||||
@TableId
|
||||
private Long articleLabelId;
|
||||
|
||||
/**
|
||||
* 临床文章id
|
||||
*/
|
||||
private Long articleId;
|
||||
|
||||
/**
|
||||
* app唯一标识
|
||||
*/
|
||||
private String appIden;
|
||||
|
||||
/**
|
||||
* 标签名称
|
||||
*/
|
||||
private String labelName;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private LocalDateTime createdAt;
|
||||
|
||||
/**
|
||||
* 修改时间
|
||||
*/
|
||||
private LocalDateTime updatedAt;
|
||||
|
||||
}
|
||||
@ -0,0 +1,59 @@
|
||||
package net.lab1024.sa.admin.module.business.caseClinicalArticle.domain.form;
|
||||
|
||||
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
import lombok.Data;
|
||||
import net.lab1024.sa.admin.module.business.caseClinicalArticleAuthor.domain.vo.CaseClinicalArticleAuthorVO;
|
||||
import net.lab1024.sa.base.common.json.deserializer.FileKeyVoDeserializer;
|
||||
import net.lab1024.sa.admin.module.business.caseClinicalArticle.domain.form.CaseClinicalArticleAuthorForm;
|
||||
|
||||
/**
|
||||
* 病例库-临床-文章 新建表单
|
||||
*
|
||||
* @Author xing
|
||||
* @Date 2025-08-04 10:17:15
|
||||
* @Copyright gdxz
|
||||
*/
|
||||
|
||||
@Data
|
||||
public class CaseClinicalArticleAddForm {
|
||||
|
||||
@Schema(description = "标题", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotBlank(message = "标题 不能为空")
|
||||
private String articleTitle;
|
||||
|
||||
@Schema(description = "状态(1:正常 2:禁用)", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotNull(message = "状态(1:正常 2:禁用) 不能为空")
|
||||
private Integer articleStatus;
|
||||
|
||||
@Schema(description = "发表时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotNull(message = "发表时间 不能为空")
|
||||
private LocalDateTime pushDate;
|
||||
|
||||
@Schema(description = "是否外部链接(0:否 1:是)", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotNull(message = "是否外部链接(0:否 1:是) 不能为空")
|
||||
private Integer isLink;
|
||||
|
||||
@Schema(description = "外部链接地址")
|
||||
private String isLinkUrl;
|
||||
|
||||
@Schema(description = "分享二维码地址")
|
||||
@JsonDeserialize(using = FileKeyVoDeserializer.class)
|
||||
private String shareQrcode;
|
||||
|
||||
@Schema(description = "内容", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotBlank(message = "内容 不能为空")
|
||||
private String articleContent;
|
||||
|
||||
@Schema(description = "作者列表")
|
||||
private List<CaseClinicalArticleAuthorForm> authorList;
|
||||
|
||||
@Schema(description = "标签列表")
|
||||
private List<CaseClinicalArticleLabelForm> labelList;
|
||||
|
||||
}
|
||||
@ -0,0 +1,31 @@
|
||||
package net.lab1024.sa.admin.module.business.caseClinicalArticle.domain.form;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 病例库-临床-文章-作者 表单
|
||||
*
|
||||
* @Author xing
|
||||
* @Date 2025-08-05 08:45:33
|
||||
* @Copyright gdxz
|
||||
*/
|
||||
|
||||
@Data
|
||||
public class CaseClinicalArticleAuthorForm {
|
||||
|
||||
@Schema(description = "医生ID")
|
||||
private Long doctorId;
|
||||
|
||||
@Schema(description = "医生姓名")
|
||||
private String doctorName;
|
||||
|
||||
@Schema(description = "医院名称")
|
||||
private String hospitalName;
|
||||
|
||||
@Schema(description = "医院省份")
|
||||
private String hospitalProvince;
|
||||
|
||||
@Schema(description = "医院城市")
|
||||
private String hospitalCity;
|
||||
}
|
||||
@ -0,0 +1,26 @@
|
||||
package net.lab1024.sa.admin.module.business.caseClinicalArticle.domain.form;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 病例库-临床-文章-标签 表单
|
||||
*
|
||||
* @Author xing
|
||||
* @Date 2025-08-05 08:45:33
|
||||
* @Copyright gdxz
|
||||
*/
|
||||
|
||||
@Data
|
||||
public class CaseClinicalArticleLabelForm {
|
||||
|
||||
@Schema(description = "医生ID")
|
||||
private Long doctorId;
|
||||
|
||||
@Schema(description = "唯一标识")
|
||||
private String appIden; // app唯一标识
|
||||
|
||||
@Schema(description = "标签名称")
|
||||
private String labelName; // 标签名称
|
||||
}
|
||||
@ -0,0 +1,25 @@
|
||||
package net.lab1024.sa.admin.module.business.caseClinicalArticle.domain.form;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import net.lab1024.sa.base.common.domain.PageParam;
|
||||
|
||||
import java.time.LocalDate;
|
||||
|
||||
/**
|
||||
* 病例库-临床-文章 分页查询表单
|
||||
*
|
||||
* @Author xing
|
||||
* @Date 2025-08-04 10:17:15
|
||||
* @Copyright gdxz
|
||||
*/
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
public class CaseClinicalArticleLabelQueryListForm {
|
||||
|
||||
@Schema(description = "父级ID,默认为0表示获取顶级标签")
|
||||
private String pId = "0";
|
||||
}
|
||||
@ -0,0 +1,36 @@
|
||||
package net.lab1024.sa.admin.module.business.caseClinicalArticle.domain.form;
|
||||
|
||||
import net.lab1024.sa.base.common.domain.PageParam;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.time.LocalDate;
|
||||
|
||||
/**
|
||||
* 病例库-临床-文章 分页查询表单
|
||||
*
|
||||
* @Author xing
|
||||
* @Date 2025-08-04 10:17:15
|
||||
* @Copyright gdxz
|
||||
*/
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
public class CaseClinicalArticleQueryForm extends PageParam {
|
||||
|
||||
@Schema(description = "关键字")
|
||||
private String keywords;
|
||||
|
||||
@Schema(description = "状态")
|
||||
private Integer articleStatus;
|
||||
|
||||
@Schema(description = "删除状态")
|
||||
private Integer deleteStatus;
|
||||
|
||||
@Schema(description = "发表时间")
|
||||
private LocalDate pushDateBegin;
|
||||
|
||||
@Schema(description = "发表时间")
|
||||
private LocalDate pushDateEnd;
|
||||
}
|
||||
@ -0,0 +1,26 @@
|
||||
package net.lab1024.sa.admin.module.business.caseClinicalArticle.domain.form;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
|
||||
/**
|
||||
* 病例库-临床-文章 状态更新表单
|
||||
*
|
||||
* @Author xing
|
||||
* @Date 2025-08-04 10:17:15
|
||||
* @Copyright gdxz
|
||||
*/
|
||||
@Data
|
||||
@Schema(description = "病例库-临床-文章 状态更新表单")
|
||||
public class CaseClinicalArticleStatusUpdateForm {
|
||||
|
||||
@Schema(description = "文章ID")
|
||||
@NotNull(message = "文章ID不能为空")
|
||||
private Long articleId;
|
||||
|
||||
@Schema(description = "状态 1:正常 2:禁用")
|
||||
@NotNull(message = "状态不能为空")
|
||||
private Integer status;
|
||||
}
|
||||
@ -0,0 +1,65 @@
|
||||
package net.lab1024.sa.admin.module.business.caseClinicalArticle.domain.form;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import java.time.LocalDateTime;
|
||||
import lombok.Data;
|
||||
import net.lab1024.sa.base.common.json.deserializer.FileKeyVoDeserializer;
|
||||
import net.lab1024.sa.admin.module.business.caseClinicalArticle.domain.form.CaseClinicalArticleAuthorForm;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 病例库-临床-文章 更新表单
|
||||
*
|
||||
* @Author xing
|
||||
* @Date 2025-08-04 10:17:15
|
||||
* @Copyright gdxz
|
||||
*/
|
||||
|
||||
@Data
|
||||
public class CaseClinicalArticleUpdateForm {
|
||||
|
||||
@Schema(description = "主键id", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotNull(message = "主键id 不能为空")
|
||||
private Long articleId;
|
||||
|
||||
@Schema(description = "标题", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotBlank(message = "标题 不能为空")
|
||||
private String articleTitle;
|
||||
|
||||
@Schema(description = "状态(1:正常 2:禁用)", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotNull(message = "状态(1:正常 2:禁用) 不能为空")
|
||||
private Integer articleStatus;
|
||||
|
||||
@Schema(description = "删除状态(0:否 1:是)", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotNull(message = "删除状态(0:否 1:是) 不能为空")
|
||||
private Integer deleteStatus;
|
||||
|
||||
@Schema(description = "发表时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotNull(message = "发表时间 不能为空")
|
||||
private LocalDateTime pushDate;
|
||||
|
||||
@Schema(description = "是否外部链接(0:否 1:是)", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotNull(message = "是否外部链接(0:否 1:是) 不能为空")
|
||||
private Integer isLink;
|
||||
|
||||
@Schema(description = "外部链接地址")
|
||||
private String isLinkUrl;
|
||||
|
||||
@Schema(description = "分享二维码地址")
|
||||
@JsonDeserialize(using = FileKeyVoDeserializer.class)
|
||||
private String shareQrcode;
|
||||
|
||||
@Schema(description = "内容", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotBlank(message = "内容 不能为空")
|
||||
private String articleContent;
|
||||
|
||||
@Schema(description = "作者列表")
|
||||
public List<CaseClinicalArticleAuthorForm> authorList;
|
||||
|
||||
@Schema(description = "标签列表")
|
||||
private List<CaseClinicalArticleLabelForm> labelList;
|
||||
}
|
||||
@ -0,0 +1,37 @@
|
||||
package net.lab1024.sa.admin.module.business.caseClinicalArticle.domain.vo;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 病例库-临床-文章-标签 列表VO
|
||||
*
|
||||
* @Author xing
|
||||
* @Date 2025-08-06 17:41:09
|
||||
* @Copyright gdxz
|
||||
*/
|
||||
|
||||
@Data
|
||||
public class AppCaseClinicalArticleLabelVO {
|
||||
/**
|
||||
* app唯一标识
|
||||
*/
|
||||
@Schema(description = "唯一标识")
|
||||
private String appIden;
|
||||
|
||||
/**
|
||||
* 标签名称
|
||||
*/
|
||||
@Schema(description = "标签名称")
|
||||
private String labelName;
|
||||
|
||||
/**
|
||||
* 是否存在子标签,0:否 1:是
|
||||
*/
|
||||
@Schema(description = "是否存在子标签")
|
||||
private Integer isSub = 0;
|
||||
|
||||
}
|
||||
@ -0,0 +1,37 @@
|
||||
package net.lab1024.sa.admin.module.business.caseClinicalArticle.domain.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import java.time.LocalDateTime;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 病例库-临床-文章-标签 列表VO
|
||||
*
|
||||
* @Author xing
|
||||
* @Date 2025-08-06 17:41:09
|
||||
* @Copyright gdxz
|
||||
*/
|
||||
|
||||
@Data
|
||||
public class CaseClinicalArticleLabelVO {
|
||||
|
||||
|
||||
@Schema(description = "主键id")
|
||||
private Long articleLabelId;
|
||||
|
||||
@Schema(description = "临床文章id")
|
||||
private Long articleId;
|
||||
|
||||
@Schema(description = "app唯一标识")
|
||||
private String appIden;
|
||||
|
||||
@Schema(description = "标签名称")
|
||||
private String labelName;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
private LocalDateTime createdAt;
|
||||
|
||||
@Schema(description = "修改时间")
|
||||
private LocalDateTime updatedAt;
|
||||
|
||||
}
|
||||
@ -0,0 +1,80 @@
|
||||
package net.lab1024.sa.admin.module.business.caseClinicalArticle.domain.vo;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import lombok.Data;
|
||||
import net.lab1024.sa.admin.module.business.caseClinicalArticle.domain.entity.CaseClinicalArticleEntity;
|
||||
import net.lab1024.sa.admin.module.business.caseClinicalArticleAuthor.domain.vo.CaseClinicalArticleAuthorVO;
|
||||
import net.lab1024.sa.admin.module.business.caseClinicalArticle.domain.vo.CaseClinicalArticleLabelVO;
|
||||
import net.lab1024.sa.admin.module.business.caseClinicalDoctor.domain.vo.CaseClinicalDoctorVO;
|
||||
import net.lab1024.sa.base.common.json.serializer.FileKeyVoSerializer;
|
||||
|
||||
/**
|
||||
* 病例库-临床-文章 列表VO
|
||||
*
|
||||
* @Author xing
|
||||
* @Date 2025-08-04 10:17:15
|
||||
* @Copyright gdxz
|
||||
*/
|
||||
|
||||
@Data
|
||||
public class CaseClinicalArticleVO {
|
||||
@Schema(description = "主键id")
|
||||
private Long articleId;
|
||||
|
||||
@Schema(description = "标题")
|
||||
private String articleTitle;
|
||||
|
||||
@Schema(description = "状态(1:正常 2:禁用)")
|
||||
private Integer articleStatus;
|
||||
|
||||
@Schema(description = "删除状态(0:否 1:是)")
|
||||
private Integer deleteStatus;
|
||||
|
||||
@Schema(description = "阅读量")
|
||||
private Integer readNum;
|
||||
|
||||
@Schema(description = "收藏量")
|
||||
private Integer collectNum;
|
||||
|
||||
@Schema(description = "评论数")
|
||||
private Integer commentNum;
|
||||
|
||||
@Schema(description = "证书图片")
|
||||
// @JsonSerialize(using = FileKeyVoSerializer.class)
|
||||
private String certImage;
|
||||
|
||||
@Schema(description = "发表时间")
|
||||
private LocalDateTime pushDate;
|
||||
|
||||
@Schema(description = "是否外部链接(0:否 1:是)")
|
||||
private Integer isLink;
|
||||
|
||||
@Schema(description = "外部链接地址")
|
||||
private String isLinkUrl;
|
||||
|
||||
@Schema(description = "分享二维码地址")
|
||||
// @JsonSerialize(using = FileKeyVoSerializer.class)
|
||||
private String shareQrcode;
|
||||
|
||||
@Schema(description = "内容")
|
||||
private String articleContent;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
private LocalDateTime createdAt;
|
||||
|
||||
@Schema(description = "修改时间")
|
||||
private LocalDateTime updatedAt;
|
||||
|
||||
@Schema(description = "作者数据")
|
||||
private List<CaseClinicalArticleAuthorVO> caseClinicalArticleAuthor;
|
||||
|
||||
@Schema(description = "标签数据")
|
||||
private List<CaseClinicalArticleLabelVO> caseClinicalArticleLabel;
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
package net.lab1024.sa.admin.module.business.caseClinicalArticle.manager;
|
||||
|
||||
import net.lab1024.sa.admin.module.business.caseClinicalArticle.domain.entity.CaseClinicalArticleLabelEntity;
|
||||
import net.lab1024.sa.admin.module.business.caseClinicalArticle.dao.CaseClinicalArticleLabelDao;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* 病例库-临床-文章-标签 Manager
|
||||
*
|
||||
* @Author xing
|
||||
* @Date 2025-08-06 17:41:09
|
||||
* @Copyright gdxz
|
||||
*/
|
||||
@Service
|
||||
public class CaseClinicalArticleLabelManager extends ServiceImpl<CaseClinicalArticleLabelDao, CaseClinicalArticleLabelEntity> {
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
package net.lab1024.sa.admin.module.business.caseClinicalArticle.manager;
|
||||
|
||||
import net.lab1024.sa.admin.module.business.caseClinicalArticle.dao.CaseClinicalArticleDao;
|
||||
import net.lab1024.sa.admin.module.business.caseClinicalArticle.domain.entity.CaseClinicalArticleEntity;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* 病例库-临床-文章 Manager
|
||||
*
|
||||
* @Author xing
|
||||
* @Date 2025-08-04 10:17:15
|
||||
* @Copyright gdxz
|
||||
*/
|
||||
@Service
|
||||
public class CaseClinicalArticleManager extends ServiceImpl<CaseClinicalArticleDao, CaseClinicalArticleEntity> {
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,71 @@
|
||||
package net.lab1024.sa.admin.module.business.caseClinicalArticle.service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.amazonaws.Response;
|
||||
import net.lab1024.sa.admin.extend.app.label.GetLabelsResponse;
|
||||
import net.lab1024.sa.admin.extend.app.label.Label;
|
||||
import net.lab1024.sa.admin.module.business.caseClinicalArticle.dao.CaseClinicalArticleLabelDao;
|
||||
import net.lab1024.sa.admin.module.business.caseClinicalArticle.domain.entity.CaseClinicalArticleLabelEntity;
|
||||
import net.lab1024.sa.admin.module.business.caseClinicalArticle.domain.vo.AppCaseClinicalArticleLabelVO;
|
||||
import net.lab1024.sa.admin.module.business.caseClinicalArticle.domain.vo.CaseClinicalArticleLabelVO;
|
||||
import net.lab1024.sa.base.common.util.SmartBeanUtil;
|
||||
import net.lab1024.sa.base.common.util.SmartPageUtil;
|
||||
import net.lab1024.sa.base.common.domain.ResponseDTO;
|
||||
import net.lab1024.sa.base.common.domain.PageResult;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||
|
||||
/**
|
||||
* 病例库-临床-文章-标签 Service
|
||||
*
|
||||
* @Author xing
|
||||
* @Date 2025-08-06 17:41:09
|
||||
* @Copyright gdxz
|
||||
*/
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
public class CaseClinicalArticleLabelService {
|
||||
|
||||
@Resource
|
||||
private CaseClinicalArticleLabelDao caseClinicalArticleLabelDao;
|
||||
|
||||
@Resource
|
||||
private Label label;
|
||||
|
||||
/**
|
||||
* 获取疾病标签数据
|
||||
*/
|
||||
public ResponseDTO<List<AppCaseClinicalArticleLabelVO>> getCaseLabel(String pid) {
|
||||
try {
|
||||
GetLabelsResponse result = label.getLabels(pid);
|
||||
List<GetLabelsResponse.GetLabelsData> datas = result.getData();
|
||||
|
||||
List<AppCaseClinicalArticleLabelVO> labelDtoList = new ArrayList<>();
|
||||
for (GetLabelsResponse.GetLabelsData d : datas) {
|
||||
AppCaseClinicalArticleLabelVO dto = new AppCaseClinicalArticleLabelVO();
|
||||
dto.setAppIden(d.getId());
|
||||
dto.setLabelName(d.getName());
|
||||
if (d.getChildrenSize() > 0){
|
||||
dto.setIsSub(1);
|
||||
}
|
||||
|
||||
labelDtoList.add(dto);
|
||||
}
|
||||
|
||||
return ResponseDTO.ok(labelDtoList);
|
||||
} catch (Exception e) {
|
||||
log.error("获取疾病标签数据失败: {}", e.getMessage(), e);
|
||||
return ResponseDTO.userErrorParam("获取疾病标签数据失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,819 @@
|
||||
package net.lab1024.sa.admin.module.business.caseClinicalArticle.service;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import net.lab1024.sa.admin.extend.app.UserInfo.GetUserInfoResponse;
|
||||
import net.lab1024.sa.admin.module.business.basicHospital.dao.BasicHospitalDao;
|
||||
import net.lab1024.sa.admin.module.business.basicHospital.domain.entity.BasicHospitalEntity;
|
||||
import net.lab1024.sa.admin.module.business.caseClinical.service.CaseClinicalService;
|
||||
import net.lab1024.sa.admin.module.business.caseClinicalArticle.dao.CaseClinicalArticleDao;
|
||||
import net.lab1024.sa.admin.module.business.caseClinicalArticle.dao.CaseClinicalArticleLabelDao;
|
||||
import net.lab1024.sa.admin.module.business.caseClinicalArticle.domain.entity.CaseClinicalArticleEntity;
|
||||
import net.lab1024.sa.admin.module.business.caseClinicalArticle.domain.entity.CaseClinicalArticleLabelEntity;
|
||||
import net.lab1024.sa.admin.module.business.caseClinicalArticle.domain.form.*;
|
||||
import net.lab1024.sa.admin.module.business.caseClinicalArticle.domain.vo.CaseClinicalArticleVO;
|
||||
import net.lab1024.sa.admin.module.business.caseClinicalArticle.domain.vo.CaseClinicalArticleLabelVO;
|
||||
import net.lab1024.sa.admin.extend.weChat.WxMaServiceUtils;
|
||||
import net.lab1024.sa.admin.extend.aliyun.Oss;
|
||||
import net.lab1024.sa.admin.module.business.caseClinicalDoctor.dao.CaseClinicalDoctorCertDao;
|
||||
import net.lab1024.sa.admin.module.business.caseClinicalDoctor.domain.entity.CaseClinicalDoctorCertEntity;
|
||||
import net.lab1024.sa.admin.module.business.statsCaseClinical.dao.StatsCaseClinicalDao;
|
||||
import net.lab1024.sa.admin.module.business.user.service.UserService;
|
||||
import net.lab1024.sa.admin.util.ImageUtil;
|
||||
import net.lab1024.sa.admin.util.Replace;
|
||||
import net.lab1024.sa.base.common.exception.BusinessException;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
|
||||
import net.lab1024.sa.admin.module.business.caseClinicalArticleAuthor.dao.CaseClinicalArticleAuthorDao;
|
||||
import net.lab1024.sa.admin.module.business.caseClinicalArticleAuthor.domain.entity.CaseClinicalArticleAuthorEntity;
|
||||
import net.lab1024.sa.admin.module.business.caseClinicalArticleAuthor.domain.vo.CaseClinicalArticleAuthorVO;
|
||||
import net.lab1024.sa.admin.module.business.caseClinicalDoctor.dao.CaseClinicalDoctorDao;
|
||||
import net.lab1024.sa.admin.module.business.caseClinicalDoctor.domain.entity.CaseClinicalDoctorEntity;
|
||||
import net.lab1024.sa.admin.module.business.caseClinicalDoctor.domain.vo.CaseClinicalDoctorVO;
|
||||
import net.lab1024.sa.base.common.util.SmartBeanUtil;
|
||||
import net.lab1024.sa.base.common.util.SmartPageUtil;
|
||||
import net.lab1024.sa.base.common.domain.ResponseDTO;
|
||||
import net.lab1024.sa.base.common.domain.PageResult;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import net.lab1024.sa.base.common.util.SmartResponseUtil;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
import net.lab1024.sa.admin.util.Replace;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.transaction.interceptor.TransactionAspectSupport;
|
||||
|
||||
/**
|
||||
* 病例库-临床-文章 Service
|
||||
*
|
||||
* @Author xing
|
||||
* @Date 2025-08-04 10:17:15
|
||||
* @Copyright gdxz
|
||||
*/
|
||||
|
||||
@Service
|
||||
public class CaseClinicalArticleService {
|
||||
|
||||
@Resource
|
||||
private CaseClinicalArticleDao caseClinicalArticleDao;
|
||||
|
||||
@Resource
|
||||
private CaseClinicalService caseClinicalService;
|
||||
|
||||
@Resource
|
||||
private StatsCaseClinicalDao statsCaseClinicalDao;
|
||||
|
||||
@Resource
|
||||
private CaseClinicalArticleAuthorDao caseClinicalArticleAuthorDao;
|
||||
|
||||
@Resource
|
||||
private CaseClinicalDoctorDao caseClinicalDoctorDao;
|
||||
|
||||
@Resource
|
||||
private BasicHospitalDao basicHospitalDao;
|
||||
|
||||
@Resource
|
||||
private WxMaServiceUtils wxMaServiceUtils;
|
||||
|
||||
@Resource
|
||||
private CaseClinicalArticleLabelDao caseClinicalArticleLabelDao;
|
||||
|
||||
@Resource
|
||||
private UserService userService;
|
||||
|
||||
@Resource
|
||||
private CaseClinicalDoctorCertDao caseClinicalDoctorCertDao;
|
||||
|
||||
@Value("${spring.profiles.active:prod}")
|
||||
private String activeProfile;
|
||||
|
||||
/**
|
||||
* 分页查询
|
||||
*/
|
||||
public PageResult<CaseClinicalArticleVO> queryPage(CaseClinicalArticleQueryForm queryForm) {
|
||||
Page<?> page = SmartPageUtil.convert2PageQuery(queryForm);
|
||||
List<CaseClinicalArticleVO> list = caseClinicalArticleDao.queryPage(page, queryForm);
|
||||
for (CaseClinicalArticleVO vo : list) {
|
||||
// 获取作者数据
|
||||
LambdaQueryWrapper<CaseClinicalArticleAuthorEntity> authorQueryWrapper = new LambdaQueryWrapper<>();
|
||||
authorQueryWrapper.eq(CaseClinicalArticleAuthorEntity::getArticleId, vo.getArticleId());
|
||||
List<CaseClinicalArticleAuthorEntity> caseClinicalArticleAuthors = caseClinicalArticleAuthorDao.selectList(authorQueryWrapper);
|
||||
|
||||
List<CaseClinicalArticleAuthorVO> caseClinicalArticleAuthorVOs = SmartBeanUtil.copyList(caseClinicalArticleAuthors, CaseClinicalArticleAuthorVO.class);
|
||||
|
||||
// 为每个作者VO设置医生数据
|
||||
for (CaseClinicalArticleAuthorVO authorVO : caseClinicalArticleAuthorVOs) {
|
||||
// 查询医生
|
||||
CaseClinicalDoctorEntity caseClinicalDoctor = caseClinicalDoctorDao.selectById(authorVO.getDoctorId());
|
||||
if (caseClinicalDoctor != null) {
|
||||
// 查询医生所属医院
|
||||
BasicHospitalEntity basicHospital = basicHospitalDao.selectById(caseClinicalDoctor.getHospitalId());
|
||||
if (basicHospital != null) {
|
||||
caseClinicalDoctor.setBasicHospital(basicHospital);
|
||||
}
|
||||
|
||||
// 转换为VO并设置医院信息
|
||||
CaseClinicalDoctorVO caseClinicalDoctorVO = SmartBeanUtil.copy(caseClinicalDoctor, CaseClinicalDoctorVO.class);
|
||||
if (basicHospital != null) {
|
||||
caseClinicalDoctorVO.setHospitalName(basicHospital.getHospitalName());
|
||||
caseClinicalDoctorVO.setHospitalProvince(basicHospital.getProvince());
|
||||
caseClinicalDoctorVO.setHospitalCity(basicHospital.getCity());
|
||||
}
|
||||
|
||||
authorVO.setCaseClinicalDoctor(caseClinicalDoctorVO);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
vo.setCaseClinicalArticleAuthor(caseClinicalArticleAuthorVOs);
|
||||
|
||||
// 获取标签数据
|
||||
LambdaQueryWrapper<CaseClinicalArticleLabelEntity> labelQueryWrapper = new LambdaQueryWrapper<>();
|
||||
labelQueryWrapper.eq(CaseClinicalArticleLabelEntity::getArticleId, vo.getArticleId());
|
||||
List<CaseClinicalArticleLabelEntity> caseClinicalArticleLabels = caseClinicalArticleLabelDao.selectList(labelQueryWrapper);
|
||||
|
||||
// 转换为VO
|
||||
List<CaseClinicalArticleLabelVO> caseClinicalArticleLabelVOs = SmartBeanUtil.copyList(caseClinicalArticleLabels, CaseClinicalArticleLabelVO.class);
|
||||
vo.setCaseClinicalArticleLabel(caseClinicalArticleLabelVOs);
|
||||
}
|
||||
|
||||
return SmartPageUtil.convert2PageResult(page, list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加
|
||||
*/
|
||||
@Transactional
|
||||
public ResponseDTO<String> add(CaseClinicalArticleAddForm addForm) {
|
||||
// 新增文章
|
||||
CaseClinicalArticleEntity caseClinicalArticle = SmartBeanUtil.copy(addForm, CaseClinicalArticleEntity.class);
|
||||
caseClinicalArticleDao.insert(caseClinicalArticle);
|
||||
|
||||
// 新增统计
|
||||
IncClinicalArticleStats(String.valueOf(caseClinicalArticle.getArticleId()),4,1);
|
||||
|
||||
// 生成文章分享二维码
|
||||
byte[] qrcodeBytes = addUnlimitedQrcode(caseClinicalArticle.getArticleId());
|
||||
if (qrcodeBytes == null || qrcodeBytes.length == 0) {
|
||||
return ResponseDTO.userErrorParam("添加失败");
|
||||
}
|
||||
|
||||
// 处理文章作者
|
||||
HandleArticleAuthor(caseClinicalArticle,addForm.getAuthorList(),qrcodeBytes);
|
||||
|
||||
// 处理文章标签
|
||||
HandleArticleLabel(caseClinicalArticle,addForm.getLabelList());
|
||||
|
||||
return ResponseDTO.ok();
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新
|
||||
*
|
||||
*/
|
||||
@Transactional
|
||||
public ResponseDTO<String> update(CaseClinicalArticleUpdateForm updateForm) {
|
||||
// 获取文章数据
|
||||
CaseClinicalArticleEntity caseClinicalArticle = caseClinicalArticleDao.selectById(updateForm.getArticleId());
|
||||
if (caseClinicalArticle == null) {
|
||||
throw new BusinessException("修改失败");
|
||||
}
|
||||
|
||||
// 修改
|
||||
if (!Objects.equals(caseClinicalArticle.getArticleTitle(), updateForm.getArticleTitle())) {
|
||||
caseClinicalArticle.setArticleTitle(updateForm.getArticleTitle());
|
||||
}
|
||||
|
||||
if (!Objects.equals(caseClinicalArticle.getPushDate(), updateForm.getPushDate())) {
|
||||
caseClinicalArticle.setPushDate(updateForm.getPushDate());
|
||||
}
|
||||
|
||||
if (!Objects.equals(caseClinicalArticle.getIsLink(), updateForm.getIsLink())) {
|
||||
caseClinicalArticle.setIsLink(updateForm.getIsLink());
|
||||
}
|
||||
|
||||
if (!Objects.equals(caseClinicalArticle.getIsLinkUrl(), updateForm.getIsLinkUrl())) {
|
||||
caseClinicalArticle.setIsLinkUrl(updateForm.getIsLinkUrl());
|
||||
}
|
||||
|
||||
if (!Objects.equals(caseClinicalArticle.getArticleContent(), updateForm.getArticleContent())) {
|
||||
caseClinicalArticle.setArticleContent(updateForm.getArticleContent());
|
||||
}
|
||||
|
||||
// 如果文章状态发生改变,修正统计数据
|
||||
if (!Objects.equals(caseClinicalArticle.getArticleStatus(), updateForm.getArticleStatus())) {
|
||||
caseClinicalArticle.setArticleStatus(updateForm.getArticleStatus());
|
||||
|
||||
// 修改统计数量
|
||||
DecClinicalArticleStats(String.valueOf(caseClinicalArticle.getArticleId()),4,1);
|
||||
|
||||
// 获取标签数据
|
||||
LambdaQueryWrapper<CaseClinicalArticleLabelEntity> labelQueryWrapper = new LambdaQueryWrapper<>();
|
||||
labelQueryWrapper.eq(CaseClinicalArticleLabelEntity::getArticleId, caseClinicalArticle.getArticleId());
|
||||
List<CaseClinicalArticleLabelEntity> caseClinicalArticleLabels = caseClinicalArticleLabelDao.selectList(labelQueryWrapper);
|
||||
for (CaseClinicalArticleLabelEntity label : caseClinicalArticleLabels){
|
||||
// 减少标签统计
|
||||
caseClinicalService.DecStatsCaseClinicalLabel(label.getAppIden(),1);
|
||||
}
|
||||
|
||||
// 获取作者数据
|
||||
LambdaQueryWrapper<CaseClinicalArticleAuthorEntity> authorQueryWrapper = new LambdaQueryWrapper<>();
|
||||
authorQueryWrapper.eq(CaseClinicalArticleAuthorEntity::getArticleId, caseClinicalArticle.getArticleId());
|
||||
List<CaseClinicalArticleAuthorEntity> caseClinicalArticleAuthors = caseClinicalArticleAuthorDao.selectList(authorQueryWrapper);
|
||||
for (CaseClinicalArticleAuthorEntity author : caseClinicalArticleAuthors){
|
||||
// 获取医生数据
|
||||
LambdaQueryWrapper<CaseClinicalDoctorEntity> doctorQueryWrapper = new LambdaQueryWrapper<>();
|
||||
doctorQueryWrapper.eq(CaseClinicalDoctorEntity::getDoctorId,author.getDoctorId());
|
||||
CaseClinicalDoctorEntity caseClinicalDoctor = caseClinicalDoctorDao.selectOne(doctorQueryWrapper);
|
||||
if (caseClinicalDoctor == null) {
|
||||
throw new BusinessException("无法完成此操作");
|
||||
}
|
||||
|
||||
// 减少医生统计
|
||||
caseClinicalService.DecStatsCaseClinicalDoctor(String.valueOf(author.getDoctorId()),1);
|
||||
|
||||
// 减少医院统计
|
||||
caseClinicalService.DecStatsCaseClinicalHospital(String.valueOf(caseClinicalDoctor.getHospitalId()),1);
|
||||
}
|
||||
}
|
||||
|
||||
caseClinicalArticleDao.updateById(caseClinicalArticle);
|
||||
|
||||
// 处理文章作者
|
||||
HandleArticleAuthor(caseClinicalArticle,updateForm.getAuthorList(),null);
|
||||
|
||||
// 处理文章标签
|
||||
HandleArticleLabel(caseClinicalArticle,updateForm.getLabelList());
|
||||
|
||||
return ResponseDTO.ok();
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除
|
||||
*/
|
||||
@Transactional
|
||||
public ResponseDTO<String> batchDelete(List<Long> idList) {
|
||||
if (CollectionUtils.isEmpty(idList)){
|
||||
return ResponseDTO.ok();
|
||||
}
|
||||
|
||||
for (Long articleId : idList) {
|
||||
if (null == articleId){
|
||||
throw new BusinessException("删除失败");
|
||||
}
|
||||
|
||||
CaseClinicalArticleEntity caseClinicalArticle = caseClinicalArticleDao.selectById(articleId);
|
||||
if (caseClinicalArticle == null){
|
||||
throw new BusinessException("删除失败");
|
||||
}
|
||||
|
||||
// 修改为删除
|
||||
caseClinicalArticle.setDeleteStatus(1);
|
||||
caseClinicalArticleDao.updateById(caseClinicalArticle);
|
||||
|
||||
// 修改统计数量
|
||||
DecClinicalArticleStats(String.valueOf(caseClinicalArticle.getArticleId()),4,1);
|
||||
|
||||
// 获取视频标签数据
|
||||
LambdaQueryWrapper<CaseClinicalArticleLabelEntity> labelQueryWrapper = new LambdaQueryWrapper<>();
|
||||
labelQueryWrapper.eq(CaseClinicalArticleLabelEntity::getArticleId, caseClinicalArticle.getArticleId());
|
||||
List<CaseClinicalArticleLabelEntity> caseClinicalArticleLabels = caseClinicalArticleLabelDao.selectList(labelQueryWrapper);
|
||||
for (CaseClinicalArticleLabelEntity label : caseClinicalArticleLabels){
|
||||
// 减少标签统计
|
||||
caseClinicalService.DecStatsCaseClinicalLabel(label.getAppIden(),1);
|
||||
}
|
||||
|
||||
// 获取作者数据
|
||||
LambdaQueryWrapper<CaseClinicalArticleAuthorEntity> authorQueryWrapper = new LambdaQueryWrapper<>();
|
||||
authorQueryWrapper.eq(CaseClinicalArticleAuthorEntity::getArticleId, caseClinicalArticle.getArticleId());
|
||||
List<CaseClinicalArticleAuthorEntity> caseClinicalArticleAuthors = caseClinicalArticleAuthorDao.selectList(authorQueryWrapper);
|
||||
for (CaseClinicalArticleAuthorEntity author : caseClinicalArticleAuthors){
|
||||
// 获取医生数据
|
||||
LambdaQueryWrapper<CaseClinicalDoctorEntity> doctorQueryWrapper = new LambdaQueryWrapper<>();
|
||||
doctorQueryWrapper.eq(CaseClinicalDoctorEntity::getDoctorId,author.getDoctorId());
|
||||
CaseClinicalDoctorEntity caseClinicalDoctor = caseClinicalDoctorDao.selectOne(doctorQueryWrapper);
|
||||
if (caseClinicalDoctor == null) {
|
||||
throw new BusinessException("无法完成此操作");
|
||||
}
|
||||
|
||||
// 减少医生统计
|
||||
caseClinicalService.DecStatsCaseClinicalDoctor(String.valueOf(author.getDoctorId()),1);
|
||||
|
||||
// 减少医院统计
|
||||
caseClinicalService.DecStatsCaseClinicalHospital(String.valueOf(caseClinicalDoctor.getHospitalId()),1);
|
||||
}
|
||||
|
||||
caseClinicalArticleDao.deleteById(articleId);
|
||||
}
|
||||
|
||||
return ResponseDTO.ok();
|
||||
}
|
||||
|
||||
/**
|
||||
* 单个删除
|
||||
*/
|
||||
public ResponseDTO<String> delete(Long articleId) {
|
||||
if (null == articleId){
|
||||
return ResponseDTO.ok();
|
||||
}
|
||||
|
||||
CaseClinicalArticleEntity caseClinicalArticle = caseClinicalArticleDao.selectById(articleId);
|
||||
if (caseClinicalArticle == null){
|
||||
return ResponseDTO.userErrorParam("删除失败");
|
||||
}
|
||||
|
||||
// 修改为删除
|
||||
caseClinicalArticle.setDeleteStatus(1);
|
||||
caseClinicalArticleDao.updateById(caseClinicalArticle);
|
||||
|
||||
// 修改统计数量
|
||||
DecClinicalArticleStats(String.valueOf(caseClinicalArticle.getArticleId()),4,1);
|
||||
|
||||
// 获取视频标签数据
|
||||
LambdaQueryWrapper<CaseClinicalArticleLabelEntity> labelQueryWrapper = new LambdaQueryWrapper<>();
|
||||
labelQueryWrapper.eq(CaseClinicalArticleLabelEntity::getArticleId, caseClinicalArticle.getArticleId());
|
||||
List<CaseClinicalArticleLabelEntity> caseClinicalArticleLabels = caseClinicalArticleLabelDao.selectList(labelQueryWrapper);
|
||||
for (CaseClinicalArticleLabelEntity label : caseClinicalArticleLabels){
|
||||
// 减少标签统计
|
||||
caseClinicalService.DecStatsCaseClinicalLabel(label.getAppIden(),1);
|
||||
}
|
||||
|
||||
// 获取作者数据
|
||||
LambdaQueryWrapper<CaseClinicalArticleAuthorEntity> authorQueryWrapper = new LambdaQueryWrapper<>();
|
||||
authorQueryWrapper.eq(CaseClinicalArticleAuthorEntity::getArticleId, caseClinicalArticle.getArticleId());
|
||||
List<CaseClinicalArticleAuthorEntity> caseClinicalArticleAuthors = caseClinicalArticleAuthorDao.selectList(authorQueryWrapper);
|
||||
for (CaseClinicalArticleAuthorEntity author : caseClinicalArticleAuthors){
|
||||
// 获取医生数据
|
||||
LambdaQueryWrapper<CaseClinicalDoctorEntity> doctorQueryWrapper = new LambdaQueryWrapper<>();
|
||||
doctorQueryWrapper.eq(CaseClinicalDoctorEntity::getDoctorId,author.getDoctorId());
|
||||
CaseClinicalDoctorEntity caseClinicalDoctor = caseClinicalDoctorDao.selectOne(doctorQueryWrapper);
|
||||
if (caseClinicalDoctor == null) {
|
||||
throw new BusinessException("无法完成此操作");
|
||||
}
|
||||
|
||||
// 减少医生统计
|
||||
caseClinicalService.DecStatsCaseClinicalDoctor(String.valueOf(author.getDoctorId()),1);
|
||||
|
||||
// 减少医院统计
|
||||
caseClinicalService.DecStatsCaseClinicalHospital(String.valueOf(caseClinicalDoctor.getHospitalId()),1);
|
||||
}
|
||||
|
||||
return ResponseDTO.ok();
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成文章分享二维码
|
||||
*/
|
||||
public byte[] addUnlimitedQrcode(Long articleId) {
|
||||
try {
|
||||
// 检查文章是否存在
|
||||
CaseClinicalArticleEntity article = caseClinicalArticleDao.selectById(articleId);
|
||||
if (article == null) {
|
||||
throw new BusinessException("文章不存在");
|
||||
}
|
||||
|
||||
// 生成二维码参数
|
||||
String scene = "?id=" + articleId + "&type=1";
|
||||
String page = "pages/detail/detail";
|
||||
|
||||
// 生成二维码
|
||||
byte[] qrcodeBytes = wxMaServiceUtils.getUnlimitedQrcode(scene, page);
|
||||
|
||||
// 生成文件名
|
||||
String fileName;
|
||||
String no = "a" + articleId;
|
||||
|
||||
// 根据环境设置路径
|
||||
String envPath = Objects.equals(activeProfile, "dev") ? "dev/" : "prod/";
|
||||
fileName = envPath + "static/images/" + no + ".png";
|
||||
|
||||
// 上传到OSS
|
||||
boolean res = Oss.putObject(fileName, qrcodeBytes);
|
||||
if (!res) {
|
||||
throw new BusinessException("上传二维码失败");
|
||||
}
|
||||
|
||||
// 更新文章记录
|
||||
article.setShareQrcode("/" + fileName);
|
||||
caseClinicalArticleDao.updateById(article);
|
||||
|
||||
return qrcodeBytes;
|
||||
} catch (Exception e) {
|
||||
throw new BusinessException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取文章详情
|
||||
*/
|
||||
public ResponseDTO<CaseClinicalArticleVO> getDetail(Long articleId) {
|
||||
CaseClinicalArticleEntity entity = caseClinicalArticleDao.selectById(articleId);
|
||||
if (entity == null) {
|
||||
return ResponseDTO.userErrorParam("文章不存在");
|
||||
}
|
||||
|
||||
CaseClinicalArticleVO vo = SmartBeanUtil.copy(entity, CaseClinicalArticleVO.class);
|
||||
|
||||
// 获取作者数据
|
||||
LambdaQueryWrapper<CaseClinicalArticleAuthorEntity> authorQueryWrapper = new LambdaQueryWrapper<>();
|
||||
authorQueryWrapper.eq(CaseClinicalArticleAuthorEntity::getArticleId, articleId);
|
||||
List<CaseClinicalArticleAuthorEntity> caseClinicalArticleAuthors = caseClinicalArticleAuthorDao.selectList(authorQueryWrapper);
|
||||
|
||||
List<CaseClinicalArticleAuthorVO> caseClinicalArticleAuthorVOs = SmartBeanUtil.copyList(caseClinicalArticleAuthors, CaseClinicalArticleAuthorVO.class);
|
||||
|
||||
// 为每个作者VO设置医生数据
|
||||
for (CaseClinicalArticleAuthorVO authorVO : caseClinicalArticleAuthorVOs) {
|
||||
// 查询医生
|
||||
CaseClinicalDoctorEntity caseClinicalDoctor = caseClinicalDoctorDao.selectById(authorVO.getDoctorId());
|
||||
if (caseClinicalDoctor != null) {
|
||||
// 查询医生所属医院
|
||||
BasicHospitalEntity basicHospital = basicHospitalDao.selectById(caseClinicalDoctor.getHospitalId());
|
||||
if (basicHospital != null) {
|
||||
caseClinicalDoctor.setBasicHospital(basicHospital);
|
||||
}
|
||||
|
||||
// 转换为VO并设置医院信息
|
||||
CaseClinicalDoctorVO caseClinicalDoctorVO = SmartBeanUtil.copy(caseClinicalDoctor, CaseClinicalDoctorVO.class);
|
||||
if (basicHospital != null) {
|
||||
caseClinicalDoctorVO.setHospitalName(basicHospital.getHospitalName());
|
||||
caseClinicalDoctorVO.setHospitalProvince(basicHospital.getProvince());
|
||||
caseClinicalDoctorVO.setHospitalCity(basicHospital.getCity());
|
||||
}
|
||||
|
||||
authorVO.setCaseClinicalDoctor(caseClinicalDoctorVO);
|
||||
}
|
||||
}
|
||||
|
||||
vo.setCaseClinicalArticleAuthor(caseClinicalArticleAuthorVOs);
|
||||
|
||||
// 获取标签数据
|
||||
LambdaQueryWrapper<CaseClinicalArticleLabelEntity> labelQueryWrapper = new LambdaQueryWrapper<>();
|
||||
labelQueryWrapper.eq(CaseClinicalArticleLabelEntity::getArticleId, articleId);
|
||||
List<CaseClinicalArticleLabelEntity> caseClinicalArticleLabels = caseClinicalArticleLabelDao.selectList(labelQueryWrapper);
|
||||
|
||||
// 转换为VO
|
||||
List<CaseClinicalArticleLabelVO> caseClinicalArticleLabelVOs = SmartBeanUtil.copyList(caseClinicalArticleLabels, CaseClinicalArticleLabelVO.class);
|
||||
vo.setCaseClinicalArticleLabel(caseClinicalArticleLabelVOs);
|
||||
|
||||
vo.setShareQrcode(Replace.addOssDomain(vo.getShareQrcode()));
|
||||
return ResponseDTO.ok(vo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新文章状态
|
||||
*/
|
||||
public ResponseDTO<String> updateStatus(Long articleId, Integer status) {
|
||||
if (null == articleId) {
|
||||
return ResponseDTO.userErrorParam("文章ID不能为空");
|
||||
}
|
||||
|
||||
CaseClinicalArticleEntity caseClinicalArticle = caseClinicalArticleDao.selectById(articleId);
|
||||
if (caseClinicalArticle == null) {
|
||||
return ResponseDTO.userErrorParam("文章不存在");
|
||||
}
|
||||
|
||||
// 如果状态没有变化,直接返回
|
||||
if (Objects.equals(caseClinicalArticle.getArticleStatus(), status)) {
|
||||
return ResponseDTO.ok();
|
||||
}
|
||||
|
||||
// 更新状态
|
||||
caseClinicalArticle.setArticleStatus(status);
|
||||
caseClinicalArticleDao.updateById(caseClinicalArticle);
|
||||
|
||||
// 如果状态发生改变,修正统计数据
|
||||
if (status == 2) {
|
||||
// 状态改为禁用,减少统计数量
|
||||
DecClinicalArticleStats(String.valueOf(caseClinicalArticle.getArticleId()), 4, 1);
|
||||
|
||||
// 获取标签数据
|
||||
LambdaQueryWrapper<CaseClinicalArticleLabelEntity> labelQueryWrapper = new LambdaQueryWrapper<>();
|
||||
labelQueryWrapper.eq(CaseClinicalArticleLabelEntity::getArticleId, caseClinicalArticle.getArticleId());
|
||||
List<CaseClinicalArticleLabelEntity> caseClinicalArticleLabels = caseClinicalArticleLabelDao.selectList(labelQueryWrapper);
|
||||
for (CaseClinicalArticleLabelEntity label : caseClinicalArticleLabels) {
|
||||
// 减少标签统计
|
||||
caseClinicalService.DecStatsCaseClinicalLabel(label.getAppIden(), 1);
|
||||
}
|
||||
|
||||
// 获取作者数据
|
||||
LambdaQueryWrapper<CaseClinicalArticleAuthorEntity> authorQueryWrapper = new LambdaQueryWrapper<>();
|
||||
authorQueryWrapper.eq(CaseClinicalArticleAuthorEntity::getArticleId, caseClinicalArticle.getArticleId());
|
||||
List<CaseClinicalArticleAuthorEntity> caseClinicalArticleAuthors = caseClinicalArticleAuthorDao.selectList(authorQueryWrapper);
|
||||
for (CaseClinicalArticleAuthorEntity author : caseClinicalArticleAuthors) {
|
||||
// 获取医生数据
|
||||
LambdaQueryWrapper<CaseClinicalDoctorEntity> doctorQueryWrapper = new LambdaQueryWrapper<>();
|
||||
doctorQueryWrapper.eq(CaseClinicalDoctorEntity::getDoctorId, author.getDoctorId());
|
||||
CaseClinicalDoctorEntity caseClinicalDoctor = caseClinicalDoctorDao.selectOne(doctorQueryWrapper);
|
||||
if (caseClinicalDoctor == null) {
|
||||
throw new BusinessException("无法完成此操作");
|
||||
}
|
||||
|
||||
// 减少医生统计
|
||||
caseClinicalService.DecStatsCaseClinicalDoctor(String.valueOf(author.getDoctorId()), 1);
|
||||
|
||||
// 减少医院统计
|
||||
caseClinicalService.DecStatsCaseClinicalHospital(String.valueOf(caseClinicalDoctor.getHospitalId()), 1);
|
||||
}
|
||||
} else if (status == 1) {
|
||||
// 状态改为正常,增加统计数量
|
||||
IncClinicalArticleStats(String.valueOf(caseClinicalArticle.getArticleId()), 4, 1);
|
||||
|
||||
// 获取标签数据
|
||||
LambdaQueryWrapper<CaseClinicalArticleLabelEntity> labelQueryWrapper = new LambdaQueryWrapper<>();
|
||||
labelQueryWrapper.eq(CaseClinicalArticleLabelEntity::getArticleId, caseClinicalArticle.getArticleId());
|
||||
List<CaseClinicalArticleLabelEntity> caseClinicalArticleLabels = caseClinicalArticleLabelDao.selectList(labelQueryWrapper);
|
||||
for (CaseClinicalArticleLabelEntity label : caseClinicalArticleLabels) {
|
||||
// 增加标签统计
|
||||
LocalDateTime lastPushDate = caseClinicalArticleDao.selectLastArticlePushDateByLabelId(label.getAppIden());
|
||||
caseClinicalService.IncStatsCaseClinicalLabel(label.getAppIden(), label.getLabelName(), 1, lastPushDate);
|
||||
}
|
||||
|
||||
// 获取作者数据
|
||||
LambdaQueryWrapper<CaseClinicalArticleAuthorEntity> authorQueryWrapper = new LambdaQueryWrapper<>();
|
||||
authorQueryWrapper.eq(CaseClinicalArticleAuthorEntity::getArticleId, caseClinicalArticle.getArticleId());
|
||||
List<CaseClinicalArticleAuthorEntity> caseClinicalArticleAuthors = caseClinicalArticleAuthorDao.selectList(authorQueryWrapper);
|
||||
for (CaseClinicalArticleAuthorEntity author : caseClinicalArticleAuthors) {
|
||||
// 获取医生数据
|
||||
LambdaQueryWrapper<CaseClinicalDoctorEntity> doctorQueryWrapper = new LambdaQueryWrapper<>();
|
||||
doctorQueryWrapper.eq(CaseClinicalDoctorEntity::getDoctorId, author.getDoctorId());
|
||||
CaseClinicalDoctorEntity caseClinicalDoctor = caseClinicalDoctorDao.selectOne(doctorQueryWrapper);
|
||||
if (caseClinicalDoctor == null) {
|
||||
throw new BusinessException("无法完成此操作");
|
||||
}
|
||||
|
||||
// 增加医生统计
|
||||
LocalDateTime lastPushDate = caseClinicalArticleDao.selectLastArticlePushDateByDoctorId(caseClinicalDoctor.getDoctorId());
|
||||
caseClinicalService.IncStatsCaseClinicalDoctor(String.valueOf(author.getDoctorId()), 1, lastPushDate);
|
||||
|
||||
// 增加医院统计
|
||||
caseClinicalService.IncStatsCaseClinicalHospital(String.valueOf(caseClinicalDoctor.getHospitalId()), 1, lastPushDate);
|
||||
}
|
||||
}
|
||||
|
||||
return ResponseDTO.ok();
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增文章的统计字段
|
||||
* @param articleId 文章id
|
||||
* @param type 类型:1:阅读量 2:收藏量 3:评论数 4:文章数
|
||||
*/
|
||||
public boolean IncClinicalArticleStats(String articleId,Integer type,Integer num){
|
||||
try {
|
||||
String caseClinicalArticleField = ""; // 具体文章
|
||||
String statsCaseClinicalField = ""; // 全部文章
|
||||
|
||||
// 阅读
|
||||
if (type == 1){
|
||||
caseClinicalArticleField = "read_num"; // 具体文章
|
||||
statsCaseClinicalField = "article_read_num"; // 全部文章
|
||||
}
|
||||
|
||||
// 收藏
|
||||
if (type == 2){
|
||||
caseClinicalArticleField = "collect_num"; // 具体文章
|
||||
statsCaseClinicalField = "article_collect_num"; // 全部文章
|
||||
}
|
||||
|
||||
// 评论
|
||||
if (type == 3){
|
||||
caseClinicalArticleField = "comment_num"; // 具体文章
|
||||
statsCaseClinicalField = "article_comment_num"; // 全部文章
|
||||
}
|
||||
|
||||
// 文章数
|
||||
if (type == 4){
|
||||
statsCaseClinicalField = "article_num"; // 全部文章
|
||||
}
|
||||
|
||||
if (!caseClinicalArticleField.isEmpty()){
|
||||
caseClinicalArticleDao.inc(Long.valueOf(articleId),caseClinicalArticleField,num);
|
||||
}
|
||||
statsCaseClinicalDao.inc(1L,statsCaseClinicalField,num);
|
||||
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 减少文章的统计字段
|
||||
* @param articleId 文章id
|
||||
* @param type 类型:1:阅读量 2:收藏量 3:评论数 4:文章数
|
||||
*/
|
||||
public boolean DecClinicalArticleStats(String articleId,Integer type,Integer num){
|
||||
try {
|
||||
String caseClinicalArticleField = ""; // 具体文章
|
||||
String statsCaseClinicalField = ""; // 全部文章
|
||||
|
||||
// 阅读
|
||||
if (type == 1){
|
||||
caseClinicalArticleField = "read_num"; // 具体文章
|
||||
statsCaseClinicalField = "article_read_num"; // 全部文章
|
||||
}
|
||||
|
||||
// 收藏
|
||||
if (type == 2){
|
||||
caseClinicalArticleField = "collect_num"; // 具体文章
|
||||
statsCaseClinicalField = "article_collect_num"; // 全部文章
|
||||
}
|
||||
|
||||
// 评论
|
||||
if (type == 3){
|
||||
caseClinicalArticleField = "comment_num"; // 具体文章
|
||||
statsCaseClinicalField = "article_comment_num"; // 全部文章
|
||||
}
|
||||
|
||||
// 文章数
|
||||
if (type == 4){
|
||||
statsCaseClinicalField = "article_num"; // 全部文章
|
||||
}
|
||||
|
||||
if (!caseClinicalArticleField.isEmpty()){
|
||||
caseClinicalArticleDao.dec(Long.valueOf(articleId),caseClinicalArticleField,num);
|
||||
}
|
||||
statsCaseClinicalDao.dec(1L,statsCaseClinicalField,num);
|
||||
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// 处理文章作者
|
||||
public void HandleArticleAuthor(CaseClinicalArticleEntity caseClinicalArticle,List<CaseClinicalArticleAuthorForm> r,byte[] qrCodeBytes){
|
||||
// 需新增的
|
||||
List<CaseClinicalArticleAuthorForm> addList = new ArrayList<>();
|
||||
|
||||
// 需删除的
|
||||
List<CaseClinicalArticleAuthorEntity> deleteList = new ArrayList<>();
|
||||
|
||||
// 获取全部作者
|
||||
LambdaQueryWrapper<CaseClinicalArticleAuthorEntity> authorQueryWrapper = new LambdaQueryWrapper<>();
|
||||
authorQueryWrapper.eq(CaseClinicalArticleAuthorEntity::getArticleId, caseClinicalArticle.getArticleId());
|
||||
List<CaseClinicalArticleAuthorEntity> caseClinicalArticleAuthors = caseClinicalArticleAuthorDao.selectList(authorQueryWrapper);
|
||||
|
||||
// 处理新增的情况
|
||||
for (CaseClinicalArticleAuthorForm a : r){
|
||||
// 默认本条为新增
|
||||
boolean exists = true;
|
||||
for (CaseClinicalArticleAuthorEntity b : caseClinicalArticleAuthors){
|
||||
if (Objects.equals(a.getDoctorId(), b.getDoctorId())){
|
||||
exists = false;
|
||||
break; // 已存在,跳出内层循环
|
||||
}
|
||||
}
|
||||
|
||||
if (exists) {
|
||||
addList.add(a); // 不存在于旧数据中,加入新增列表
|
||||
}
|
||||
}
|
||||
|
||||
// 处理删除的情况
|
||||
for (CaseClinicalArticleAuthorEntity b : caseClinicalArticleAuthors){
|
||||
// 默认本条为删除
|
||||
boolean exists = true;
|
||||
for (CaseClinicalArticleAuthorForm a : r){
|
||||
if (Objects.equals(a.getDoctorId(), b.getDoctorId())){
|
||||
exists = false;
|
||||
break; // 已存在,跳出内层循环
|
||||
}
|
||||
}
|
||||
|
||||
if (exists) {
|
||||
deleteList.add(b); // 加入删除列表
|
||||
}
|
||||
}
|
||||
|
||||
// 删除
|
||||
for (CaseClinicalArticleAuthorEntity author : deleteList){
|
||||
// 获取医生数据
|
||||
LambdaQueryWrapper<CaseClinicalDoctorEntity> doctorQueryWrapper = new LambdaQueryWrapper<>();
|
||||
doctorQueryWrapper.eq(CaseClinicalDoctorEntity::getDoctorId, author.getDoctorId());
|
||||
CaseClinicalDoctorEntity caseClinicalDoctor = caseClinicalDoctorDao.selectOne(doctorQueryWrapper);
|
||||
if (caseClinicalDoctor == null) {
|
||||
throw new BusinessException("操作失败");
|
||||
}
|
||||
|
||||
// 获取医院数据
|
||||
BasicHospitalEntity basicHospital = basicHospitalDao.selectById(caseClinicalDoctor.getHospitalId());
|
||||
if (basicHospital == null) {
|
||||
throw new BusinessException("操作失败");
|
||||
}
|
||||
|
||||
// 减少作者统计
|
||||
caseClinicalService.DecStatsCaseClinicalDoctor(String.valueOf(caseClinicalDoctor.getDoctorId()),1);
|
||||
|
||||
// 减少医院统计
|
||||
caseClinicalService.DecStatsCaseClinicalHospital(String.valueOf(caseClinicalDoctor.getHospitalId()),1);
|
||||
|
||||
// 删除该作者
|
||||
caseClinicalArticleAuthorDao.deleteById(author.getAuthorId());
|
||||
|
||||
// 删除该作者证书
|
||||
LambdaQueryWrapper<CaseClinicalDoctorCertEntity> certWrapper = new LambdaQueryWrapper<>();
|
||||
certWrapper.eq(CaseClinicalDoctorCertEntity::getDoctorId, caseClinicalDoctor.getDoctorId());
|
||||
certWrapper.eq(CaseClinicalDoctorCertEntity::getId, caseClinicalArticle.getArticleId());
|
||||
certWrapper.eq(CaseClinicalDoctorCertEntity::getType, 1);
|
||||
caseClinicalDoctorCertDao.delete(certWrapper);
|
||||
}
|
||||
|
||||
// 新增新的作者
|
||||
for (CaseClinicalArticleAuthorForm author : addList){
|
||||
CaseClinicalDoctorEntity caseClinicalDoctor = caseClinicalDoctorDao.selectById(author.getDoctorId());
|
||||
|
||||
CaseClinicalArticleAuthorEntity caseClinicalArticleAuthor = new CaseClinicalArticleAuthorEntity();
|
||||
caseClinicalArticleAuthor.setArticleId(caseClinicalArticle.getArticleId());
|
||||
caseClinicalArticleAuthor.setDoctorId(caseClinicalDoctor.getDoctorId());
|
||||
caseClinicalArticleAuthorDao.insert(caseClinicalArticleAuthor);
|
||||
|
||||
LocalDateTime lastPushDate = caseClinicalArticleDao.selectLastArticlePushDateByDoctorId(caseClinicalDoctor.getDoctorId());
|
||||
|
||||
// 新增作者统计
|
||||
caseClinicalService.IncStatsCaseClinicalDoctor(String.valueOf(caseClinicalDoctor.getDoctorId()),1,lastPushDate);
|
||||
|
||||
// 新增医院统计
|
||||
caseClinicalService.IncStatsCaseClinicalHospital(String.valueOf(caseClinicalDoctor.getHospitalId()),1,lastPushDate);
|
||||
|
||||
// 生成用户证书-文章/视频
|
||||
if (qrCodeBytes == null || qrCodeBytes.length == 0) {
|
||||
// 生成二维码图片
|
||||
if (caseClinicalArticle.getShareQrcode() == null){
|
||||
try {
|
||||
// 生成用户分享二维码-文章/视频
|
||||
qrCodeBytes = addUnlimitedQrcode(caseClinicalArticle.getArticleId());
|
||||
} catch (Exception e) {
|
||||
// 不处理
|
||||
throw new BusinessException("操作失败");
|
||||
}
|
||||
}else{
|
||||
// 下载二维码图片
|
||||
qrCodeBytes = Oss.getObjectToByte(caseClinicalArticle.getShareQrcode().replaceFirst("^/+", ""));
|
||||
if (qrCodeBytes == null) {
|
||||
throw new BusinessException("操作失败");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 下载头像
|
||||
byte[] avatarByte = new byte[0];
|
||||
if (caseClinicalDoctor.getAvatar() != null && !caseClinicalDoctor.getAvatar().isEmpty()) {
|
||||
avatarByte = Oss.getObjectToByte(caseClinicalDoctor.getAvatar().replaceFirst("^/+", ""));
|
||||
}else{
|
||||
try {
|
||||
avatarByte = ImageUtil.readImageToBytes("static/cert/avatar.png");
|
||||
} catch (Exception e) {
|
||||
throw new BusinessException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
if (avatarByte == null) {
|
||||
throw new BusinessException("操作失败");
|
||||
}
|
||||
|
||||
userService.CreateUserCert(
|
||||
String.valueOf(caseClinicalArticle.getArticleId()),
|
||||
1,
|
||||
String.valueOf(caseClinicalDoctor.getDoctorId()),
|
||||
qrCodeBytes,
|
||||
avatarByte
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// 处理文章标签
|
||||
public void HandleArticleLabel(CaseClinicalArticleEntity caseClinicalArticle, List<CaseClinicalArticleLabelForm> r){
|
||||
// 获取全部b标签
|
||||
LambdaQueryWrapper<CaseClinicalArticleLabelEntity> labelQueryWrapper = new LambdaQueryWrapper<>();
|
||||
labelQueryWrapper.eq(CaseClinicalArticleLabelEntity::getArticleId, caseClinicalArticle.getArticleId());
|
||||
List<CaseClinicalArticleLabelEntity> caseClinicalArticleLabels = caseClinicalArticleLabelDao.selectList(labelQueryWrapper);
|
||||
for (CaseClinicalArticleLabelEntity label : caseClinicalArticleLabels){
|
||||
// 减少标签统计
|
||||
caseClinicalService.DecStatsCaseClinicalLabel(label.getAppIden(),1);
|
||||
|
||||
// 删除视频标签
|
||||
caseClinicalArticleLabelDao.deleteById(label.getArticleLabelId());
|
||||
}
|
||||
|
||||
for (CaseClinicalArticleLabelForm label : r){
|
||||
CaseClinicalArticleLabelEntity caseClinicalArticleLabel = new CaseClinicalArticleLabelEntity();
|
||||
caseClinicalArticleLabel.setArticleId(caseClinicalArticle.getArticleId());
|
||||
caseClinicalArticleLabel.setAppIden(label.getAppIden());
|
||||
caseClinicalArticleLabel.setLabelName(label.getLabelName());
|
||||
caseClinicalArticleLabelDao.insert(caseClinicalArticleLabel);
|
||||
|
||||
LocalDateTime lastPushDate = caseClinicalArticleDao.selectLastArticlePushDateByLabelId(label.getAppIden());
|
||||
|
||||
// 新增标签统计
|
||||
caseClinicalService.IncStatsCaseClinicalLabel(label.getAppIden(),caseClinicalArticleLabel.getLabelName(),1,lastPushDate);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,40 @@
|
||||
package net.lab1024.sa.admin.module.business.caseClinicalArticleAuthor.controller;
|
||||
|
||||
import net.lab1024.sa.admin.module.business.caseClinicalArticleAuthor.domain.form.CaseClinicalArticleAuthorQueryForm;
|
||||
import net.lab1024.sa.admin.module.business.caseClinicalArticleAuthor.domain.vo.CaseClinicalArticleAuthorVO;
|
||||
import net.lab1024.sa.admin.module.business.caseClinicalArticleAuthor.service.CaseClinicalArticleAuthorService;
|
||||
import net.lab1024.sa.base.common.domain.ResponseDTO;
|
||||
import net.lab1024.sa.base.common.domain.PageResult;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.validation.Valid;
|
||||
|
||||
/**
|
||||
* 病例库-临床-文章-作者 Controller
|
||||
*
|
||||
* @Author xing
|
||||
* @Date 2025-08-05 08:45:33
|
||||
* @Copyright gdxz
|
||||
*/
|
||||
|
||||
@RestController
|
||||
@Tag(name = "病例库-临床-文章-作者")
|
||||
public class CaseClinicalArticleAuthorController {
|
||||
|
||||
@Resource
|
||||
private CaseClinicalArticleAuthorService caseClinicalArticleAuthorService;
|
||||
|
||||
@Operation(summary = "分页查询 @author xing")
|
||||
@PostMapping("/caseClinicalArticleAuthor/queryPage")
|
||||
@SaCheckPermission("caseClinicalArticleAuthor:query")
|
||||
public ResponseDTO<PageResult<CaseClinicalArticleAuthorVO>> queryPage(@RequestBody @Valid CaseClinicalArticleAuthorQueryForm queryForm) {
|
||||
return ResponseDTO.ok(caseClinicalArticleAuthorService.queryPage(queryForm));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,33 @@
|
||||
package net.lab1024.sa.admin.module.business.caseClinicalArticleAuthor.dao;
|
||||
|
||||
import java.util.List;
|
||||
import net.lab1024.sa.admin.module.business.caseClinicalArticleAuthor.domain.entity.CaseClinicalArticleAuthorEntity;
|
||||
import net.lab1024.sa.admin.module.business.caseClinicalArticleAuthor.domain.form.CaseClinicalArticleAuthorQueryForm;
|
||||
import net.lab1024.sa.admin.module.business.caseClinicalArticleAuthor.domain.vo.CaseClinicalArticleAuthorVO;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 病例库-临床-文章-作者 Dao
|
||||
*
|
||||
* @Author xing
|
||||
* @Date 2025-08-05 08:45:33
|
||||
* @Copyright gdxz
|
||||
*/
|
||||
|
||||
@Mapper
|
||||
public interface CaseClinicalArticleAuthorDao extends BaseMapper<CaseClinicalArticleAuthorEntity> {
|
||||
|
||||
/**
|
||||
* 分页 查询
|
||||
*
|
||||
* @param page
|
||||
* @param queryForm
|
||||
* @return
|
||||
*/
|
||||
List<CaseClinicalArticleAuthorVO> queryPage(Page page, @Param("queryForm") CaseClinicalArticleAuthorQueryForm queryForm);
|
||||
|
||||
}
|
||||
@ -0,0 +1,56 @@
|
||||
package net.lab1024.sa.admin.module.business.caseClinicalArticleAuthor.domain.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import net.lab1024.sa.admin.module.business.caseClinicalDoctor.domain.entity.CaseClinicalDoctorEntity;
|
||||
import net.lab1024.sa.admin.module.business.caseClinicalDoctor.domain.vo.CaseClinicalDoctorVO;
|
||||
|
||||
/**
|
||||
* 病例库-临床-文章-作者 实体类
|
||||
*
|
||||
* @Author xing
|
||||
* @Date 2025-08-05 08:45:33
|
||||
* @Copyright gdxz
|
||||
*/
|
||||
|
||||
@Data
|
||||
@TableName("case_clinical_article_author")
|
||||
public class CaseClinicalArticleAuthorEntity {
|
||||
|
||||
/**
|
||||
* 主键id
|
||||
*/
|
||||
@TableId
|
||||
private Long authorId;
|
||||
|
||||
/**
|
||||
* 临床文章id
|
||||
*/
|
||||
private Long articleId;
|
||||
|
||||
/**
|
||||
* 医生id
|
||||
*/
|
||||
private Long doctorId;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private LocalDateTime createdAt;
|
||||
|
||||
/**
|
||||
* 修改时间
|
||||
*/
|
||||
private LocalDateTime updatedAt;
|
||||
|
||||
/**
|
||||
* 医生数据
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
private CaseClinicalDoctorEntity caseClinicalDoctor;
|
||||
}
|
||||
@ -0,0 +1,19 @@
|
||||
package net.lab1024.sa.admin.module.business.caseClinicalArticleAuthor.domain.form;
|
||||
|
||||
import net.lab1024.sa.base.common.domain.PageParam;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
/**
|
||||
* 病例库-临床-文章-作者 分页查询表单
|
||||
*
|
||||
* @Author xing
|
||||
* @Date 2025-08-05 08:45:33
|
||||
* @Copyright gdxz
|
||||
*/
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
public class CaseClinicalArticleAuthorQueryForm extends PageParam {
|
||||
|
||||
}
|
||||
@ -0,0 +1,42 @@
|
||||
package net.lab1024.sa.admin.module.business.caseClinicalArticleAuthor.domain.vo;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import lombok.Data;
|
||||
import net.lab1024.sa.admin.module.business.caseClinicalArticleAuthor.domain.entity.CaseClinicalArticleAuthorEntity;
|
||||
import net.lab1024.sa.admin.module.business.caseClinicalDoctor.domain.vo.CaseClinicalDoctorVO;
|
||||
|
||||
/**
|
||||
* 病例库-临床-文章-作者 列表VO
|
||||
*
|
||||
* @Author xing
|
||||
* @Date 2025-08-05 08:45:33
|
||||
* @Copyright gdxz
|
||||
*/
|
||||
|
||||
@Data
|
||||
public class CaseClinicalArticleAuthorVO {
|
||||
@Schema(description = "主键id")
|
||||
private Long authorId;
|
||||
|
||||
@Schema(description = "临床文章id")
|
||||
private Long articleId;
|
||||
|
||||
@Schema(description = "医生id")
|
||||
private Long doctorId;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
private LocalDateTime createdAt;
|
||||
|
||||
@Schema(description = "修改时间")
|
||||
private LocalDateTime updatedAt;
|
||||
|
||||
@Schema(description = "医生数据")
|
||||
private CaseClinicalDoctorVO caseClinicalDoctor;
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
package net.lab1024.sa.admin.module.business.caseClinicalArticleAuthor.manager;
|
||||
|
||||
import net.lab1024.sa.admin.module.business.caseClinicalArticleAuthor.domain.entity.CaseClinicalArticleAuthorEntity;
|
||||
import net.lab1024.sa.admin.module.business.caseClinicalArticleAuthor.dao.CaseClinicalArticleAuthorDao;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* 病例库-临床-文章-作者 Manager
|
||||
*
|
||||
* @Author xing
|
||||
* @Date 2025-08-05 08:45:33
|
||||
* @Copyright gdxz
|
||||
*/
|
||||
@Service
|
||||
public class CaseClinicalArticleAuthorManager extends ServiceImpl<CaseClinicalArticleAuthorDao, CaseClinicalArticleAuthorEntity> {
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,42 @@
|
||||
package net.lab1024.sa.admin.module.business.caseClinicalArticleAuthor.service;
|
||||
|
||||
import java.util.List;
|
||||
import net.lab1024.sa.admin.module.business.caseClinicalArticleAuthor.dao.CaseClinicalArticleAuthorDao;
|
||||
import net.lab1024.sa.admin.module.business.caseClinicalArticleAuthor.domain.entity.CaseClinicalArticleAuthorEntity;
|
||||
import net.lab1024.sa.admin.module.business.caseClinicalArticleAuthor.domain.form.CaseClinicalArticleAuthorQueryForm;
|
||||
import net.lab1024.sa.admin.module.business.caseClinicalArticleAuthor.domain.vo.CaseClinicalArticleAuthorVO;
|
||||
import net.lab1024.sa.base.common.util.SmartBeanUtil;
|
||||
import net.lab1024.sa.base.common.util.SmartPageUtil;
|
||||
import net.lab1024.sa.base.common.domain.ResponseDTO;
|
||||
import net.lab1024.sa.base.common.domain.PageResult;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
|
||||
/**
|
||||
* 病例库-临床-文章-作者 Service
|
||||
*
|
||||
* @Author xing
|
||||
* @Date 2025-08-05 08:45:33
|
||||
* @Copyright gdxz
|
||||
*/
|
||||
|
||||
@Service
|
||||
public class CaseClinicalArticleAuthorService {
|
||||
|
||||
@Resource
|
||||
private CaseClinicalArticleAuthorDao caseClinicalArticleAuthorDao;
|
||||
|
||||
/**
|
||||
* 分页查询
|
||||
*/
|
||||
public PageResult<CaseClinicalArticleAuthorVO> queryPage(CaseClinicalArticleAuthorQueryForm queryForm) {
|
||||
Page<?> page = SmartPageUtil.convert2PageQuery(queryForm);
|
||||
List<CaseClinicalArticleAuthorVO> list = caseClinicalArticleAuthorDao.queryPage(page, queryForm);
|
||||
return SmartPageUtil.convert2PageResult(page, list);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,105 @@
|
||||
package net.lab1024.sa.admin.module.business.caseClinicalDoctor.controller;
|
||||
|
||||
import net.lab1024.sa.admin.module.business.caseClinicalDoctor.domain.form.CaseClinicalDoctorAddForm;
|
||||
import net.lab1024.sa.admin.module.business.caseClinicalDoctor.domain.form.CaseClinicalDoctorQueryForm;
|
||||
import net.lab1024.sa.admin.module.business.caseClinicalDoctor.domain.form.CaseClinicalDoctorQueryListForm;
|
||||
import net.lab1024.sa.admin.module.business.caseClinicalDoctor.domain.form.CaseClinicalDoctorUpdateForm;
|
||||
import net.lab1024.sa.admin.module.business.caseClinicalDoctor.domain.form.CaseClinicalDoctorStatusUpdateForm;
|
||||
import net.lab1024.sa.admin.module.business.caseClinicalDoctor.domain.vo.CaseClinicalDoctorVO;
|
||||
import net.lab1024.sa.admin.module.business.caseClinicalDoctor.domain.vo.AppDoctorVO;
|
||||
import net.lab1024.sa.admin.module.business.caseClinicalDoctor.service.CaseClinicalDoctorService;
|
||||
import net.lab1024.sa.base.common.domain.ValidateList;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import net.lab1024.sa.base.common.domain.ResponseDTO;
|
||||
import net.lab1024.sa.base.common.domain.PageResult;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.validation.Valid;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 医生管理 Controller
|
||||
*
|
||||
* @Author xing
|
||||
* @Date 2025-08-04 15:24:56
|
||||
* @Copyright gdxz
|
||||
*/
|
||||
|
||||
@RestController
|
||||
@Tag(name = "医生管理")
|
||||
public class CaseClinicalDoctorController {
|
||||
|
||||
@Resource
|
||||
private CaseClinicalDoctorService caseClinicalDoctorService;
|
||||
|
||||
@Operation(summary = "分页查询 @author xing")
|
||||
@PostMapping("/caseClinicalDoctor/queryPage")
|
||||
@SaCheckPermission("caseClinicalDoctor:query")
|
||||
public ResponseDTO<PageResult<CaseClinicalDoctorVO>> queryPage(@RequestBody @Valid CaseClinicalDoctorQueryForm queryForm) {
|
||||
return ResponseDTO.ok(caseClinicalDoctorService.queryPage(queryForm));
|
||||
}
|
||||
|
||||
@Operation(summary = "列表查询 @author xing")
|
||||
@PostMapping("/caseClinicalDoctor/queryList")
|
||||
@SaCheckPermission("caseClinicalDoctor:query")
|
||||
public ResponseDTO<List<CaseClinicalDoctorVO>> queryList(@RequestBody @Valid CaseClinicalDoctorQueryListForm queryForm) {
|
||||
return ResponseDTO.ok(caseClinicalDoctorService.queryList(queryForm));
|
||||
}
|
||||
|
||||
@Operation(summary = "添加 @author xing")
|
||||
@PostMapping("/caseClinicalDoctor/add")
|
||||
@SaCheckPermission("caseClinicalDoctor:add")
|
||||
public ResponseDTO<String> add(@RequestBody @Valid CaseClinicalDoctorAddForm addForm) {
|
||||
return caseClinicalDoctorService.add(addForm);
|
||||
}
|
||||
|
||||
@Operation(summary = "更新 @author xing")
|
||||
@PostMapping("/caseClinicalDoctor/update")
|
||||
@SaCheckPermission("caseClinicalDoctor:update")
|
||||
public ResponseDTO<String> update(@RequestBody @Valid CaseClinicalDoctorUpdateForm updateForm) {
|
||||
return caseClinicalDoctorService.update(updateForm);
|
||||
}
|
||||
|
||||
@Operation(summary = "批量删除 @author xing")
|
||||
@PostMapping("/caseClinicalDoctor/batchDelete")
|
||||
@SaCheckPermission("caseClinicalDoctor:delete")
|
||||
public ResponseDTO<String> batchDelete(@RequestBody ValidateList<Long> idList) {
|
||||
return caseClinicalDoctorService.batchDelete(idList);
|
||||
}
|
||||
|
||||
@Operation(summary = "单个删除 @author xing")
|
||||
@GetMapping("/caseClinicalDoctor/delete/{doctorId}")
|
||||
@SaCheckPermission("caseClinicalDoctor:delete")
|
||||
public ResponseDTO<String> batchDelete(@PathVariable Long doctorId) {
|
||||
return caseClinicalDoctorService.delete(doctorId);
|
||||
}
|
||||
|
||||
@Operation(summary = "更新状态 @author xing")
|
||||
@PostMapping("/caseClinicalDoctor/status/update")
|
||||
@SaCheckPermission("caseClinicalDoctor:update")
|
||||
public ResponseDTO<String> updateStatus(@RequestBody @Valid CaseClinicalDoctorStatusUpdateForm updateForm) {
|
||||
return caseClinicalDoctorService.updateStatus(updateForm.getDoctorId(), updateForm.getStatus());
|
||||
}
|
||||
|
||||
@Operation(summary = "获取APP医生信息 @author xing")
|
||||
@GetMapping("/caseClinicalDoctor/getAppDoctor")
|
||||
@SaCheckPermission("caseClinicalDoctor:query")
|
||||
public ResponseDTO<AppDoctorVO> getAppDoctor(@RequestParam String doctorName) {
|
||||
return caseClinicalDoctorService.getAppDoctor(doctorName);
|
||||
}
|
||||
|
||||
@Operation(summary = "获取医生详情 @author xing")
|
||||
@GetMapping("/caseClinicalDoctor/getDetail/{doctorId}")
|
||||
@SaCheckPermission("caseClinicalDoctor:query")
|
||||
public ResponseDTO<CaseClinicalDoctorVO> getDetail(@PathVariable Long doctorId) {
|
||||
return caseClinicalDoctorService.getDetail(doctorId);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,24 @@
|
||||
package net.lab1024.sa.admin.module.business.caseClinicalDoctor.dao;
|
||||
|
||||
import java.util.List;
|
||||
import net.lab1024.sa.admin.module.business.caseClinicalDoctor.domain.entity.CaseClinicalDoctorCertEntity;
|
||||
import net.lab1024.sa.admin.module.business.caseClinicalDoctor.domain.vo.CaseClinicalDoctorCertVO;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 医生证书 Dao
|
||||
*
|
||||
* @Author xing
|
||||
* @Date 2025-08-06 11:22:22
|
||||
* @Copyright gdxz
|
||||
*/
|
||||
|
||||
@Mapper
|
||||
public interface CaseClinicalDoctorCertDao extends BaseMapper<CaseClinicalDoctorCertEntity> {
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,42 @@
|
||||
package net.lab1024.sa.admin.module.business.caseClinicalDoctor.dao;
|
||||
|
||||
import java.util.List;
|
||||
import net.lab1024.sa.admin.module.business.caseClinicalDoctor.domain.entity.CaseClinicalDoctorEntity;
|
||||
import net.lab1024.sa.admin.module.business.caseClinicalDoctor.domain.form.CaseClinicalDoctorQueryForm;
|
||||
import net.lab1024.sa.admin.module.business.caseClinicalDoctor.domain.form.CaseClinicalDoctorQueryListForm;
|
||||
import net.lab1024.sa.admin.module.business.caseClinicalDoctor.domain.vo.CaseClinicalDoctorVO;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 医生管理 Dao
|
||||
*
|
||||
* @Author xing
|
||||
* @Date 2025-08-04 15:24:56
|
||||
* @Copyright gdxz
|
||||
*/
|
||||
|
||||
@Mapper
|
||||
public interface CaseClinicalDoctorDao extends BaseMapper<CaseClinicalDoctorEntity> {
|
||||
|
||||
/**
|
||||
* 分页 查询
|
||||
*
|
||||
* @param page
|
||||
* @param queryForm
|
||||
* @return
|
||||
*/
|
||||
List<CaseClinicalDoctorVO> queryPage(Page page, @Param("queryForm") CaseClinicalDoctorQueryForm queryForm);
|
||||
|
||||
/**
|
||||
* 列表 查询
|
||||
*
|
||||
* @param queryForm
|
||||
* @return
|
||||
*/
|
||||
List<CaseClinicalDoctorVO> queryList(@Param("queryForm") CaseClinicalDoctorQueryListForm queryForm);
|
||||
|
||||
}
|
||||
@ -0,0 +1,56 @@
|
||||
package net.lab1024.sa.admin.module.business.caseClinicalDoctor.domain.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import java.time.LocalDateTime;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 医生证书 实体类
|
||||
*
|
||||
* @Author xing
|
||||
* @Date 2025-08-06 11:22:22
|
||||
* @Copyright gdxz
|
||||
*/
|
||||
|
||||
@Data
|
||||
@TableName("case_clinical_doctor_cert")
|
||||
public class CaseClinicalDoctorCertEntity {
|
||||
|
||||
/**
|
||||
* 主键id
|
||||
*/
|
||||
@TableId
|
||||
private Long certId;
|
||||
|
||||
/**
|
||||
* 医生id
|
||||
*/
|
||||
private Long doctorId;
|
||||
|
||||
/**
|
||||
* 关联的视频/文章id
|
||||
*/
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 类型(1:文章 2:视频)
|
||||
*/
|
||||
private Integer type;
|
||||
|
||||
/**
|
||||
* 证书图片
|
||||
*/
|
||||
private String certImage;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private LocalDateTime createdAt;
|
||||
|
||||
/**
|
||||
* 修改时间
|
||||
*/
|
||||
private LocalDateTime updatedAt;
|
||||
|
||||
}
|
||||
@ -0,0 +1,69 @@
|
||||
package net.lab1024.sa.admin.module.business.caseClinicalDoctor.domain.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import java.time.LocalDateTime;
|
||||
import lombok.Data;
|
||||
import net.lab1024.sa.admin.module.business.basicHospital.domain.entity.BasicHospitalEntity;
|
||||
|
||||
/**
|
||||
* 医生管理 实体类
|
||||
*
|
||||
* @Author xing
|
||||
* @Date 2025-08-04 15:24:56
|
||||
* @Copyright gdxz
|
||||
*/
|
||||
|
||||
@Data
|
||||
@TableName("case_clinical_doctor")
|
||||
public class CaseClinicalDoctorEntity {
|
||||
|
||||
/**
|
||||
* 主键id
|
||||
*/
|
||||
@TableId
|
||||
private Long doctorId;
|
||||
|
||||
/**
|
||||
* app唯一标识(存在即表示为注册用户)
|
||||
*/
|
||||
private String doctorIden;
|
||||
|
||||
/**
|
||||
* 用户名称
|
||||
*/
|
||||
private String doctorName;
|
||||
|
||||
/**
|
||||
* 所属医院id
|
||||
*/
|
||||
private Long hospitalId;
|
||||
|
||||
/**
|
||||
* 状态(1:正常 2:禁用)
|
||||
*/
|
||||
private Integer status;
|
||||
|
||||
/**
|
||||
* 头像
|
||||
*/
|
||||
private String avatar;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private LocalDateTime createdAt;
|
||||
|
||||
/**
|
||||
* 修改时间
|
||||
*/
|
||||
private LocalDateTime updatedAt;
|
||||
|
||||
/**
|
||||
* 医院数据
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
private BasicHospitalEntity basicHospital;
|
||||
|
||||
}
|
||||
@ -0,0 +1,40 @@
|
||||
package net.lab1024.sa.admin.module.business.caseClinicalDoctor.domain.form;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonAlias;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
import net.lab1024.sa.base.common.json.deserializer.FileKeyVoDeserializer;
|
||||
|
||||
/**
|
||||
* 医生管理 新建表单
|
||||
*
|
||||
* @Author xing
|
||||
* @Date 2025-08-04 15:24:56
|
||||
* @Copyright gdxz
|
||||
*/
|
||||
|
||||
@Data
|
||||
public class CaseClinicalDoctorAddForm {
|
||||
|
||||
@Schema(description = "用户名称", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotBlank(message = "用户名称 不能为空")
|
||||
private String doctorName;
|
||||
|
||||
@Schema(description = "app唯一标识(可用uuid入参)")
|
||||
@JsonAlias({"uuid"})
|
||||
private String doctorIden;
|
||||
|
||||
@Schema(description = "所属医院id", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotNull(message = "所属医院id 不能为空")
|
||||
private Long hospitalId;
|
||||
|
||||
@Schema(description = "医院UUID")
|
||||
private String hospitalUuid;
|
||||
|
||||
@Schema(description = "状态(1:正常 2:禁用)", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotNull(message = "状态(1:正常 2:禁用) 不能为空")
|
||||
private Integer status = 1;
|
||||
}
|
||||
@ -0,0 +1,29 @@
|
||||
package net.lab1024.sa.admin.module.business.caseClinicalDoctor.domain.form;
|
||||
|
||||
import net.lab1024.sa.base.common.domain.PageParam;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
/**
|
||||
* 医生管理 分页查询表单
|
||||
*
|
||||
* @Author xing
|
||||
* @Date 2025-08-04 15:24:56
|
||||
* @Copyright gdxz
|
||||
*/
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
public class CaseClinicalDoctorQueryForm extends PageParam {
|
||||
|
||||
@Schema(description = "医生姓名")
|
||||
private String keywords;
|
||||
|
||||
@Schema(description = "医院名称")
|
||||
private String hospitalName;
|
||||
|
||||
@Schema(description = "状态")
|
||||
private Integer status;
|
||||
|
||||
}
|
||||
@ -0,0 +1,23 @@
|
||||
package net.lab1024.sa.admin.module.business.caseClinicalDoctor.domain.form;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import net.lab1024.sa.base.common.domain.PageParam;
|
||||
|
||||
/**
|
||||
* 医生管理 分页查询表单
|
||||
*
|
||||
* @Author xing
|
||||
* @Date 2025-08-04 15:24:56
|
||||
* @Copyright gdxz
|
||||
*/
|
||||
|
||||
@Data
|
||||
public class CaseClinicalDoctorQueryListForm {
|
||||
@Schema(description = "医生姓名")
|
||||
private String keywords;
|
||||
|
||||
@Schema(description = "数量")
|
||||
private Integer limit = 10;
|
||||
}
|
||||
@ -0,0 +1,26 @@
|
||||
package net.lab1024.sa.admin.module.business.caseClinicalDoctor.domain.form;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
|
||||
/**
|
||||
* 医生管理 状态更新表单
|
||||
*
|
||||
* @Author xing
|
||||
* @Date 2025-08-04 15:24:56
|
||||
* @Copyright gdxz
|
||||
*/
|
||||
@Data
|
||||
@Schema(description = "医生管理 状态更新表单")
|
||||
public class CaseClinicalDoctorStatusUpdateForm {
|
||||
|
||||
@Schema(description = "医生ID")
|
||||
@NotNull(message = "医生ID不能为空")
|
||||
private Long doctorId;
|
||||
|
||||
@Schema(description = "状态 1:正常 2:禁用")
|
||||
@NotNull(message = "状态不能为空")
|
||||
private Integer status;
|
||||
}
|
||||
@ -0,0 +1,37 @@
|
||||
package net.lab1024.sa.admin.module.business.caseClinicalDoctor.domain.form;
|
||||
|
||||
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
import net.lab1024.sa.base.common.json.deserializer.FileKeyVoDeserializer;
|
||||
|
||||
/**
|
||||
* 医生管理 更新表单
|
||||
*
|
||||
* @Author xing
|
||||
* @Date 2025-08-04 15:24:56
|
||||
* @Copyright gdxz
|
||||
*/
|
||||
|
||||
@Data
|
||||
public class CaseClinicalDoctorUpdateForm {
|
||||
|
||||
@Schema(description = "主键id", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotNull(message = "主键id 不能为空")
|
||||
private Long doctorId;
|
||||
|
||||
@Schema(description = "用户名称", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotBlank(message = "用户名称 不能为空")
|
||||
private String doctorName;
|
||||
|
||||
@Schema(description = "状态(1:正常 2:禁用)", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotNull(message = "状态(1:正常 2:禁用) 不能为空")
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "头像", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@JsonDeserialize(using = FileKeyVoDeserializer.class)
|
||||
private String avatar;
|
||||
|
||||
}
|
||||
@ -0,0 +1,37 @@
|
||||
package net.lab1024.sa.admin.module.business.caseClinicalDoctor.domain.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* APP医生信息 VO
|
||||
*
|
||||
* @Author xing
|
||||
* @Date 2025-08-04 15:24:56
|
||||
* @Copyright gdxz
|
||||
*/
|
||||
@Data
|
||||
@Schema(description = "APP医生信息")
|
||||
public class AppDoctorVO {
|
||||
|
||||
@Schema(description = "UUID")
|
||||
private String uuid;
|
||||
|
||||
@Schema(description = "姓名")
|
||||
private String doctorName;
|
||||
|
||||
@Schema(description = "手机号")
|
||||
private String phone;
|
||||
|
||||
@Schema(description = "省份")
|
||||
private String province;
|
||||
|
||||
@Schema(description = "医院UUID")
|
||||
private String hospitalUuid;
|
||||
|
||||
@Schema(description = "医院ID")
|
||||
private Long hospitalId;
|
||||
|
||||
@Schema(description = "医院名称")
|
||||
private String hospitalName;
|
||||
}
|
||||
@ -0,0 +1,40 @@
|
||||
package net.lab1024.sa.admin.module.business.caseClinicalDoctor.domain.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import java.time.LocalDateTime;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 医生证书 列表VO
|
||||
*
|
||||
* @Author xing
|
||||
* @Date 2025-08-06 11:22:22
|
||||
* @Copyright gdxz
|
||||
*/
|
||||
|
||||
@Data
|
||||
public class CaseClinicalDoctorCertVO {
|
||||
|
||||
|
||||
@Schema(description = "主键id")
|
||||
private Long certId;
|
||||
|
||||
@Schema(description = "医生id")
|
||||
private Long doctorId;
|
||||
|
||||
@Schema(description = "关联的视频/文章id")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "类型(1:文章 2:视频)")
|
||||
private Integer type;
|
||||
|
||||
@Schema(description = "证书图片")
|
||||
private String certImage;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
private LocalDateTime createdAt;
|
||||
|
||||
@Schema(description = "修改时间")
|
||||
private LocalDateTime updatedAt;
|
||||
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user