初始化

This commit is contained in:
砂糖
2025-11-08 10:38:36 +08:00
commit 3beeec7296
1626 changed files with 198488 additions and 0 deletions

View File

@@ -0,0 +1,32 @@
package com.gccloud.dataroom.core.config;
import com.gccloud.dataroom.core.config.bean.DemoEnv;
import com.gccloud.dataroom.core.config.bean.FileConfig;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.NestedConfigurationProperty;
import org.springframework.context.annotation.Configuration;
/**
* @Author qianxing
* @Date 2020-06-16
* @Version 1.0.0
*/
@Slf4j
@Configuration
@ConfigurationProperties(prefix = "gc.starter")
@Data
public class DataRoomConfig {
/**
* 文件存储配置
*/
@NestedConfigurationProperty
private FileConfig file = new FileConfig();
/**
* 演示环境
*/
@NestedConfigurationProperty
private DemoEnv demoEnv = new DemoEnv();
}

View File

@@ -0,0 +1,50 @@
package com.gccloud.dataroom.core.config;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.datatype.jsonorg.JSONArraySerializer;
import com.fasterxml.jackson.datatype.jsonorg.JsonOrgModule;
import com.gccloud.dataroom.core.constant.DataRoomConst;
import lombok.extern.slf4j.Slf4j;
import oracle.sql.CLOB;
import oracle.sql.TIMESTAMP;
import org.json.JSONArray;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Configuration;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
/**
* Jackson配置类
* @Author hongyang
* @Date 2022/06/19
* @Version 1.0.0
*/
@Slf4j
@Configuration
@ConditionalOnMissingClass(value = "com.gccloud.dashboard.core.config.ObjectMapperConfiguration")
@ConditionalOnProperty(prefix = "gc.starter.dataroom.component", name = "ObjectMapperConfiguration", havingValue = "ObjectMapperConfiguration", matchIfMissing = true)
public class DataRoomObjectMapperConfiguration {
@Resource
private ObjectMapper objectMapper;
@PostConstruct
public void init() {
log.info(DataRoomConst.Console.LINE);
log.info("注册 Jackson JsonOrgModule 模块");
// 不注册该模块会导致 @RequestBody 为 JSONObject 时属性无法填充
JsonOrgModule jsonOrgModule = new JsonOrgModule();
objectMapper.registerModule(jsonOrgModule);
SimpleModule simpleModule = new SimpleModule();
// 解决 接口响应中包含JSONObject 或 JSONArray时, 序列化失败,变成{empty: false} 的问题
simpleModule.addSerializer(JSONArray.class, JSONArraySerializer.instance);
simpleModule.addSerializer(CLOB.class, new OracleClobSerializer());
simpleModule.addSerializer(TIMESTAMP.class, new OracleTimestampSerializer());
objectMapper.registerModule(simpleModule);
log.info(DataRoomConst.Console.LINE);
}
}

View File

@@ -0,0 +1,42 @@
package com.gccloud.dataroom.core.config;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import lombok.extern.slf4j.Slf4j;
import oracle.sql.CLOB;
import org.apache.commons.lang3.exception.ExceptionUtils;
import java.io.IOException;
import java.sql.Clob;
/**
* 解决oracle CLOB类型返回序列化问题
* @author hongyang
* @version 1.0
* @date 2024/03/22 17:30
*/
@Slf4j
public class OracleClobSerializer extends JsonSerializer<CLOB> {
@Override
public void serialize(CLOB clob, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
jsonGenerator.writeString(clobToString(clob));
}
/**
* Clob字段处理
*
* @param clob
* @return
*/
public static String clobToString(Clob clob) {
String content = "";
try {
content = clob.getSubString(1, (int) clob.length());
} catch (Exception e) {
log.error(ExceptionUtils.getStackTrace(e));
}
return content;
}
}

View File

@@ -0,0 +1,42 @@
package com.gccloud.dataroom.core.config;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import lombok.extern.slf4j.Slf4j;
import oracle.sql.TIMESTAMP;
import org.apache.commons.lang3.exception.ExceptionUtils;
import java.io.IOException;
/**
* 解决oracle TIMESTAMP类型返回序列化问题
* @author hongyang
* @version 1.0
* @date 2024/05/07 10:30
*/
@Slf4j
public class OracleTimestampSerializer extends JsonSerializer<TIMESTAMP> {
@Override
public void serialize(TIMESTAMP timestamp, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
jsonGenerator.writeString(timestampToString(timestamp));
}
/**
* timestamp字段处理
*
* @param timestamp
* @return
*/
public static String timestampToString(TIMESTAMP timestamp) {
String content = "";
try {
// 转为日期格式
content = timestamp.stringValue();
} catch (Exception e) {
log.error(ExceptionUtils.getStackTrace(e));
}
return content;
}
}

View File

@@ -0,0 +1,108 @@
package com.gccloud.dataroom.core.config.bean;
import lombok.Data;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
/**
* @author hongyang
* @version 1.0
* @date 2023/10/17 15:18
*/
@Data
@Configuration
@ConfigurationProperties(prefix = "gc.starter.file.ftp")
public class DataRoomFtpConfig extends GenericObjectPoolConfig {
/**
* ftp服务器地址
*/
private String host;
/**
* ftp服务器端口
*/
private Integer port;
/**
* ftp服务器用户名
*/
private String username;
/**
* ftp服务器密码
*/
private String password;
/**
* 传输编码
*/
String encoding = "utf-8";
/**
* 被动模式:在这种模式下,数据连接是由客户程序发起的
*/
boolean passiveMode = true;
/**
* 连接超时时间
*/
int clientTimeout = 30000;
/**
* 0=ASCII_FILE_TYPE(ASCII格式)1=EBCDIC_FILE_TYPE2=LOCAL_FILE_TYPE(二进制文件)
*/
int transferFileType = 2;
/**
* 重新连接时间
*/
int retryTimes;
/**
* 缓存大小
*/
int bufferSize = 1024;
/* 连接池配置 */
/**
* 最大连接数
*/
int maxTotal = DEFAULT_MAX_TOTAL;
/**
* 最小空闲
*/
int minIdle = DEFAULT_MIN_IDLE;
/**
* 最大空闲
*/
int maxIdle = DEFAULT_MAX_IDLE;
/**
* 最大等待时间 10s
*/
int maxWait = 10000;
/**
* 池对象耗尽之后是否阻塞maxWait < 0 时一直等待
*/
boolean blockWhenExhausted = DEFAULT_BLOCK_WHEN_EXHAUSTED;
/**
* 取对象时验证
*/
boolean testOnBorrow = true ;
/**
* 回收验证
*/
boolean testOnReturn = true;
/**
* 创建时验证
*/
boolean testOnCreate = true;
/**
* 空闲验证
*/
boolean testWhileIdle = true;
/**
* 后进先出
*/
boolean lifo = DEFAULT_LIFO;
}

View File

@@ -0,0 +1,50 @@
package com.gccloud.dataroom.core.config.bean;
import com.gccloud.common.exception.GlobalException;
import io.minio.MinioClient;
import lombok.Data;
import org.apache.commons.lang3.StringUtils;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* Minio 配置信息
*
* @author Acechengui
*/
@Data
@Configuration
@ConfigurationProperties(prefix = "gc.starter.file.minio")
public class DataRoomMinioConfig
{
/**
* 服务地址
*/
private String url;
/**
* 用户名
*/
private String accessKey;
/**
* 密码
*/
private String secretKey;
/**
* 存储桶名称
*/
private String bucketName;
@Bean
@ConditionalOnProperty(prefix = "gc.starter.file", name = "type", havingValue = "minio")
public MinioClient getMinioClient() {
if (StringUtils.isBlank(bucketName)) {
throw new GlobalException("Minio bucketName 不能为空");
}
return MinioClient.builder().endpoint(url).credentials(accessKey, secretKey).build();
}
}

View File

@@ -0,0 +1,94 @@
package com.gccloud.dataroom.core.config.bean;
import lombok.Data;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
/**
* @author hongyang
* @version 1.0
* @date 2023/10/17 15:18
*/
@Configuration
@ConfigurationProperties(prefix = "gc.starter.file.sftp")
@Data
public class DataRoomSftpConfig extends GenericObjectPoolConfig {
/**
* sftp服务器地址
*/
private String host;
/**
* sftp服务器端口
*/
private Integer port;
/**
* sftp服务器用户名
*/
private String username;
/**
* sftp服务器密码
*/
private String password;
/**
* 私钥
*/
private String privateKey;
/**
* 缓存大小
*/
int bufferSize = 1024;
/* 连接池配置 */
/**
* 最大连接数
*/
int maxTotal = DEFAULT_MAX_TOTAL;
/**
* 最小空闲
*/
int minIdle = DEFAULT_MIN_IDLE;
/**
* 最大空闲
*/
int maxIdle = DEFAULT_MAX_IDLE;
/**
* 最大等待时间 10s
*/
int maxWait = 10000;
/**
* 池对象耗尽之后是否阻塞maxWait < 0 时一直等待
*/
boolean blockWhenExhausted = DEFAULT_BLOCK_WHEN_EXHAUSTED;
/**
* 取对象时验证
*/
boolean testOnBorrow = true ;
/**
* 回收验证
*/
boolean testOnReturn = true;
/**
* 创建时验证
*/
boolean testOnCreate = true;
/**
* 空闲验证
*/
boolean testWhileIdle = true;
/**
* 后进先出
*/
boolean lifo = DEFAULT_LIFO;
}

View File

@@ -0,0 +1,55 @@
/*
* Copyright 2023 http://gcpaas.gccloud.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.gccloud.dataroom.core.config.bean;
import com.google.common.collect.Sets;
import lombok.Data;
import java.util.Set;
/**
* 演示环境配置
*
* @author liuchengbiao
* @date 2021/7/28 5:34 下午
*/
@Data
public class DemoEnv {
/**
* 是否是演示环境
*/
private Boolean enable = false;
/**
* 非法请求警告提示
*/
private String tip = "演示环境,不允许操作";
/**
* post请求过滤URL
*/
private Set<String> postUrlPassSet = Sets.newHashSet();
/**
* put请求过滤URL
*/
private Set<String> putUrlPassSet = Sets.newHashSet();
/**
* delete请求过滤URL
*/
private Set<String> deleteUrlPassSet = Sets.newHashSet();
/**
* 以该URL开头的都过滤掉
*/
private Set<String> startWithUrlPassSet = Sets.newHashSet();
}

View File

@@ -0,0 +1,48 @@
package com.gccloud.dataroom.core.config.bean;
import com.google.common.collect.Sets;
import lombok.Data;
import java.util.Set;
/**
* 文件存储配置
*/
@Data
public class FileConfig {
/**
* 文件存储的基础路径
*/
private String basePath;
/**
* 文件地址前缀
*/
private String urlPrefix;
/**
* 允许的上传文件后缀类型
*/
private Set<String> allowedFileExtensionName = Sets.newHashSet(
"jpg", "jpeg", "png", "gif", "bmp", "svg", "webp", "ico",
"xls", "xlsx", "csv",
"ppt", "pptx",
"doc", "docx",
"txt", "pdf",
"mp4", "mov", "mp3",
"rar", "zip"
);
/**
* ftp配置
*/
private DataRoomFtpConfig ftp;
/**
* sftp配置
*/
private DataRoomSftpConfig sftp;
/**
* minio配置
*/
private DataRoomMinioConfig minio;
}

View File

@@ -0,0 +1,66 @@
package com.gccloud.dataroom.core.constant;
/**
* @author liuchengbiao
* @date 2020-06-21 13:33
*/
public interface DataRoomConst {
/**
* 控制台
*/
interface Console {
/**
* 控制台line
*/
String LINE = "----------------------------------------";
}
/**
* 响应
*/
interface Response {
/**
* 响应码
*/
interface Code {
/**
* 未登录
*/
int NO_LOGIN = 401;
/**
* 无权限
*/
int NO_ACCESS = 403;
/**
* 资源不存在
*/
int NO_FOUNT = 404;
/**
* 服务端异常
*/
int SERVER_ERROR = 500;
/**
* 成功
*/
int SUCCESS = 200;
}
}
/**
* 扫描包路径
*/
interface ScanPackage {
/**
* 基础包路径
*/
String COMPONENT = "com.gccloud.dataroom";
/**
* dao路径
*/
String DAO = "com.gccloud.dataroom.core.**.dao";
}
}

View File

@@ -0,0 +1,209 @@
package com.gccloud.dataroom.core.constant;
/**
* @author zhang.tianming
*/
public interface PageDesignConstant {
/**
* 页面类型
*/
interface Type {
/**
* 大屏
*/
String BIG_SCREEN = "bigScreen";
/**
* 大屏组件
*/
String COMPONENT = "component";
}
interface CategoryType {
/**
* 大屏目录
*/
String BIG_SCREEN = "bigScreenCatalog";
/**
* 大屏模板目录
*/
String BIG_SCREEN_TEMPLATE = "bigScreenTemplateCatalog";
/**
* 资源库目录
*/
String RESOURCE = "resourceCatalog";
/**
* 组件库目录
*/
String COMPONENT = "componentCatalog";
}
/**
* 大屏
*/
interface BigScreen {
/**
* 组件类型
*/
interface Type {
/**
* 表格
*/
String TABLES = "tables";
/**
* 外链
*/
String IFRAME = "iframeChart";
/**
* 倒计时
*/
String TIME_COUNT_DOWN = "timeCountDown";
/**
* 当前时间
*/
String CURRENT_TIME = "currentTime";
/**
* 文本
*/
String TEXT = "texts";
/**
* 装饰边框
*/
String BORDER = "border";
/**
* 滚动面板
*/
String SCREEN_SCROLL_BOARD = "screenScrollBoard";
/**
* 滚动排行榜
*/
String SCREEN_SCROLL_RANKING = "screenScrollRanking";
/**
* 自定义组件
*/
String CUSTOM_COMPONENT = "customComponent";
/**
* 地图
*/
String MAP = "map";
/**
* 图标
*/
String SVGS = "svgs";
/**
* 数字翻牌器
*/
String DIGITAL_FLOP = "digitalFlop";
/**
* 视频
*/
String VIDEO = "video";
/**
* 输入框
*/
String INPUT = "input";
/**
* 按钮
*/
String BUTTON = "button";
/**
* 超链接
*/
String LINK = "linkChart";
/**
* 主题切换器
*/
String THEME_SWITCHER = "themeSwitcher";
/**
* 主题选择器
*/
String THEME_SELECT = "themeSelect";
/**
* 跑马灯
*/
String MARQUEE = "marquee";
/**
* 飞线地图
*/
String FLY_MAP = "flyMap";
/**
* Tab切换
*/
String TAB_CHART = "chartTab";
/**
* 选择器
*/
String SELECT = "select";
/**
* 时间选择
*/
String TIME_PICKER = "timePicker";
/**
* echarts组件
*/
String ECHARTS_COMPONENT = "echartsComponent";
/**
* 日期时间选择
*/
String DATE_TIME_PICKER = "dateTimePicker";
/**
* 指标卡1
*/
String INDEX_CARD = "indexCard";
/**
* 指标卡2
*/
String INDICATOR_CARD = "indicatorCard";
/**
* 数字
*/
String NUMBER = "number";
/**
* 自定义html
*/
String CUSTOM_HTML = "customHtml";
/**
* K线图
*/
String K_LINE = "kLine";
}
}
}

View File

@@ -0,0 +1,67 @@
package com.gccloud.dataroom.core.exception;
import com.gccloud.dataroom.core.constant.DataRoomConst;
import com.gccloud.common.exception.GlobalException;
import com.gccloud.common.vo.R;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;
/**
* 全局异常处理
*
* @Author maoshufeng
* @Date 2020-06-19
* @Version 1.0.0
*/
@RestControllerAdvice
@Slf4j
@ConditionalOnProperty(prefix = "gc.starter.dataroom.component", name = "DataRoomGlobalExceptionHandler", havingValue = "DataRoomGlobalExceptionHandler", matchIfMissing = true)
public class DataRoomGlobalExceptionHandler {
@PostConstruct
public void init() {
log.info(DataRoomConst.Console.LINE);
log.info("初始化默认全局异常处理如果和项目中的全局异常处理冲突可以在配置文件中配置gc.starter.dataroom.component.DataRoomGlobalExceptionHandler=false禁用该全局异常处理");
log.info(DataRoomConst.Console.LINE);
}
@ExceptionHandler(HttpRequestMethodNotSupportedException.class)
public R<String> httpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException e) {
log.error(ExceptionUtils.getStackTrace(e));
R<String> r = new R<String>();
r.setCode(DataRoomConst.Response.Code.SERVER_ERROR);
r.setMsg("不支持该请求方式");
return r;
}
/**
* 处理自定义异常
*/
@ExceptionHandler(GlobalException.class)
public R<String> exception(HttpServletRequest request, GlobalException e) {
log.error(ExceptionUtils.getStackTrace(e));
R<String> r = new R<>();
r.setCode(e.getCode());
r.setMsg(e.getMessage());
return r;
}
@ExceptionHandler(IllegalArgumentException.class)
public R<String> illegalArgumentException(Exception e) {
log.error(ExceptionUtils.getStackTrace(e));
return R.error("参数非法");
}
@ExceptionHandler(Exception.class)
public R<String> handleException(Exception e) {
log.error(ExceptionUtils.getStackTrace(e));
return R.error("服务器异常");
}
}

View File

@@ -0,0 +1,89 @@
package com.gccloud.dataroom.core.filter;
import com.baomidou.mybatisplus.core.config.GlobalConfig;
import com.gccloud.common.vo.R;
import com.gccloud.dataroom.core.config.DataRoomConfig;
import com.gccloud.dataroom.core.config.bean.DemoEnv;
import com.google.common.collect.Sets;
import com.google.gson.Gson;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMethod;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Set;
/**
* 演示环境
*
* @author liuchengbiao
* @date 2021年07月28日17:31:33
*/
@Order(2)
@Component
@Slf4j
@ConditionalOnProperty(prefix = "gc.starter.demoEnv", name = "enable", havingValue = "true")
public class DemoEnvFilter implements Filter {
@Resource
private DataRoomConfig dataRoomConfig;
/**
* 系统默认的post请求放行接口
*/
private static final Set<String> POST_URL_PASS_SET = Sets.newHashSet(
"/dataroom/design",
"/dataroom/file",
"/datasource/"
);
@PostConstruct
public void init() {
log.info("启动演示环境过滤器用于保证演示环境的稳定性仅允许指定的一些接口请求访问可通过gc.starter.demoEnv.enable 设置是否禁用");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
String method = request.getMethod();
if (StringUtils.equalsAnyIgnoreCase(RequestMethod.GET.toString(), method)
|| StringUtils.equalsAnyIgnoreCase(RequestMethod.OPTIONS.toString(), method)) {
filterChain.doFilter(servletRequest, servletResponse);
return;
}
String uri = request.getServletPath();
DemoEnv demoEnv = dataRoomConfig.getDemoEnv();
for (String startWithUrl : demoEnv.getStartWithUrlPassSet()) {
if (uri.startsWith(startWithUrl)) {
filterChain.doFilter(servletRequest, servletResponse);
return;
}
}
if (StringUtils.equalsAnyIgnoreCase(RequestMethod.POST.toString(), method) && (demoEnv.getPostUrlPassSet().contains(uri) || POST_URL_PASS_SET.contains(uri))) {
filterChain.doFilter(servletRequest, servletResponse);
return;
} else if (StringUtils.equalsAnyIgnoreCase(RequestMethod.PUT.toString(), method) && demoEnv.getPutUrlPassSet().contains(uri)) {
filterChain.doFilter(servletRequest, servletResponse);
return;
} else if (StringUtils.equalsAnyIgnoreCase(RequestMethod.DELETE.toString(), method) && (demoEnv.getDeleteUrlPassSet().contains(uri))) {
filterChain.doFilter(servletRequest, servletResponse);
return;
}
log.error("演示环境,不允许发送 {} 的 {} 请求", uri, request.getMethod());
HttpServletResponse response = (HttpServletResponse) servletResponse;
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setContentType("application/json;charset=UTF-8");
response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
String json = new Gson().toJson(R.error(500, demoEnv.getTip()));
response.getWriter().print(json);
}
}

View File

@@ -0,0 +1,15 @@
package com.gccloud.dataroom.core.module.basic.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.gccloud.dataroom.core.module.basic.entity.PageEntity;
import org.apache.ibatis.annotations.Mapper;
/**
* @Author qianxing
* @Date 2022/06/07
* @Version 1.0.0
*/
@Mapper
public interface DataRoomPageDao extends BaseMapper<PageEntity> {
}

View File

@@ -0,0 +1,15 @@
package com.gccloud.dataroom.core.module.basic.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.gccloud.dataroom.core.module.basic.entity.PagePreviewEntity;
import org.apache.ibatis.annotations.Mapper;
/**
* @Author gcpaas
* @Date 2022/06/07
* @Version 1.0.0
*/
@Mapper
public interface DataRoomPagePreviewDao extends BaseMapper<PagePreviewEntity> {
}

View File

@@ -0,0 +1,23 @@
package com.gccloud.dataroom.core.module.basic.dto;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
/**
* 用于反序列化和序列化的
* @author liuchengbiao
* @version 1.0
* @date 2022/8/8 15:11
*/
@Data
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "className")
public class BasePageDTO implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty(notes = "所属应用编码")
private String appCode;
}

View File

@@ -0,0 +1,63 @@
package com.gccloud.dataroom.core.module.basic.entity;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.FieldStrategy;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import com.gccloud.dataroom.core.constant.PageDesignConstant;
import com.gccloud.dataroom.core.module.basic.dto.BasePageDTO;
import com.gccloud.dataroom.core.module.basic.entity.type.BasePageDTOTypeHandler;
import com.gccloud.common.entity.SuperEntity;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;
import java.io.Serializable;
import java.util.Date;
/**
* 页面基本信息表
*
* @Author qianxing
* @Date 2022/06/07
* @Version 1.0.0
*/
@Data
@TableName(value = "big_screen_page", autoResultMap = true)
@ApiModel
public class PageEntity extends SuperEntity implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty(notes = "页面中文名称")
private String name;
@ApiModelProperty(notes = "页面编码,页面唯一标识符")
private String code;
@ApiModelProperty(notes = "父节点编码/所属分组编码")
private String parentCode;
/**
* 参考:{@link PageDesignConstant.Type}
*/
@ApiModelProperty(notes = "页面类型")
private String type;
@ApiModelProperty(notes = "大屏首页封面")
private String coverPicture;
@ApiModelProperty(notes = "具体组件配置、JSON格式")
@TableField(typeHandler = BasePageDTOTypeHandler.class)
private BasePageDTO config;
@ApiModelProperty(notes = "备注")
private String remark;
@ApiModelProperty(notes = "排序")
private Integer orderNum;
@ApiModelProperty(notes = "所属应用编码")
private String appCode;
}

View File

@@ -0,0 +1,41 @@
package com.gccloud.dataroom.core.module.basic.entity;
import com.baomidou.mybatisplus.annotation.*;
import com.gccloud.common.entity.SuperEntity;
import com.gccloud.dataroom.core.module.basic.dto.BasePageDTO;
import com.gccloud.dataroom.core.module.basic.entity.type.BasePageDTOTypeHandler;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
/**
* 预览缓存临时表
*
* @Author qianxing
* @Date 2022/06/07
* @Version 1.0.0
*/
@Data
@TableName(value = "big_screen_page_preview", autoResultMap = true)
@ApiModel
public class PagePreviewEntity implements Serializable {
@TableId
@ApiModelProperty(notes = "主键")
private String id;
@ApiModelProperty(notes = "页面编码,页面唯一标识符")
private String code;
@ApiModelProperty(notes = "具体组件配置、JSON格式")
@TableField(typeHandler = BasePageDTOTypeHandler.class)
private BasePageDTO config;
@TableField(fill = FieldFill.INSERT, updateStrategy = FieldStrategy.NEVER)
@ApiModelProperty(notes = "创建时间")
private Date createDate;
}

View File

@@ -0,0 +1,63 @@
package com.gccloud.dataroom.core.module.basic.entity.type;
import com.gccloud.dataroom.core.module.basic.dto.BasePageDTO;
import com.gccloud.common.utils.JSON;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedJdbcTypes;
import org.apache.ibatis.type.MappedTypes;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
* JSONObject 与 字符串自动转换
*
* @author liuchengbiao
* @version 1.0
* @date 2022/8/8 15:11
*/
@MappedJdbcTypes(JdbcType.VARCHAR)
@MappedTypes(BasePageDTO.class)
public class BasePageDTOTypeHandler extends BaseTypeHandler<BasePageDTO> {
@Override
public void setNonNullParameter(PreparedStatement preparedStatement, int i, BasePageDTO obj, JdbcType jdbcType) throws SQLException {
String data = JSON.toJSONString(obj);
preparedStatement.setString(i, data);
}
@Override
public BasePageDTO getNullableResult(ResultSet resultSet, String columnName) throws SQLException {
String data = resultSet.getString(columnName);
if (StringUtils.isBlank(data)) {
return null;
}
BasePageDTO basePageDTO = JSON.parseObject(data, BasePageDTO.class);
return basePageDTO;
}
@Override
public BasePageDTO getNullableResult(ResultSet resultSet, int i) throws SQLException {
String data = resultSet.getString(i);
if (StringUtils.isBlank(data)) {
return null;
}
BasePageDTO basePageDTO = JSON.parseObject(data, BasePageDTO.class);
return basePageDTO;
}
@Override
public BasePageDTO getNullableResult(CallableStatement callableStatement, int i) throws SQLException {
String data = callableStatement.getString(i);
if (StringUtils.isBlank(data)) {
return null;
}
BasePageDTO basePageDTO = JSON.parseObject(data, BasePageDTO.class);
return basePageDTO;
}
}

View File

@@ -0,0 +1,118 @@
package com.gccloud.dataroom.core.module.basic.service;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.gccloud.dataroom.core.module.basic.entity.PageEntity;
import com.gccloud.common.service.ISuperService;
import com.gccloud.common.utils.AssertUtils;
import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import org.apache.commons.lang3.StringUtils;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
/**
*
* @author liuchengbiao
* @version 1.0
* @date 2022/8/8 15:11
*/
public interface IBasePageService extends ISuperService<PageEntity> {
/**
* 页面实体缓存
*/
Cache<String, PageEntity> PAGE_ENTITY_CACHE = Caffeine.newBuilder().expireAfterWrite(1, TimeUnit.MINUTES).build();
/**
* 获取指定类型页面所有名称
*
* @param type
* @return
*/
default Set<String> getAllName(String type) {
AssertUtils.isTrue(StringUtils.isNotBlank(type), "type不能为空");
LambdaQueryWrapper<PageEntity> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(PageEntity::getType, type);
queryWrapper.select(PageEntity::getName);
List<PageEntity> list = getBaseMapper().selectList(queryWrapper);
Set<String> allName = list.stream().map(PageEntity::getName).collect(Collectors.toSet());
return allName;
}
/**
* 根据编码查询
*
* @param code
* @return
*/
default PageEntity getByCode(String code) {
AssertUtils.isTrue(StringUtils.isNotBlank(code), "页面编码不能为空");
PageEntity ifPresent = PAGE_ENTITY_CACHE.getIfPresent(code);
if (ifPresent != null) {
return ifPresent;
}
LambdaQueryWrapper<PageEntity> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(PageEntity::getCode, code);
PageEntity pageEntity = getBaseMapper().selectOne(queryWrapper);
if (pageEntity != null) {
PAGE_ENTITY_CACHE.put(code, pageEntity);
}
return pageEntity;
}
/**
* 名称查重
* @param entity
* @return
*/
default boolean checkNameRepeat(PageEntity entity) {
AssertUtils.isTrue(StringUtils.isNotBlank(entity.getName()), "名称不能为空");
LambdaQueryWrapper<PageEntity> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.select(PageEntity::getId);
queryWrapper.eq(StringUtils.isNotBlank(entity.getAppCode()), PageEntity::getAppCode, entity.getAppCode())
.eq(PageEntity::getName, entity.getName())
.eq(PageEntity::getType, entity.getType())
.ne(StringUtils.isNotBlank(entity.getId()), PageEntity::getId, entity.getId());
return getBaseMapper().selectList(queryWrapper).size() > 0;
}
/**
* 名称查重
* @param appCode
* @param name
* @param id
* @param type
* @return
*/
default boolean checkNameRepeat(String appCode, String name, String id, String type) {
AssertUtils.isTrue(StringUtils.isNotBlank(name), "名称不能为空");
LambdaQueryWrapper<PageEntity> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.select(PageEntity::getId);
queryWrapper.eq(StringUtils.isNotBlank(appCode), PageEntity::getAppCode, appCode)
.eq(PageEntity::getName, name)
.eq(PageEntity::getType, type)
.ne(StringUtils.isNotBlank(id), PageEntity::getId, id);
return getBaseMapper().selectList(queryWrapper).size() > 0;
}
/**
* 编码查重
* @param entity
* @return
*/
default boolean checkCodeRepeat(PageEntity entity) {
AssertUtils.isTrue(StringUtils.isNotBlank(entity.getCode()), "编码不能为空");
LambdaQueryWrapper<PageEntity> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.select(PageEntity::getId);
queryWrapper.eq(StringUtils.isNotBlank(entity.getAppCode()), PageEntity::getAppCode, entity.getAppCode())
.eq(PageEntity::getCode, entity.getCode())
.eq(PageEntity::getType, entity.getType())
.ne(StringUtils.isNotBlank(entity.getId()), PageEntity::getId, entity.getId());
return getBaseMapper().selectList(queryWrapper).size() > 0;
}
}

View File

@@ -0,0 +1,33 @@
package com.gccloud.dataroom.core.module.basic.task;
import com.gccloud.dataroom.core.module.manage.service.IDataRoomPagePreviewService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
/**
* 每日定时清理预览临时表数据
* @author hongyang
* @version 1.0
* @date 2023/9/13 10:37
*/
@EnableScheduling
@Component
@Slf4j
public class PreviewClearTask {
@Resource
private IDataRoomPagePreviewService previewService;
@Scheduled(cron = "0 0 1 * * ?")
public void clear() {
log.info("开始清理预览数据");
previewService.clear();
}
}

View File

@@ -0,0 +1,98 @@
package com.gccloud.dataroom.core.module.biz.component.controller;
import com.gccloud.common.permission.ApiPermission;
import com.gccloud.common.utils.BeanConvertUtils;
import com.gccloud.dataroom.core.module.biz.component.dto.BizComponentDTO;
import com.gccloud.dataroom.core.module.biz.component.dto.BizComponentSearchDTO;
import com.gccloud.dataroom.core.module.biz.component.entity.BizComponentEntity;
import com.gccloud.dataroom.core.module.biz.component.service.IBizComponentService;
import com.gccloud.common.vo.PageVO;
import com.gccloud.common.vo.R;
import com.gccloud.dataroom.core.permission.Permission;
import io.swagger.annotations.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
/**
* @author hongyang
* @version 1.0
* @date 2023/6/5 13:43
*/
@Slf4j
@RestController("dataRoomBizComponentController")
@RequestMapping("/bigScreen/bizComponent")
@Api(tags = "业务组件")
@ApiSort(value = 110)
public class BizComponentController {
@Resource
private IBizComponentService bizComponentService;
@ApiPermission(permissions = {Permission.Component.VIEW})
@GetMapping("/page")
@ApiOperation(value = "分页", position = 10, notes = "分页查询业务组件", produces = MediaType.APPLICATION_JSON_VALUE)
@ApiImplicitParams({
@ApiImplicitParam(name = "current", value = "页码", paramType = "query", required = true, dataType = "int"),
@ApiImplicitParam(name = "size", value = "每页条数", paramType = "query", required = true, dataType = "int"),
@ApiImplicitParam(name = "name", value = "名称模糊查询", paramType = "query", dataType = "string")
})
public R<PageVO<BizComponentEntity>> getPage(@ApiParam(name = "查询", value = "传入查询的业务条件", required = true) BizComponentSearchDTO searchDTO) {
PageVO<BizComponentEntity> page = bizComponentService.getPage(searchDTO);
return R.success(page);
}
@ApiPermission(permissions = {Permission.Component.ADD})
@PostMapping("/add")
@ApiOperation(value = "新增", notes = "新增", produces = MediaType.APPLICATION_JSON_VALUE)
public R<String> add(@ApiParam(name = "新增", value = "传入新增的业务条件", required = true) @RequestBody BizComponentDTO dto) {
BizComponentEntity entity = BeanConvertUtils.convert(dto, BizComponentEntity.class);
String code = bizComponentService.add(entity);
return R.success(code);
}
@ApiPermission(permissions = {Permission.Component.UPDATE})
@PostMapping("/update")
@ApiOperation(value = "修改", notes = "修改", produces = MediaType.APPLICATION_JSON_VALUE)
public R<Void> update(@ApiParam(name = "修改", value = "传入修改的业务条件", required = true) @RequestBody BizComponentDTO dto) {
BizComponentEntity entity = BeanConvertUtils.convert(dto, BizComponentEntity.class);
bizComponentService.update(entity);
return R.success();
}
@ApiPermission(permissions = {Permission.Component.ADD})
@PostMapping("/copy/{code}")
@ApiOperation(value = "复制", notes = "复制", produces = MediaType.APPLICATION_JSON_VALUE)
public R<String> copy( @PathVariable String code) {
String newCode = bizComponentService.copy(code);
return R.success(newCode);
}
@ApiPermission(permissions = {Permission.Component.DELETE})
@PostMapping("/delete/{id}")
@ApiOperation(value = "删除", notes = "删除", produces = MediaType.APPLICATION_JSON_VALUE)
public R<Void> delete(@ApiParam(name = "删除", value = "传入删除的业务条件", required = true) @PathVariable String id) {
bizComponentService.delete(id);
return R.success();
}
@ApiPermission(permissions = {Permission.Component.VIEW})
@GetMapping("/info/{code}")
@ApiOperation(value = "根据编码获取组件", notes = "根据编码获取组件", produces = MediaType.APPLICATION_JSON_VALUE)
public R<BizComponentEntity> getInfoByCode(@ApiParam(name = "根据编码获取组件", value = "传入根据编码获取组件的业务条件", required = true) @PathVariable String code) {
BizComponentEntity entity = bizComponentService.getInfoByCode(code);
return R.success(entity);
}
@ApiPermission(permissions = {Permission.Component.VIEW})
@PostMapping("/name/repeat")
@ApiOperation(value = "名称查重", notes = "名称查重", produces = MediaType.APPLICATION_JSON_VALUE)
public R<Boolean> nameRepeat(@RequestBody BizComponentDTO dto) {
return R.success(bizComponentService.checkName(dto.getId(), dto.getName()));
}
}

View File

@@ -0,0 +1,14 @@
package com.gccloud.dataroom.core.module.biz.component.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.gccloud.dataroom.core.module.biz.component.entity.BizComponentEntity;
import org.apache.ibatis.annotations.Mapper;
/**
* @author hongyang
* @version 1.0
* @date 2023/6/5 11:39
*/
@Mapper
public interface DataRoomBizComponentDao extends BaseMapper<BizComponentEntity> {
}

View File

@@ -0,0 +1,49 @@
package com.gccloud.dataroom.core.module.biz.component.dto;
import com.baomidou.mybatisplus.annotation.FieldStrategy;
import com.baomidou.mybatisplus.annotation.TableField;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.gccloud.common.utils.EmptyAsNullDeserializer;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* @author hongyang
* @version 1.0
* @date 2023/6/5 11:41
*/
@Data
public class BizComponentDTO {
@JsonDeserialize(using = EmptyAsNullDeserializer.class)
@ApiModelProperty(notes = "主键")
private String id;
@ApiModelProperty(notes = "业务组件中文名称")
private String name;
@ApiModelProperty(notes = "业务组件编码,页面唯一标识符")
@TableField(updateStrategy = FieldStrategy.NEVER)
private String code;
@ApiModelProperty(notes = "业务组件所属分组")
private String type;
@ApiModelProperty(notes = "组件封面")
private String coverPicture;
@ApiModelProperty(notes = "vue组件内容")
private String vueContent;
@ApiModelProperty(notes = "组件配置内容")
private String settingContent;
@ApiModelProperty(notes = "备注")
private String remark;
@ApiModelProperty(notes = "排序")
private Integer orderNum;
@ApiModelProperty(notes = "模块编码")
private String moduleCode;
}

View File

@@ -0,0 +1,20 @@
package com.gccloud.dataroom.core.module.biz.component.dto;
import com.gccloud.common.dto.SearchDTO;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* @author hongyang
* @version 1.0
* @date 2023/6/5 11:41
*/
@Data
public class BizComponentSearchDTO extends SearchDTO {
@ApiModelProperty(value = "所属分组")
private String type;
@ApiModelProperty(value = "名称")
private String name;
}

View File

@@ -0,0 +1,55 @@
package com.gccloud.dataroom.core.module.biz.component.entity;
import com.baomidou.mybatisplus.annotation.FieldStrategy;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import com.gccloud.common.entity.SuperEntity;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
/**
* 页面基本信息表
*
* @Author qianxing
* @Date 2022/06/07
* @Version 1.0.0
*/
@Data
@TableName(value = "big_screen_biz_component")
@ApiModel
public class BizComponentEntity extends SuperEntity implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty(notes = "业务组件中文名称")
private String name;
@ApiModelProperty(notes = "业务组件编码,页面唯一标识符")
@TableField(updateStrategy = FieldStrategy.NEVER)
private String code;
@ApiModelProperty(notes = "业务组件所属分组")
private String type;
@ApiModelProperty(notes = "组件封面")
private String coverPicture;
@ApiModelProperty(notes = "vue组件内容")
private String vueContent;
@ApiModelProperty(notes = "组件配置内容")
private String settingContent;
@ApiModelProperty(notes = "备注")
private String remark;
@ApiModelProperty(notes = "排序")
private Integer orderNum;
@ApiModelProperty(notes = "模块编码")
private String moduleCode;
}

View File

@@ -0,0 +1,72 @@
package com.gccloud.dataroom.core.module.biz.component.service;
import com.gccloud.dataroom.core.module.biz.component.dto.BizComponentSearchDTO;
import com.gccloud.dataroom.core.module.biz.component.entity.BizComponentEntity;
import com.gccloud.common.service.ISuperService;
import com.gccloud.common.vo.PageVO;
import java.util.List;
/**
* @author hongyang
* @version 1.0
* @date 2023/6/5 11:39
*/
public interface IBizComponentService extends ISuperService<BizComponentEntity> {
/**
* 获取组件列表分页
* @param searchDTO
* @return
*/
PageVO<BizComponentEntity> getPage(BizComponentSearchDTO searchDTO);
/**
* 获取组件列表
* @param searchDTO
* @return
*/
List<BizComponentEntity> getList(BizComponentSearchDTO searchDTO);
/**
* 根据编码获取组件
* @param code
* @return
*/
BizComponentEntity getInfoByCode(String code);
/**
* 新增组件
* @param entity
* @return
*/
String add(BizComponentEntity entity);
/**
* 更新组件
* @param entity
*/
void update(BizComponentEntity entity);
/**
* 复制
* @param code
* @return
*/
String copy(String code);
/**
* 删除组件
* @param id
*/
void delete(String id);
/**
* 名称查重
* @param id
* @param name
* @return
*/
boolean checkName(String id, String name);
}

View File

@@ -0,0 +1,240 @@
package com.gccloud.dataroom.core.module.biz.component.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gccloud.dataroom.core.config.DataRoomConfig;
import com.gccloud.dataroom.core.module.biz.component.dao.DataRoomBizComponentDao;
import com.gccloud.dataroom.core.module.biz.component.dto.BizComponentSearchDTO;
import com.gccloud.dataroom.core.module.biz.component.entity.BizComponentEntity;
import com.gccloud.dataroom.core.module.biz.component.service.IBizComponentService;
import com.gccloud.dataroom.core.module.file.entity.DataRoomFileEntity;
import com.gccloud.dataroom.core.module.file.service.IDataRoomOssService;
import com.gccloud.dataroom.core.utils.CodeGenerateUtils;
import com.gccloud.common.exception.GlobalException;
import com.gccloud.common.vo.PageVO;
import com.gccloud.dataroom.core.utils.PathUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.io.*;
import java.util.Base64;
import java.util.List;
/**
* @author hongyang
* @version 1.0
* @date 2023/6/5 13:35
*/
@Slf4j
@Service("dataRoomBizComponentService")
public class BizComponentServiceImpl extends ServiceImpl<DataRoomBizComponentDao, BizComponentEntity> implements IBizComponentService {
@Resource
private DataRoomConfig bigScreenConfig;
@Resource
private IDataRoomOssService ossService;
@Override
public PageVO<BizComponentEntity> getPage(BizComponentSearchDTO searchDTO) {
LambdaQueryWrapper<BizComponentEntity> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.like(StringUtils.isNotBlank(searchDTO.getName()), BizComponentEntity::getName, searchDTO.getName());
queryWrapper.eq(StringUtils.isNotBlank(searchDTO.getType()), BizComponentEntity::getType, searchDTO.getType());
queryWrapper.orderByAsc(BizComponentEntity::getOrderNum);
queryWrapper.orderByDesc(BizComponentEntity::getCreateDate);
PageVO<BizComponentEntity> page = this.page(searchDTO, queryWrapper);
List<BizComponentEntity> list = page.getList();
String urlPrefix = bigScreenConfig.getFile().getUrlPrefix();
if (!urlPrefix.endsWith("/")) {
urlPrefix += "/";
}
for (BizComponentEntity entity : list) {
if (StringUtils.isBlank(entity.getCoverPicture())) {
continue;
}
// entity.setCoverPicture(urlPrefix + entity.getCoverPicture().replace("\\", "/"));
entity.setCoverPicture(PathUtils.normalizePath(entity.getCoverPicture()));
}
return page;
}
@Override
public List<BizComponentEntity> getList(BizComponentSearchDTO searchDTO) {
LambdaQueryWrapper<BizComponentEntity> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.like(StringUtils.isNotBlank(searchDTO.getName()), BizComponentEntity::getName, searchDTO.getName());
queryWrapper.eq(StringUtils.isNotBlank(searchDTO.getType()), BizComponentEntity::getType, searchDTO.getType());
List<BizComponentEntity> list = this.list(queryWrapper);
String urlPrefix = bigScreenConfig.getFile().getUrlPrefix();
if (!urlPrefix.endsWith("/")) {
urlPrefix += "/";
}
for (BizComponentEntity entity : list) {
if (StringUtils.isBlank(entity.getCoverPicture())) {
continue;
}
entity.setCoverPicture(urlPrefix + entity.getCoverPicture().replace("\\", "/"));
}
return list;
}
@Override
public BizComponentEntity getInfoByCode(String code) {
if (StringUtils.isBlank(code)) {
throw new GlobalException("组件编码不能为空");
}
LambdaQueryWrapper<BizComponentEntity> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(BizComponentEntity::getCode, code);
List<BizComponentEntity> list = list(queryWrapper);
if (list.size() == 0) {
throw new GlobalException("组件不存在");
}
BizComponentEntity bizComponentEntity = list.get(0);
String urlPrefix = bigScreenConfig.getFile().getUrlPrefix();
if (!urlPrefix.endsWith("/")) {
urlPrefix += "/";
}
for (BizComponentEntity entity : list) {
String coverPicture = entity.getCoverPicture();
if (StringUtils.isBlank(coverPicture)) {
continue;
}
if (coverPicture.startsWith("/")) {
coverPicture = coverPicture.substring(1);
}
entity.setCoverPicture(urlPrefix + PathUtils.normalizePath(coverPicture));
}
return bizComponentEntity;
}
@Override
public String add(BizComponentEntity entity) {
boolean repeat = this.checkName(null, entity.getName());
if (repeat) {
throw new GlobalException("组件名称重复");
}
String code = CodeGenerateUtils.generate("bizComponent");
entity.setCode(code);
if (StringUtils.isNotBlank(entity.getCoverPicture())) {
String base64Str = entity.getCoverPicture();
String fileUrl = this.saveCoverPicture(base64Str, entity.getCode());
entity.setCoverPicture(fileUrl);
}
this.save(entity);
return code;
}
@Override
public void update(BizComponentEntity entity) {
boolean repeat = this.checkName(entity.getId(), entity.getName());
if (repeat) {
throw new GlobalException("组件名称重复");
}
if (StringUtils.isNotBlank(entity.getCoverPicture())) {
String base64Str = entity.getCoverPicture();
String fileUrl = this.saveCoverPicture(base64Str, entity.getCode());
entity.setCoverPicture(fileUrl);
}
this.updateById(entity);
}
private String saveCoverPicture(String base64String, String fileName) {
String fileUrl = "";
if (StringUtils.isBlank(base64String)) {
return fileUrl;
}
try {
// 去除base64字符串前缀从初始位置到逗号位置
base64String = base64String.substring(base64String.indexOf(",") + 1);
// 解码base64字符串
byte[] imageBytes = Base64.getDecoder().decode(base64String);
InputStream inputStream = new ByteArrayInputStream(imageBytes);
DataRoomFileEntity fileEntity = new DataRoomFileEntity();
String filePath = "cover" + File.separator + fileName + ".png";
ossService.upload(inputStream, filePath, 0, fileEntity);
// 封面先不保存到资源库
// fileService.save(fileEntity);
log.info("组业务件封面保存至:{}", filePath);
fileUrl = fileEntity.getUrl();
} catch (Exception e) {
log.error(ExceptionUtils.getStackTrace(e));
}
return fileUrl;
}
public static final String COPY_SUFFIX = "-副本";
@Override
public String copy(String code) {
BizComponentEntity copyFrom = this.getInfoByCode(code);
if (copyFrom == null) {
throw new GlobalException("源业务组件不存在");
}
String oldCode = copyFrom.getCode();
copyFrom.setId(null);
String oldName = copyFrom.getName();
// 检查是否有 -副本,有的话从-副本开始,后面全部去掉
if (oldName.contains(COPY_SUFFIX)) {
oldName = oldName.substring(0, oldName.indexOf(COPY_SUFFIX));
if (StringUtils.isBlank(oldName)) {
oldName = "组件";
}
}
copyFrom.setName(oldName + COPY_SUFFIX);
int i = 1;
while(this.checkName(null, copyFrom.getName())) {
copyFrom.setName(oldName + COPY_SUFFIX + i);
i++;
}
copyFrom.setCode(CodeGenerateUtils.generate("bizComponent"));
String copyUrl = this.copyCoverPicture(oldCode, copyFrom.getCode());
if (StringUtils.isBlank(copyUrl)) {
copyFrom.setCoverPicture(null);
} else {
copyFrom.setCoverPicture(copyUrl);
}
this.save(copyFrom);
return copyFrom.getCode();
}
/**
* 复制封面文件
* @param oldFileName
* @param newFileName
* @return
*/
private String copyCoverPicture(String oldFileName, String newFileName) {
if (StringUtils.isBlank(oldFileName)) {
return "";
}
String oldFile = "cover" + File.separator + oldFileName + ".png";
String newFilePath = "cover" + File.separator + newFileName + ".png";
return ossService.copy(oldFile, newFilePath);
}
@Override
public void delete(String id) {
if (StringUtils.isBlank(id)) {
throw new GlobalException("组件id不能为空");
}
this.removeById(id);
}
@Override
public boolean checkName(String id, String name) {
LambdaQueryWrapper<BizComponentEntity> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.select(BizComponentEntity::getId);
queryWrapper.eq(BizComponentEntity::getName, name);
if (StringUtils.isNotBlank(id)) {
queryWrapper.ne(BizComponentEntity::getId, id);
}
return this.list(queryWrapper).size() > 0;
}
}

View File

@@ -0,0 +1,78 @@
package com.gccloud.dataroom.core.module.chart.bean;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.HashMap;
/**
* @author hongyang
* @version 1.0
* @date 2023/1/11 15:20
*/
@Data
public class Btn {
@ApiModelProperty(notes = "按钮名称")
private String name;
@ApiModelProperty(notes = "按钮标签")
private String remark;
@ApiModelProperty(notes = "按钮类型")
private String type;
@ApiModelProperty(notes = "折叠到更多")
private boolean isPackUp = false;
@ApiModelProperty(notes = "按钮动作")
private Action action;
@ApiModelProperty(notes = "按钮是否可用")
private boolean enable;
@ApiModelProperty(notes = "按钮自定义属性")
private Attribute customize;
@ApiModelProperty(notes = "列点击绑定列")
private String columnCode;
@Data
public static class Action {
@ApiModelProperty(notes = "动作类型")
private String type;
@ApiModelProperty(notes = "动作脚本")
private String script;
@ApiModelProperty(notes = "打开页面类型的配置")
private HashMap<String, Object> page;
@ApiModelProperty(notes = "打开表单类型的配置")
private HashMap<String, Object> form;
@ApiModelProperty(notes = "组件能力类型的配置")
private HashMap<String, Object> component;
@ApiModelProperty(notes = "javascript类型的配置")
private HashMap<String, Object> js;
}
@Data
private static class Attribute {
@ApiModelProperty(notes = "按钮图标")
private String icon;
@ApiModelProperty(notes = "按钮颜色")
private String style;
@ApiModelProperty(notes = "按钮大小")
private String size;
}
}

View File

@@ -0,0 +1,119 @@
package com.gccloud.dataroom.core.module.chart.bean;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.gccloud.dataroom.core.module.chart.components.datasource.BaseChartDataSource;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.List;
import java.util.Map;
/**
* Charts图表
* @author liuchengbiao
* @version 1.0
* @date 2022/8/8 15:11
*/
@Data
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "className")
public class Chart {
@ApiModelProperty(notes = "版本")
private String version;
@ApiModelProperty(notes = "key")
private String key;
@ApiModelProperty(notes = "图表唯一标识")
private String code;
@ApiModelProperty(notes = "数据源")
private BaseChartDataSource dataSource;
@ApiModelProperty(notes = "显示图表标题")
private Boolean showTitle = true;
@ApiModelProperty(notes = "图表标题")
private String title;
@ApiModelProperty(notes = "名称")
private String name;
@ApiModelProperty(notes = "组件类型")
private String type;
@ApiModelProperty(notes = "宽度")
private Integer w = 1;
@ApiModelProperty(notes = "高度")
private Integer h = 1;
@ApiModelProperty(notes = "X坐标点")
private Integer x = 0;
@ApiModelProperty(notes = "Y坐标点")
private Integer y = 1;
@ApiModelProperty(notes = "Z图层")
private Integer z;
@ApiModelProperty(notes = "分组标识")
private String group;
@ApiModelProperty(notes = "锁定")
private Boolean locked = false;
@ApiModelProperty(notes = "联动")
private Linkage linkage = new Linkage();
@ApiModelProperty(notes = "联动入参配置")
private List<InParam> inParams;
/**
* 主题配置,格式如下
* {
* dark: {},
* light: {}
* }
*/
@ApiModelProperty(notes = "主题配置")
private Map<String, Object> theme;
/**
* 边框配置,格式如下
* {
* type: '',
* titleHeight: 60,
* fontSize: 30,
* color: ['#5B8FF9', '#61DDAA', '#5D7092', '#F6BD16', '#6F5EF9']
*/
@ApiModelProperty(notes = "边框配置")
private Map<String, Object> border;
@ApiModelProperty(notes = "计算表达式")
private String expression;
@ApiModelProperty(notes = "表达式关联的组件的code集合")
private List<String> expressionCodes;
@ApiModelProperty(notes = "旋转x")
private Integer rotateX;
@ApiModelProperty(notes = "旋转y")
private Integer rotateY;
@ApiModelProperty(notes = "旋转z")
private Integer rotateZ;
@ApiModelProperty(notes = "透视")
private Integer perspective;
@ApiModelProperty(notes = "倾斜x")
private Integer skewX;
@ApiModelProperty(notes = "倾斜y")
private Integer skewY;
}

View File

@@ -0,0 +1,55 @@
package com.gccloud.dataroom.core.module.chart.bean;
import com.gccloud.dataset.dto.DatasetParamDTO;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.List;
/**
* @author hongyang
* @version 1.0
* @date 2023/1/11 15:22
*/
@Data
public class Field {
@ApiModelProperty(notes = "参数名称")
private String name;
@ApiModelProperty(notes = "参数标签")
private String label;
@ApiModelProperty(notes = "组件类型")
private String component;
@ApiModelProperty(notes = "查询规则")
private String queryRule;
@ApiModelProperty(notes = "是否显示")
private boolean display;
@ApiModelProperty(notes = "枚举值配置")
private Enumeration enumeration;
@Data
public static class Enumeration {
@ApiModelProperty(notes = "数据集")
private String dataSetKey;
@ApiModelProperty(notes = "数据集类型,前端使用")
private String dataSetType;
@ApiModelProperty(notes = "显示字段")
private String itemKeyName;
@ApiModelProperty(notes = "值字段")
private String itemValueName;
@ApiModelProperty(value = "参数")
private List<DatasetParamDTO> params;
}
}

View File

@@ -0,0 +1,22 @@
package com.gccloud.dataroom.core.module.chart.bean;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.List;
/**
* 过滤条件
* @author liuchengbiao
* @version 1.0
* @date 2022/8/8 15:11
*/
@Data
public class Filter {
@ApiModelProperty(notes = "表格列")
private String column;
@ApiModelProperty(notes = "条件")
private String operator;
@ApiModelProperty(notes = "")
private List<String> value;
}

View File

@@ -0,0 +1,17 @@
package com.gccloud.dataroom.core.module.chart.bean;
import lombok.Data;
/**
* @author hongyang
* @version 1.0
* @date 2023/1/4 16:48
*/
@Data
public class InParam {
private String name;
private String code;
}

View File

@@ -0,0 +1,59 @@
package com.gccloud.dataroom.core.module.chart.bean;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.List;
/**
* @author hongyang
* @version 1.0
* @date 2023/1/4 16:39
*/
@Data
public class Linkage {
@ApiModelProperty(notes = "联动执行的逻辑")
private Action action;
@ApiModelProperty(notes = "组件的唯一标识,用于知道和谁做联动")
private List<Component> components;
@Data
public static class Action {
@ApiModelProperty("联动类型")
private String type;
@ApiModelProperty("联动执行的逻辑")
private String script;
}
@Data
public static class Component {
@ApiModelProperty("组件的唯一标识,用于知道和谁做联动")
private String componentKey;
@ApiModelProperty("使用数据模型已有的关联关系进行联动查询")
private boolean linkByRelation;
@ApiModelProperty("映射关系")
private List<Mapping> maps;
}
@Data
public static class Mapping {
@ApiModelProperty("源字段")
private String sourceField;
@ApiModelProperty("目标字段")
private String targetField;
@ApiModelProperty("查询规则")
private String queryRule;
}
}

View File

@@ -0,0 +1,82 @@
package com.gccloud.dataroom.core.module.chart.components;
import com.gccloud.dataroom.core.constant.PageDesignConstant;
import com.gccloud.dataroom.core.module.chart.bean.Chart;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.List;
/**
* tab切换
* @author hongyang
* @version 1.0
* @date 2023/8/24 17:03
*/
@Data
public class ChartTabChart extends Chart{
@ApiModelProperty(notes = "类型")
private String type = PageDesignConstant.BigScreen.Type.TAB_CHART;
@ApiModelProperty(notes = "个性化")
private Customize customize = new Customize();
@Data
public static class Customize {
@ApiModelProperty(notes = "组件tab列表")
private List<Tab> tabList;
@ApiModelProperty(notes = "字体大小")
private Integer fontSize;
@ApiModelProperty(notes = "字体粗细")
private Integer fontWeight;
@ApiModelProperty(notes = "字体颜色")
private String color;
@ApiModelProperty(notes = "线条颜色")
private String lineColor;
@ApiModelProperty(notes = "线条位置")
private String position;
}
@Data
public static class Tab {
@ApiModelProperty(notes = "组件编码")
private String chartCode;
@ApiModelProperty(notes = "组件名称")
private String name;
@ApiModelProperty(notes = "tab图表")
private Chart chart;
}
/**
* 获取内部图表
* @param chartCode
* @return
*/
public Chart getInnerChart(String chartCode) {
if (customize == null) {
return null;
}
if (customize.tabList == null || customize.tabList.isEmpty()) {
return null;
}
for (Tab tab : customize.tabList) {
if (tab.getChartCode().equals(chartCode)) {
return tab.getChart();
}
}
return null;
}
}

View File

@@ -0,0 +1,57 @@
package com.gccloud.dataroom.core.module.chart.components;
import com.gccloud.dataroom.core.constant.PageDesignConstant;
import com.gccloud.dataroom.core.module.chart.bean.Chart;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.List;
import java.util.Map;
/**
* 自定义组件
* @author hongyang
* @version 1.0
* @date 2023/3/28 14:25
*/
@Data
public class CustomComponentChart extends Chart {
@ApiModelProperty(notes = "父编码")
private String parentCode;
@ApiModelProperty(notes = "版本")
private String version;
@ApiModelProperty(notes = "类型")
private String type = PageDesignConstant.BigScreen.Type.CUSTOM_COMPONENT;
@ApiModelProperty(notes = "自定义处理配置脚本")
private String optionHandler;
@ApiModelProperty(notes = "自定义处理数据源脚本")
private String dataHandler;
@ApiModelProperty(notes = "组件的构造函数分类")
private String chartType;
@ApiModelProperty(notes = "组件的配置直接从g2官网复制")
private Object option;
@ApiModelProperty(notes = "右侧面板自定义配置")
private List<Map<String, Object>> setting;
@ApiModelProperty(notes = "组件类别")
private String category;
@Data
public static class Setting {
@ApiModelProperty(notes = "配置项字段")
private String field;
@ApiModelProperty(notes = "")
private Object value;
}
}

View File

@@ -0,0 +1,84 @@
package com.gccloud.dataroom.core.module.chart.components;
import com.gccloud.dataroom.core.constant.PageDesignConstant;
import com.gccloud.dataroom.core.module.chart.bean.Chart;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.List;
/**
* 自定义Echarts组件
* @author hongyang
* @version 1.0
* @date 2023/3/28 14:25
*/
@Data
public class EchartsComponentChart extends Chart {
@ApiModelProperty(notes = "父编码")
private String parentCode;
@ApiModelProperty(notes = "版本")
private String version;
@ApiModelProperty(notes = "类型")
private String type = PageDesignConstant.BigScreen.Type.ECHARTS_COMPONENT;
@ApiModelProperty(notes = "自定义处理配置脚本")
private String optionHandler;
@ApiModelProperty(notes = "自定义处理数据源脚本")
private String dataHandler;
@ApiModelProperty(notes = "组件的构造函数分类")
private String chartType;
@ApiModelProperty(notes = "组件的配置直接从g2官网复制")
private Object option;
@ApiModelProperty(notes = "右侧面板自定义配置")
private List<Setting> setting;
@ApiModelProperty(notes = "组件的唯一名称")
private String name;
@Data
public static class Setting {
@ApiModelProperty(notes = "配置项名称")
private String label;
@ApiModelProperty(notes = "配置项组件类型")
private String type;
@ApiModelProperty(notes = "配置项字段")
private String field;
@ApiModelProperty(notes = "配置项对应options中的字段")
private String optionField;
@ApiModelProperty(notes = "是否多选")
private Boolean multiple;
@ApiModelProperty(notes = "")
private Object value;
@ApiModelProperty(notes = "所属tab页")
private String tabName;
@ApiModelProperty(notes = "多选时选项")
private Object options;
@ApiModelProperty(notes = "步长")
private Integer step;
@ApiModelProperty(notes = "所属样式分组")
private String groupName;
}
}

View File

@@ -0,0 +1,91 @@
package com.gccloud.dataroom.core.module.chart.components;
import com.gccloud.dataroom.core.constant.PageDesignConstant;
import com.gccloud.dataroom.core.module.chart.bean.Chart;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.List;
/**
* 自定义组件
* @author hongyang
* @version 1.0
* @date 2023/3/28 14:25
*/
@Data
public class RemoteComponentChart extends Chart {
@ApiModelProperty(notes = "类型")
private String type = PageDesignConstant.BigScreen.Type.CUSTOM_COMPONENT;
@ApiModelProperty(notes = "自定义处理配置脚本")
private String optionHandler;
@ApiModelProperty(notes = "自定义处理数据源脚本")
private String dataHandler;
@ApiModelProperty(notes = "组件的构造函数分类")
private String chartType;
@ApiModelProperty(notes = "组件的配置直接从g2官网复制")
private Object option;
@ApiModelProperty(notes = "右侧面板自定义配置")
private List<Setting> setting;
@ApiModelProperty(notes = "组件的唯一名称")
private String name;
@ApiModelProperty(notes = "自定义")
private Customize customize = new Customize();
@Data
public static class Setting {
@ApiModelProperty(notes = "配置项名称")
private String label;
@ApiModelProperty(notes = "配置项组件类型")
private String type;
@ApiModelProperty(notes = "配置项字段")
private String field;
@ApiModelProperty(notes = "配置项对应options中的字段")
private String optionField;
@ApiModelProperty(notes = "是否多选")
private Boolean multiple;
@ApiModelProperty(notes = "")
private Object value;
@ApiModelProperty(notes = "所属tab页")
private String tabName;
@ApiModelProperty(notes = "多选时选项")
private Object options;
@ApiModelProperty(notes = "步长")
private Integer step;
@ApiModelProperty(notes = "所属样式分组")
private String groupName;
}
@Data
public static class Customize {
@ApiModelProperty(notes = "用户从外部传入的自定义的vue文件所在目录名称")
private String vueSysComponentDirName;
@ApiModelProperty(notes = "业务组件表唯一标识")
private String vueBizComponentCode;
}
}

View File

@@ -0,0 +1,23 @@
package com.gccloud.dataroom.core.module.chart.components;
import com.gccloud.dataroom.core.module.chart.bean.Chart;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.HashMap;
import java.util.Map;
/**
* 边框图表
* @author hongyang
* @version 1.0
* @date 2023/3/16 10:29
*/
@Data
public class ScreenBorderChart extends Chart {
@ApiModelProperty(notes = "个性化配置")
private Map<String, Object> customize = new HashMap<>();
}

View File

@@ -0,0 +1,80 @@
package com.gccloud.dataroom.core.module.chart.components;
import com.gccloud.dataroom.core.constant.PageDesignConstant;
import com.gccloud.dataroom.core.module.chart.bean.Chart;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.List;
/**
* 按钮组件
* @author hongyang
* @version 1.0
* @date 2023/3/13 16:44
*/
@Data
public class ScreenButtonChart extends Chart {
@ApiModelProperty(notes = "组件类型")
private String type = PageDesignConstant.BigScreen.Type.BUTTON;
@ApiModelProperty(notes = "个性化")
private Customize customize = new Customize();
@ApiModelProperty(notes = "名称")
private String name;
@Data
public static class Customize {
@ApiModelProperty(notes = "类型")
private String type;
@ApiModelProperty(notes = "背景颜色")
private String backgroundColor;
@ApiModelProperty(notes = "字体颜色")
private String fontColor;
@ApiModelProperty(notes = "字体大小")
private Integer fontSize;
@ApiModelProperty(notes = "边框样式")
private BorderStyle borderStyle;
@ApiModelProperty(notes = "")
private List<Object> bindComponents;
@ApiModelProperty(notes = "图标")
private Icon icon;
}
@Data
public static class Icon {
@ApiModelProperty(notes = "图标名称")
private String name;
@ApiModelProperty(notes = "位置")
private String position;
}
@Data
public static class BorderStyle {
@ApiModelProperty(notes = "边框颜色")
private String borderColor;
@ApiModelProperty(notes = "边框宽度")
private Integer borderWidth;
@ApiModelProperty(notes = "边框样式")
private String borderStyle;
@ApiModelProperty(notes = "边框圆角")
private Integer borderRadius;
}
}

View File

@@ -0,0 +1,26 @@
package com.gccloud.dataroom.core.module.chart.components;
import com.gccloud.dataroom.core.constant.PageDesignConstant;
import com.gccloud.dataroom.core.module.chart.bean.Chart;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.Map;
/**
* 文本
* @author hongyang
* @version 1.0
* @date 2023/3/13 16:44
*/
@Data
public class ScreenCandlestickChart extends Chart {
@ApiModelProperty(notes = "组件类型")
private String type = PageDesignConstant.BigScreen.Type.K_LINE;
@ApiModelProperty(notes = "个性化")
private Map<String, Object> customize;
}

View File

@@ -0,0 +1,78 @@
package com.gccloud.dataroom.core.module.chart.components;
import com.gccloud.dataroom.core.module.chart.bean.Chart;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* 装饰
* @author hongyang
* @version 1.0
* @date 2023/3/16 9:53
*/
@Data
public class ScreenConfigurationChart extends Chart {
@ApiModelProperty(notes = "个性化配置")
private Customize customize = new Customize();
@Data
public static class Customize {
@ApiModelProperty(notes = "装饰颜色1")
private String decorationColor1;
@ApiModelProperty(notes = "装饰颜色2")
private String decorationColor2;
@ApiModelProperty(notes = "状态颜色")
private String statusColor;
@ApiModelProperty(notes = "线条宽度")
private Integer lineWidth;
@ApiModelProperty(notes = "是否反转")
private Boolean reverse;
@ApiModelProperty(notes = "线条类型")
private String lineType;
@ApiModelProperty(notes = "流向")
private String flowDirection;
@ApiModelProperty(notes = "线条动画")
private String animation;
@ApiModelProperty(notes = "透明度")
private String opacity;
@ApiModelProperty(notes = "动画时长")
private Integer dur;
@ApiModelProperty(notes = "扫描动画时长")
private Integer scanDur;
@ApiModelProperty(notes = "光晕动画时长")
private Integer haloDur;
@ApiModelProperty(notes = "标题")
private String title;
@ApiModelProperty(notes = "字体大小")
private Integer fontSize;
@ApiModelProperty(notes = "字体粗细")
private Integer fontWeight;
@ApiModelProperty(notes = "字体颜色")
private String color;
@ApiModelProperty(notes = "边框颜色")
private String borderColor;
@ApiModelProperty(notes = "边框宽度")
private Integer borderWidth;
}
}

View File

@@ -0,0 +1,40 @@
package com.gccloud.dataroom.core.module.chart.components;
import com.gccloud.dataroom.core.constant.PageDesignConstant;
import com.gccloud.dataroom.core.module.chart.bean.Chart;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* @author hongyang
* @version 1.0
* @date 2023/3/16 16:44
*/
@Data
public class ScreenCurrentTimeChart extends Chart {
@ApiModelProperty(notes = "时间格式")
private String dateFormat;
@ApiModelProperty(notes = "个性化")
private Customize customize = new Customize();
@ApiModelProperty(notes = "类型")
private String type = PageDesignConstant.BigScreen.Type.CURRENT_TIME;
@Data
public static class Customize {
@ApiModelProperty(notes = "字体大小")
private Integer fontSize = 14;
@ApiModelProperty(notes = "字体权重")
private Integer fontWeight = 700;
@ApiModelProperty(notes = "字体颜色")
private String color;
@ApiModelProperty(notes = "字体")
private String fontFamily;
}
}

View File

@@ -0,0 +1,30 @@
package com.gccloud.dataroom.core.module.chart.components;
import com.gccloud.dataroom.core.constant.PageDesignConstant;
import com.gccloud.dataroom.core.module.chart.bean.Chart;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* 自定义html
* @author hongyang
* @version 1.0
* @date 2023/3/16 16:44
*/
@Data
public class ScreenCustomHtmlChart extends Chart {
@ApiModelProperty(notes = "类型")
private String type = PageDesignConstant.BigScreen.Type.CUSTOM_HTML;
@ApiModelProperty(notes = "个性化")
private Customize customize = new Customize();
@Data
public static class Customize {
@ApiModelProperty(notes = "自定义html")
private String htmlStr;
}
}

View File

@@ -0,0 +1,55 @@
package com.gccloud.dataroom.core.module.chart.components;
import com.gccloud.dataroom.core.constant.PageDesignConstant;
import com.gccloud.dataroom.core.module.chart.bean.Chart;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.Map;
/**
* 日期时间选择
* @author hongyang
* @version 1.0
* @date 2023/09/14 16:44
*/
@Data
public class ScreenDateTimePickerChart extends Chart {
@ApiModelProperty(notes = "组件类型")
private String type = PageDesignConstant.BigScreen.Type.DATE_TIME_PICKER;
@ApiModelProperty(notes = "个性化")
private Customize customize = new Customize();
@Data
public static class Customize {
@ApiModelProperty(notes = "选择框背景颜色")
private String bgColor;
@ApiModelProperty(notes = "选择框文字颜色")
private String fontColor;
@ApiModelProperty(notes = "选择框文字大小")
private Integer fontSize;
@ApiModelProperty(notes = "显示类型 year/month/date/week/ datetime/datetimerange/daterange")
private String type;
@ApiModelProperty(notes = "时间格式化类型:Date 对象default时间戳timestamp自定义custom")
private String formatType;
@ApiModelProperty(notes = "绑定值的格式")
private String valueFormat;
@ApiModelProperty(notes = "显示的格式")
private String format;
@ApiModelProperty(notes = "下拉框")
private Map<String, Object> dropDownBox;
}
}

View File

@@ -0,0 +1,59 @@
package com.gccloud.dataroom.core.module.chart.components;
import com.gccloud.dataroom.core.module.chart.bean.Chart;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* 装饰
* @author hongyang
* @version 1.0
* @date 2023/3/16 9:53
*/
@Data
public class ScreenDecorationChart extends Chart {
@ApiModelProperty(notes = "个性化配置")
private Customize customize = new Customize();
@Data
public static class Customize {
@ApiModelProperty(notes = "装饰颜色1")
private String decorationColor1;
@ApiModelProperty(notes = "装饰颜色2")
private String decorationColor2;
@ApiModelProperty(notes = "是否反转")
private Boolean reverse;
@ApiModelProperty(notes = "动画时长")
private Integer dur;
@ApiModelProperty(notes = "扫描动画时长")
private Integer scanDur;
@ApiModelProperty(notes = "光晕动画时长")
private Integer haloDur;
@ApiModelProperty(notes = "标题")
private String title;
@ApiModelProperty(notes = "字体大小")
private Integer fontSize;
@ApiModelProperty(notes = "字体粗细")
private Integer fontWeight;
@ApiModelProperty(notes = "字体颜色")
private String color;
@ApiModelProperty(notes = "边框颜色")
private String borderColor;
@ApiModelProperty(notes = "边框宽度")
private Integer borderWidth;
}
}

View File

@@ -0,0 +1,82 @@
package com.gccloud.dataroom.core.module.chart.components;
import com.gccloud.dataroom.core.constant.PageDesignConstant;
import com.gccloud.dataroom.core.module.chart.bean.Chart;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.Map;
/**
* @author hongyang
* @version 1.0
* @date 2023/5/24 14:36
*/
@Data
public class ScreenDigitalFlopChart extends Chart {
@ApiModelProperty(notes = "类型")
private String type = PageDesignConstant.BigScreen.Type.DIGITAL_FLOP;
@ApiModelProperty(notes = "个性化")
private Customize customize = new Customize();
@Data
public static class Customize {
@ApiModelProperty(notes = "字体颜色")
private String color;
@ApiModelProperty(notes = "背景颜色")
private String bgColor;
@ApiModelProperty(notes = "字体大小")
private Integer fontSize;
@ApiModelProperty(notes = "宽度")
private Integer width;
@ApiModelProperty(notes = "圆角")
private Integer borderRadius;
@ApiModelProperty(notes = "格式化")
private Integer formatter;
@ApiModelProperty(notes = "字体粗细")
private String fontWeight;
@ApiModelProperty(notes = "左侧插槽")
private String slotLeft;
@ApiModelProperty(notes = "右侧插槽")
private String slotRight;
@ApiModelProperty(notes = "右侧margin")
private Integer marginRight;
@ApiModelProperty(notes = "数字位数")
private Integer numberDigits;
@ApiModelProperty(notes = "占位符")
private String placeHolder;
@ApiModelProperty(notes = "高度")
private Integer height;
@ApiModelProperty(notes = "边框颜色")
private String borderColor;
@ApiModelProperty(notes = "边框宽度")
private Integer borderWidth;
@ApiModelProperty("字体")
private String fontFamily;
@ApiModelProperty("线条样式")
private Map<String, Object> lineStyle;
}
}

View File

@@ -0,0 +1,134 @@
package com.gccloud.dataroom.core.module.chart.components;
import com.gccloud.dataroom.core.constant.PageDesignConstant;
import com.gccloud.dataroom.core.module.chart.bean.Chart;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.List;
import java.util.Map;
/**
* 飞线地图
* @author hongyang
* @version 1.0
* @date 2023/8/24 17:03
*/
@Data
public class ScreenFlyMapChart extends Chart{
@ApiModelProperty(notes = "类型")
private String type = PageDesignConstant.BigScreen.Type.FLY_MAP;
@ApiModelProperty(notes = "个性化")
private Customize customize = new Customize();
@Data
public static class Customize {
@ApiModelProperty(notes = "数据配置")
private Map<String, Object> dataField;
@ApiModelProperty(notes = "地图id")
private String mapId;
@ApiModelProperty(notes = "是否显示文字")
private Boolean mapName;
@ApiModelProperty(notes = "文字颜色")
private String mapNameColor;
@ApiModelProperty(notes = "文字大小")
private Integer mapNameSize;
@ApiModelProperty(notes = "文字权重")
private Integer mapNameWeight;
@ApiModelProperty(notes = "悬浮框背景色")
private String tooltipBackgroundColor;
@ApiModelProperty(notes = "悬浮框边框色")
private String borderColor;
@ApiModelProperty(notes = "悬浮框字体颜色")
private String fontColor;
@ApiModelProperty(notes = "打点图背景颜色")
private String scatterBackgroundColor;
@ApiModelProperty(notes = "打点图文字颜色")
private String scatterColor;
@ApiModelProperty(notes = "打点图中心点文字颜色")
private String scatterCenterColor;
@ApiModelProperty(notes = "分割线颜色")
private String mapLineColor;
@ApiModelProperty(notes = "是否开启下钻")
private Boolean down;
@ApiModelProperty(notes = "允许下钻的层级")
private Integer downLevel;
@ApiModelProperty(notes = "轨迹图像")
private String symbol;
@ApiModelProperty(notes = "轨迹颜色")
private String symbolColor;
@ApiModelProperty(notes = "轨迹大小")
private Integer symbolSize;
@ApiModelProperty(notes = "地图级别")
private String level;
@ApiModelProperty(notes = "范围")
private String scope;
@ApiModelProperty(notes = "地图区域颜色")
private String areaColor;
@ApiModelProperty(notes = "是否开启筛选")
private Boolean visual;
@ApiModelProperty(notes = "筛选范围")
private List<Integer> range;
@ApiModelProperty(notes = "打点图格式化脚本")
private String scatterFormatter;
@ApiModelProperty(notes = "轨迹格式化脚本")
private String lineFormatter;
@ApiModelProperty(notes = "从上到下的颜色")
private List<String> rangeColor;
@ApiModelProperty(notes = "地图数据")
private String dataMap;
@ApiModelProperty(notes = "展示字段")
private String value;
@ApiModelProperty(notes = "横坐标")
private String xaxis;
@ApiModelProperty(notes = "纵坐标")
private String yaxis;
@ApiModelProperty(notes = "名称")
private String name;
@ApiModelProperty(notes = "图形")
private List<String> graphic;
@ApiModelProperty(notes = "图形字体颜色")
private String fontGraphicColor;
@ApiModelProperty(notes = "图形字体大小")
private String fontSize;
}
}

View File

@@ -0,0 +1,22 @@
package com.gccloud.dataroom.core.module.chart.components;
import com.gccloud.dataroom.core.constant.PageDesignConstant;
import com.gccloud.dataroom.core.module.chart.bean.Chart;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* @author hongyang
* @version 1.0
* @date 2023/3/13 16:44
*/
@Data
public class ScreenIframeChart extends Chart {
@ApiModelProperty(notes = "外链地址")
private String url;
@ApiModelProperty(notes = "类型")
private String type = PageDesignConstant.BigScreen.Type.IFRAME;
}

View File

@@ -0,0 +1,94 @@
package com.gccloud.dataroom.core.module.chart.components;
import com.gccloud.dataroom.core.constant.PageDesignConstant;
import com.gccloud.dataroom.core.module.chart.bean.Chart;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* 指标卡组件
* @author hongyang
* @version 1.0
* @date 2023/10/7 10:58
*/
@Data
public class ScreenIndexCardChart extends Chart {
@ApiModelProperty(notes = "类型")
private String type = PageDesignConstant.BigScreen.Type.INDEX_CARD;
@ApiModelProperty(notes = "个性化配置")
private Customize customize = new Customize();
@Data
public static class Customize {
@ApiModelProperty(notes = "图片地址")
private String src;
@ApiModelProperty(notes = "边框圆角")
private Integer borderRadius;
@ApiModelProperty(notes = "边框宽度")
private Integer borderWidth;
@ApiModelProperty(notes = "边框线距离")
private Integer lineDistance;
@ApiModelProperty(notes = "边框颜色")
private String borderColor;
@ApiModelProperty(notes = "背景颜色")
private String bgColor;
@ApiModelProperty(notes = "距离")
private Integer distance;
@ApiModelProperty(notes = "图片大小")
private Integer imgSize;
@ApiModelProperty(notes = "第一行字体大小")
private Integer firstSize;
@ApiModelProperty(notes = "第一行字体颜色")
private String firstColor;
@ApiModelProperty(notes = "第一行字体粗细")
private Integer firstWeight;
@ApiModelProperty(notes = "第二行字体大小")
private Integer secondSize;
@ApiModelProperty(notes = "第二行字体颜色")
private String secondColor;
@ApiModelProperty(notes = "第二行字体粗细")
private Integer secondWeight;
@ApiModelProperty(notes = "第二行字体内容")
private String secondLine;
@ApiModelProperty(notes = "字体")
private String fontFamily;
@ApiModelProperty(notes = "单位")
private String unit;
@ApiModelProperty(notes = "单位字体大小")
private Integer unitSize;
@ApiModelProperty(notes = "单位字体颜色")
private String unitColor;
@ApiModelProperty(notes = "渐变方向")
private String gradientDirection;
@ApiModelProperty(notes = "渐变颜色0")
private String gradientColor0;
@ApiModelProperty(notes = "渐变颜色1")
private String gradientColor1;
}
}

View File

@@ -0,0 +1,84 @@
package com.gccloud.dataroom.core.module.chart.components;
import com.gccloud.dataroom.core.constant.PageDesignConstant;
import com.gccloud.dataroom.core.module.chart.bean.Chart;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* 指标卡组件
* @author hongyang
* @version 1.0
* @date 2023/10/7 10:58
*/
@Data
public class ScreenIndicatorCardChart extends Chart {
@ApiModelProperty(notes = "类型")
private String type = PageDesignConstant.BigScreen.Type.INDICATOR_CARD;
@ApiModelProperty(notes = "个性化配置")
private Customize customize = new Customize();
@Data
public static class Customize {
@ApiModelProperty(notes = "边框圆角")
private Integer borderRadius;
@ApiModelProperty(notes = "边框宽度")
private Integer borderWidth;
@ApiModelProperty(notes = "边框线距离")
private Integer lineDistance;
@ApiModelProperty(notes = "边框颜色")
private String borderColor;
@ApiModelProperty(notes = "背景颜色")
private String bgColor;
@ApiModelProperty(notes = "第一行字体大小")
private Integer firstSize;
@ApiModelProperty(notes = "第一行字体颜色")
private String firstColor;
@ApiModelProperty(notes = "第一行字体粗细")
private Integer firstWeight;
@ApiModelProperty(notes = "第二行字体大小")
private Integer secondSize;
@ApiModelProperty(notes = "第二行字体颜色")
private String secondColor;
@ApiModelProperty(notes = "第二行字体粗细")
private Integer secondWeight;
@ApiModelProperty(notes = "第二行字体内容")
private String secondLine;
@ApiModelProperty(notes = "字体")
private String fontFamily;
@ApiModelProperty(notes = "单位")
private String unit;
@ApiModelProperty(notes = "单位字体大小")
private Integer unitSize;
@ApiModelProperty(notes = "单位字体颜色")
private String unitColor;
@ApiModelProperty(notes = "渐变方向")
private String gradientDirection;
@ApiModelProperty(notes = "渐变颜色0")
private String gradientColor0;
@ApiModelProperty(notes = "渐变颜色1")
private String gradientColor1;
}
}

View File

@@ -0,0 +1,118 @@
package com.gccloud.dataroom.core.module.chart.components;
import com.gccloud.dataroom.core.constant.PageDesignConstant;
import com.gccloud.dataroom.core.module.chart.bean.Chart;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* 输入框
* @author hongyang
* @version 1.0
* @date 2023/3/13 16:44
*/
@Data
public class ScreenInputChart extends Chart {
@ApiModelProperty(notes = "组件类型")
private String type = PageDesignConstant.BigScreen.Type.INPUT;
@ApiModelProperty(notes = "个性化")
private Customize customize = new Customize();
@Data
public static class Customize {
@ApiModelProperty(notes = "是否显示标题")
private boolean showTitle;
@ApiModelProperty(notes = "标题")
private String title;
@ApiModelProperty(notes = "标题样式")
private TitleStyle titleStyle;
@ApiModelProperty(notes = "输入框样式")
private InputStyle inputStyle;
@ApiModelProperty(notes = "占位符样式")
private PlaceholderStyle placeholderStyle;
@ApiModelProperty(notes = "边框样式")
private BorderStyle borderStyle;
@ApiModelProperty(notes = "背景样式")
private BackgroundStyle backgroundStyle;
@ApiModelProperty(notes = "图标")
private Icon icon;
}
@Data
public static class Icon {
@ApiModelProperty(notes = "图标名称")
private String name;
@ApiModelProperty(notes = "位置")
private String position;
}
@Data
public static class InputStyle {
@ApiModelProperty(notes = "输入值字体大小")
private Integer fontSize;
@ApiModelProperty(notes = "输入值字体颜色")
private String color;
}
@Data
public static class TitleStyle {
@ApiModelProperty(notes = "标题大小")
private Integer fontSize;
@ApiModelProperty(notes = "标题颜色")
private String color;
@ApiModelProperty(notes = "标题间距")
private Integer marginRight;
}
@Data
public static class BorderStyle {
@ApiModelProperty(notes = "边框颜色")
private String borderColor;
@ApiModelProperty(notes = "边框宽度")
private Integer borderWidth;
@ApiModelProperty(notes = "边框样式")
private String borderStyle;
@ApiModelProperty(notes = "边框圆角")
private Integer borderRadius;
}
@Data
public static class BackgroundStyle {
@ApiModelProperty(notes = "背景颜色")
private String backgroundColor;
}
@Data
public static class PlaceholderStyle {
@ApiModelProperty(notes = "占位符")
private String placeholder;
@ApiModelProperty(notes = "占位符字体颜色")
private String placeholderColor;
@ApiModelProperty(notes = "占位符字体大小")
private Integer placeholderFontSize;
}
}

View File

@@ -0,0 +1,51 @@
package com.gccloud.dataroom.core.module.chart.components;
import com.gccloud.dataroom.core.constant.PageDesignConstant;
import com.gccloud.dataroom.core.module.chart.bean.Chart;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* 链接组件
* @author hongyang
* @version 1.0
* @date 2023/3/13 16:44
*/
@Data
public class ScreenLinkChart extends Chart {
@ApiModelProperty(notes = "组件类型")
private String type = PageDesignConstant.BigScreen.Type.LINK;
@ApiModelProperty(notes = "个性化")
private Customize customize = new Customize();
@Data
public static class Customize {
@ApiModelProperty(notes = "字体大小")
private Integer fontSize;
@ApiModelProperty(notes = "字体粗细")
private Integer fontWeight;
@ApiModelProperty(notes = "字体颜色")
private String color;
@ApiModelProperty(notes = "标题")
private String title;
@ApiModelProperty(notes = "链接地址")
private String url;
@ApiModelProperty(notes = "打开方式")
private String openType;
@ApiModelProperty(notes = "弹窗宽度")
private Integer dialogW;
@ApiModelProperty(notes = "弹窗高度")
private Integer dialogH;
}
}

View File

@@ -0,0 +1,137 @@
package com.gccloud.dataroom.core.module.chart.components;
import com.gccloud.dataroom.core.constant.PageDesignConstant;
import com.gccloud.dataroom.core.module.chart.bean.Chart;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* 地图组件
* @author hongyang
* @version 1.0
* @date 2023/3/13 16:44
*/
@Data
public class ScreenMapChart extends Chart {
@ApiModelProperty(notes = "组件类型")
private String type = PageDesignConstant.BigScreen.Type.MAP;
@ApiModelProperty(notes = "个性化")
private Customize customize = new Customize();
@Data
public static class Customize {
@ApiModelProperty(notes = "地图id")
private String mapId;
@ApiModelProperty(notes = "是否显示文字")
private Boolean mapName;
@ApiModelProperty(notes = "文字颜色")
private String mapNameColor;
@ApiModelProperty(notes = "文字大小")
private Integer mapNameSize;
@ApiModelProperty(notes = "文字权重")
private Integer mapNameWeight;
@ApiModelProperty(notes = "地图背景色")
private String backgroundColor;
@ApiModelProperty(notes = "是否打点")
private Boolean scatter;
@ApiModelProperty(notes = "悬浮框背景色")
private String tooltipBackgroundColor;
@ApiModelProperty(notes = "悬浮框边框色")
private String borderColor;
@ApiModelProperty(notes = "打点图背景颜色")
private String scatterBackgroundColor;
@ApiModelProperty(notes = "打点图文字颜色")
private String scatterColor;
@ApiModelProperty(notes = "分割线颜色")
private String mapLineColor;
@ApiModelProperty(notes = "地图级别")
private String level;
@ApiModelProperty(notes = "范围")
private String scope;
@ApiModelProperty(notes = "地图区域颜色")
private String areaColor;
@ApiModelProperty(notes = "是否开启筛选")
private Boolean visual;
@ApiModelProperty(notes = "筛选范围")
private Integer[] range;
@ApiModelProperty(notes = "从上到下的颜色")
private String[] rangeColor;
@ApiModelProperty(notes = "地图数据")
private String dataMap;
@ApiModelProperty(notes = "经度")
private String xaxis;
@ApiModelProperty(notes = "纬度")
private String yaxis;
@ApiModelProperty(notes = "名称")
private String name;
@ApiModelProperty(notes = "")
private String value;
@ApiModelProperty(notes = "图形字体颜色")
private String fontGraphicColor;
@ApiModelProperty(notes = "图形字体大小")
private String fontSize;
@ApiModelProperty(notes = "是否开启下钻")
private Boolean down;
@ApiModelProperty(notes = "允许下钻的层级")
private Integer downLevel;
@ApiModelProperty(notes = "地图比例")
private Float zoom;
@ApiModelProperty(notes = "中心点x轴位置")
private Integer center1;
@ApiModelProperty(notes = "中心点y轴位置")
private Integer center2;
@ApiModelProperty(notes = "悬浮框数值标题")
private String tooltipTitle;
@ApiModelProperty(notes = "是否显示打点数值")
private Boolean showScatterValue;
@ApiModelProperty(notes = "打点图形")
private String scatterSymbol;
@ApiModelProperty(notes = "打点大小")
private Integer scatterSize;
@ApiModelProperty(notes = "高亮颜色")
private String emphasisColor;
}
}

View File

@@ -0,0 +1,83 @@
package com.gccloud.dataroom.core.module.chart.components;
import com.gccloud.dataroom.core.constant.PageDesignConstant;
import com.gccloud.dataroom.core.module.chart.bean.Chart;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.Map;
/**
* @author hongyang
* @version 1.0
* @date 2023/8/24 17:03
*/
@Data
public class ScreenMarqueeChart extends Chart{
@ApiModelProperty(notes = "类型")
private String type = PageDesignConstant.BigScreen.Type.MARQUEE;
@ApiModelProperty(notes = "自定义处理数据源脚本")
private String dataHandler;
@ApiModelProperty(notes = "个性化")
private Customize customize = new Customize();
@Data
public static class Customize {
@ApiModelProperty(notes = "标题")
private String title;
@ApiModelProperty(notes = "字体大小")
private Integer fontSize = 20;
@ApiModelProperty(notes = "字体权重")
private Integer fontWeight = 700;
@ApiModelProperty(notes = "图标")
private Map<String, String> icon;
@ApiModelProperty(notes = "文字颜色类型: 纯色、渐变")
private String textColorType;
@ApiModelProperty(notes = "文字颜色")
private String textColor;
@ApiModelProperty(notes = "文字渐变开始颜色")
private String textGradientColor0;
@ApiModelProperty(notes = "文字渐变结束颜色")
private String textGradientColor1;
@ApiModelProperty(notes = "文字渐变方向")
private String textGradientDirection;
@ApiModelProperty(notes = "滚动方向")
private String direction;
@ApiModelProperty(notes = "滚动间隔")
private String dur;
@ApiModelProperty(notes = "背景色类型:纯色、渐变、透明")
private String backgroundColorType;
@ApiModelProperty(notes = "背景色")
private String backgroundColor;
@ApiModelProperty(notes = "背景渐变色开始颜色")
private String bgGradientColor0;
@ApiModelProperty(notes = "背景渐变色结束颜色")
private String bgGradientColor1;
@ApiModelProperty(notes = "背景色渐变方向")
private String bgGradientDirection;
@ApiModelProperty(notes = "语音播报")
private Boolean voiceBroadcast;
}
}

View File

@@ -0,0 +1,51 @@
package com.gccloud.dataroom.core.module.chart.components;
import com.gccloud.dataroom.core.constant.PageDesignConstant;
import com.gccloud.dataroom.core.module.chart.bean.Chart;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* 数字
* @author hongyang
* @version 1.0
* @date 2023/10/12 17:23
*/
@Data
public class ScreenNumbersChart extends Chart {
@ApiModelProperty(notes = "组件类型")
private String type = PageDesignConstant.BigScreen.Type.NUMBER;
@ApiModelProperty(notes = "个性化")
private Customize customize = new Customize();
@Data
public static class Customize {
@ApiModelProperty(notes = "字体大小")
private Integer fontSize;
@ApiModelProperty(notes = "字体粗细")
private Integer fontWeight;
@ApiModelProperty(notes = "字体")
private String fontFamily;
@ApiModelProperty(notes = "字体颜色")
private String color;
@ApiModelProperty(notes = "标题")
private String title;
@ApiModelProperty(notes = "文字对齐方式")
private String align;
@ApiModelProperty(notes = "文字间距")
private Integer letterSpacing;
@ApiModelProperty(notes = "千分位")
private Boolean thousands;
}
}

View File

@@ -0,0 +1,32 @@
package com.gccloud.dataroom.core.module.chart.components;
import com.gccloud.dataroom.core.module.chart.bean.Chart;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* 图片
* @author hongyang
* @version 1.0
* @date 2023/3/16 10:30
*/
@Data
public class ScreenPictureChart extends Chart {
@ApiModelProperty(notes = "自定义")
private Customize customize;
@Data
public static class Customize {
@ApiModelProperty(notes = "透明度")
private Float opacity;
@ApiModelProperty(notes = "圆角")
private Integer radius;
@ApiModelProperty(notes = "图片地址")
private String url;
}
}

View File

@@ -0,0 +1,22 @@
package com.gccloud.dataroom.core.module.chart.components;
import com.gccloud.dataroom.core.module.chart.bean.Chart;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.Map;
/**
* 文本
* @author hongyang
* @version 1.0
* @date 2023/3/13 16:44
*/
@Data
public class ScreenSankeyChart extends Chart {
@ApiModelProperty(notes = "个性化")
private Map<String, Object> customize;
}

View File

@@ -0,0 +1,68 @@
package com.gccloud.dataroom.core.module.chart.components;
import com.gccloud.dataroom.core.constant.PageDesignConstant;
import com.gccloud.dataroom.core.module.chart.bean.Chart;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.HashMap;
import java.util.List;
/**
* @author hongyang
* @version 1.0
* @date 2023/3/22 14:50
*/
@Data
public class ScreenScrollBoardChart extends Chart {
@ApiModelProperty(notes = "类型")
private String type = PageDesignConstant.BigScreen.Type.SCREEN_SCROLL_BOARD;
@ApiModelProperty(notes = "个性化")
private Customize customize = new Customize();
@Data
public static class Customize{
@ApiModelProperty(notes = "列配置")
private List<HashMap<String, Object>> columnConfig;
@ApiModelProperty(notes = "滚动条数")
private Integer rowNum;
@ApiModelProperty(notes = "表头背景色")
private String headerBGC;
@ApiModelProperty(notes = "奇数行背景色")
private String oddRowBGC;
@ApiModelProperty(notes = "偶数行背景色")
private String evenRowBGC;
@ApiModelProperty(notes = "滚动间隔时间")
private Integer waitTime;
@ApiModelProperty(notes = "表头高度")
private Integer headerHeight;
@ApiModelProperty(notes = "列宽")
private List<String> columnWidth;
@ApiModelProperty(notes = "对齐方式")
private List<String> align;
@ApiModelProperty(notes = "是否显示行号")
private Boolean index;
@ApiModelProperty(notes = "序号表头")
private String indexHeader;
@ApiModelProperty(notes = "滚动方向")
private String carousel;
@ApiModelProperty(notes = "鼠标悬停是否暂停")
private Boolean hoverPause;
}
}

View File

@@ -0,0 +1,66 @@
package com.gccloud.dataroom.core.module.chart.components;
import com.gccloud.dataroom.core.constant.PageDesignConstant;
import com.gccloud.dataroom.core.module.chart.bean.Chart;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* @author hongyang
* @version 1.0
* @date 2023/3/22 16:10
*/
@Data
public class ScreenScrollRankingChart extends Chart {
@ApiModelProperty(notes = "类型")
private String type = PageDesignConstant.BigScreen.Type.SCREEN_SCROLL_RANKING;
@ApiModelProperty(notes = "个性化")
private Customize customize = new Customize();
@Data
public static class Customize {
@ApiModelProperty(notes = "滚动条数")
private Integer rowNum;
@ApiModelProperty(notes = "滚动间隔时间")
private Integer waitTime;
@ApiModelProperty(notes = "是否轮播")
private String carousel;
@ApiModelProperty(notes = "单位")
private String unit;
@ApiModelProperty(notes = "是否自动排序")
private Boolean sort;
@ApiModelProperty("排名字体大小")
private Integer rankFontSize;
@ApiModelProperty("排名字体颜色")
private String rankColor;
@ApiModelProperty("名称字体大小")
private Integer infoNameFontSize;
@ApiModelProperty("名称字体颜色")
private String infoNameColor;
@ApiModelProperty("值字体大小")
private Integer rankingValueFontSize;
@ApiModelProperty("值字体颜色")
private String rankingValueColor;
@ApiModelProperty("内部柱子颜色")
private String insideColumnColor;
@ApiModelProperty("排名柱子底部颜色")
private String rankingColumnBorderBottomColor;
}
}

View File

@@ -0,0 +1,67 @@
package com.gccloud.dataroom.core.module.chart.components;
import com.gccloud.dataroom.core.constant.PageDesignConstant;
import com.gccloud.dataroom.core.module.chart.bean.Chart;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* 下拉选择
* @author hongyang
* @version 1.0
* @date 2023/3/13 16:44
*/
@Data
public class ScreenSelectChart extends Chart {
@ApiModelProperty(notes = "组件类型")
private String type = PageDesignConstant.BigScreen.Type.SELECT;
@ApiModelProperty(notes = "个性化")
private Customize customize = new Customize();
@Data
public static class Customize {
@ApiModelProperty("输入框背景颜色")
private String backgroundColor;
@ApiModelProperty("输入框字体大小")
private Integer fontSize;
@ApiModelProperty("输入框字体颜色")
private String fontColor;
@ApiModelProperty("下拉框背景颜色")
private String dropDownBackgroundColor;
@ApiModelProperty("下拉框字体颜色")
private String dropDownFontColor;
@ApiModelProperty("下拉项hover背景颜色")
private String dropDownHoverBackgroundColor;
@ApiModelProperty("下拉项hover字体颜色")
private String dropDownHoverFontColor;
@ApiModelProperty("激活项背景颜色")
private String activeBackgroundColor;
@ApiModelProperty("激活项字体颜色")
private String activeFontColor;
@ApiModelProperty("占位提示")
private String placeholder;
@ApiModelProperty("边框颜色")
private String borderColor;
@ApiModelProperty("占位符字体颜色")
private String placeholderColor;
@ApiModelProperty("占位符字体大小")
private Integer placeholderFontSize;
}
}

View File

@@ -0,0 +1,22 @@
package com.gccloud.dataroom.core.module.chart.components;
import com.gccloud.dataroom.core.constant.PageDesignConstant;
import com.gccloud.dataroom.core.module.chart.bean.Chart;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* @author hongyang
* @version 1.0
* @date 2023/3/13 16:44
*/
@Data
public class ScreenSvgsChart extends Chart {
@ApiModelProperty(notes = "类型")
private String type = PageDesignConstant.BigScreen.Type.SVGS;
@ApiModelProperty(notes = "图标")
private String icon;
}

View File

@@ -0,0 +1,90 @@
package com.gccloud.dataroom.core.module.chart.components;
import com.gccloud.dataroom.core.constant.PageDesignConstant;
import com.gccloud.dataroom.core.module.chart.bean.Btn;
import com.gccloud.dataroom.core.module.chart.bean.Chart;
import com.gccloud.dataroom.core.module.chart.bean.Field;
import com.gccloud.dataroom.core.module.chart.components.datasource.BaseChartDataSource;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.List;
/**
* @author hongyang
* @version 1.0
* @date 2023/3/13 16:44
*/
@Data
public class ScreenTablesChart extends Chart {
@ApiModelProperty(notes = "数据源")
private BaseChartDataSource dataSource;
@ApiModelProperty(notes = "版本")
private String version;
@ApiModelProperty(notes = "类型")
private String type = PageDesignConstant.BigScreen.Type.TABLES;
@ApiModelProperty(notes = "个性化")
private Customize customize = new Customize();
@ApiModelProperty(notes = "快速筛选项配置")
private List<Field> fields;
@ApiModelProperty(notes = "查询表单按钮")
private List<Btn> btns;
@ApiModelProperty(notes = "操作按钮")
private List<Btn> opts;
@ApiModelProperty(notes = "列按钮")
private List<Btn> colBtns;
@Data
public static class Customize {
@ApiModelProperty(notes = "是否前端分页")
private boolean webPagination = false;
@ApiModelProperty(notes = "分页页长0表示不分页仅在服务端分页未开启时生效")
private Integer pageSize;
/**
* 大屏表格属性
*/
@ApiModelProperty(notes = "表格主题")
private String theme = "dark";
@ApiModelProperty(notes = "表格头部背景颜色")
private String headerBackgroundColor = "#1d1d1d";
@ApiModelProperty(notes = "表格头部字体颜色")
private String headerFontColor = "#ffffff";
@ApiModelProperty(notes = "表格头部字体大小")
private Integer headerFontSize = 14;
@ApiModelProperty(notes = "表格主体背景颜色")
private String bodyBackgroundColor = "#1d1d1d";
@ApiModelProperty(notes = "表格主体字体颜色")
private String bodyFontColor = "#ffffff";
@ApiModelProperty(notes = "表格主体字体大小")
private Integer bodyFontSize = 14;
@ApiModelProperty(notes = "是否开启斑马纹")
private boolean stripe = false;
@ApiModelProperty(notes = "表格偶数行背景颜色")
private String evenRowBackgroundColor;
@ApiModelProperty(notes = "表格奇数行背景颜色")
private String oddRowBackgroundColor;
}
}

View File

@@ -0,0 +1,49 @@
package com.gccloud.dataroom.core.module.chart.components;
import com.gccloud.dataroom.core.constant.PageDesignConstant;
import com.gccloud.dataroom.core.module.chart.bean.Chart;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* 文本
* @author hongyang
* @version 1.0
* @date 2023/3/13 16:44
*/
@Data
public class ScreenTextChart extends Chart {
@ApiModelProperty(notes = "组件类型")
private String type = PageDesignConstant.BigScreen.Type.TEXT;
@ApiModelProperty(notes = "个性化")
private Customize customize = new Customize();
@ApiModelProperty(notes = "自定义处理数据源脚本")
private String dataHandler;
@Data
public static class Customize {
@ApiModelProperty(notes = "字体大小")
private Integer fontSize;
@ApiModelProperty(notes = "字体粗细")
private Integer fontWeight;
@ApiModelProperty(notes = "字体")
private String fontFamily;
@ApiModelProperty(notes = "字体颜色")
private String color;
@ApiModelProperty(notes = "标题")
private String title;
@ApiModelProperty(notes = "文字对齐方式")
private String align;
@ApiModelProperty(notes = "文字间距")
private Integer letterSpacing;
}
}

View File

@@ -0,0 +1,55 @@
package com.gccloud.dataroom.core.module.chart.components;
import com.gccloud.dataroom.core.constant.PageDesignConstant;
import com.gccloud.dataroom.core.module.chart.bean.Chart;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.Date;
/**
* @author hongyang
* @version 1.0
* @date 2023/3/13 16:44
*/
@Data
public class ScreenTimeCountDownChart extends Chart {
/**
* 描述
*/
@ApiModelProperty(notes = "描述")
private String title;
/**
* 以结束时间进行倒计时
*/
@ApiModelProperty(notes = "结束时间")
private Date endTime;
@ApiModelProperty(notes = "类型")
private String type = PageDesignConstant.BigScreen.Type.TIME_COUNT_DOWN;
@ApiModelProperty(notes = "个性化")
private Customize customize = new Customize();
@ApiModelProperty(notes = "日期格式")
private String dateFormat;
@Data
public static class Customize {
@ApiModelProperty(notes = "字体大小")
private Integer fontSize = 14;
@ApiModelProperty(notes = "字体权重")
private Integer fontWeight = 700;
@ApiModelProperty(notes = "字体颜色")
private String color;
@ApiModelProperty(notes = "字体")
private String fontFamily;
}
}

View File

@@ -0,0 +1,63 @@
package com.gccloud.dataroom.core.module.chart.components;
import com.gccloud.dataroom.core.constant.PageDesignConstant;
import com.gccloud.dataroom.core.module.chart.bean.Chart;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* 时间选择
* @author hongyang
* @version 1.0
* @date 2023/09/14 16:44
*/
@Data
public class ScreenTimePickerChart extends Chart {
@ApiModelProperty(notes = "组件类型")
private String type = PageDesignConstant.BigScreen.Type.TIME_PICKER;
@ApiModelProperty(notes = "个性化")
private Customize customize = new Customize();
@Data
public static class Customize {
@ApiModelProperty(notes = "选择框背景颜色")
private String backgroundColor;
@ApiModelProperty(notes = "选择框文字颜色")
private String fontColor;
@ApiModelProperty(notes = "选择框文字大小")
private Integer fontSize;
@ApiModelProperty(notes = "下拉框背景颜色")
private String dropDownBackgroundColor;
@ApiModelProperty(notes = "下拉框字体颜色")
private String dropDownFontColor;
@ApiModelProperty(notes = "下拉项hover背景颜色")
private String dropDownHoverBackgroundColor;
@ApiModelProperty(notes = "下拉项hover字体颜色")
private String dropDownHoverFontColor;
@ApiModelProperty(notes = "下拉项激活文字颜色")
private String dropDownSelectedFontColor;
@ApiModelProperty(notes = "时间格式化类型:Date 对象default时间戳timestamp自定义custom")
private String formatType;
@ApiModelProperty(notes = "绑定值的格式")
private String valueFormat;
@ApiModelProperty(notes = "显示的格式")
private String format;
}
}

View File

@@ -0,0 +1,36 @@
package com.gccloud.dataroom.core.module.chart.components;
import com.gccloud.dataroom.core.constant.PageDesignConstant;
import com.gccloud.dataroom.core.module.chart.bean.Chart;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* 视频组件
* @author hongyang
* @version 1.0
* @date 2023/3/13 16:44
*/
@Data
public class ScreenVideoChart extends Chart {
@ApiModelProperty(notes = "组件类型")
private String type = PageDesignConstant.BigScreen.Type.VIDEO;
@ApiModelProperty(notes = "个性化")
private Customize customize = new Customize();
@Data
public static class Customize {
@ApiModelProperty(notes = "视频类型")
private String videoType;
@ApiModelProperty(notes = "视频地址")
private String videoUrl;
@ApiModelProperty(notes = "封面地址")
private String posterUrl;
}
}

View File

@@ -0,0 +1,41 @@
package com.gccloud.dataroom.core.module.chart.components;
import com.gccloud.dataroom.core.constant.PageDesignConstant;
import com.gccloud.dataroom.core.module.chart.bean.Chart;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* 主题选择器
* @author hongyang
* @version 1.0
* @date 2023/8/24 17:03
*/
@Data
public class ThemeSelectChart extends Chart{
@ApiModelProperty(notes = "类型")
private String type = PageDesignConstant.BigScreen.Type.THEME_SELECT;
@ApiModelProperty(notes = "个性化")
private Customize customize = new Customize();
@Data
public static class Customize {
@ApiModelProperty(notes = "标题")
private String title;
@ApiModelProperty(notes = "字体大小")
private Integer fontSize = 20;
@ApiModelProperty(notes = "字体权重")
private Integer fontWeight = 700;
@ApiModelProperty(notes = "字体颜色")
private String color;
}
}

View File

@@ -0,0 +1,46 @@
package com.gccloud.dataroom.core.module.chart.components;
import com.gccloud.dataroom.core.constant.PageDesignConstant;
import com.gccloud.dataroom.core.module.chart.bean.Chart;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* @author hongyang
* @version 1.0
* @date 2023/8/24 17:03
*/
@Data
public class ThemeSwitcherChart extends Chart{
@ApiModelProperty(notes = "类型")
private String type = PageDesignConstant.BigScreen.Type.THEME_SWITCHER;
@ApiModelProperty(notes = "个性化")
private Customize customize = new Customize();
@Data
public static class Customize {
@ApiModelProperty(notes = "标题")
private String title;
@ApiModelProperty(notes = "字体大小")
private Integer fontSize = 20;
@ApiModelProperty(notes = "字体权重")
private Integer fontWeight = 700;
@ApiModelProperty(notes = "字体颜色")
private String color;
@ApiModelProperty(notes = "单选框字体激活状态")
private String activeColor;
@ApiModelProperty(notes = "单选框字体非激活状态")
private String inactiveColor;
}
}

View File

@@ -0,0 +1,17 @@
package com.gccloud.dataroom.core.module.chart.components.datasource;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import lombok.Data;
/**
* 图表数据源
* @author liuchengbiao
* @version 1.0
* @date 2022/8/8 15:11
*/
@Data
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "className")
public abstract class BaseChartDataSource {
}

View File

@@ -0,0 +1,89 @@
package com.gccloud.dataroom.core.module.chart.components.datasource;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.HashMap;
import java.util.List;
/**
* @author hongyang
* @version 1.0
* @date 2022/11/19 10:45
*/
@Data
public class DataSetDataSource extends BaseChartDataSource {
@ApiModelProperty(notes = "数据来源,可能为数据集或者表达式")
private String source;
@ApiModelProperty(notes = "数据集标识")
private String businessKey;
@ApiModelProperty(notes = "数据源标识")
private String dataSourceKey;
@ApiModelProperty(notes = "数据集类型")
private String dataSetType;
@ApiModelProperty(notes = "数据集参数")
private HashMap<String, Object> params;
@ApiModelProperty(notes = "x轴维度字段")
private String dimensionField;
@ApiModelProperty(notes = "y轴指标字段")
private String metricField;
@ApiModelProperty(notes = "拆分字段")
private String seriesField;
@ApiModelProperty(notes = "维度字段列表")
private List<String> dimensionFieldList;
@ApiModelProperty(notes = "指标字段列表")
private List<String> metricFieldList;
@ApiModelProperty(notes = "拆分字段列表")
private List<String> seriesFieldList;
@ApiModelProperty(notes = "服务端分页")
private Boolean serverPagination;
@ApiModelProperty(notes = "服务端分页页长")
private Integer pageSize;
/**
* 散点图特殊配置
*/
@ApiModelProperty(notes = "颜色字段")
private String colorField;
@ApiModelProperty(notes = "形状字段")
private String shapeField;
@ApiModelProperty(notes = "散点大小字段")
private String sizeField;
/**
* K线图特殊配置
*/
@ApiModelProperty(notes = "x轴字段")
private String xField;
@ApiModelProperty(notes = "开盘字段")
private String openField;
@ApiModelProperty(notes = "收盘字段")
private String closeField;
@ApiModelProperty(notes = "最低字段")
private String lowField;
@ApiModelProperty(notes = "最高字段")
private String highField;
}

View File

@@ -0,0 +1,151 @@
package com.gccloud.dataroom.core.module.chart.controller;
import com.gccloud.dataroom.core.module.basic.dto.BasePageDTO;
import com.gccloud.dataroom.core.module.basic.entity.PageEntity;
import com.gccloud.dataroom.core.module.chart.bean.Chart;
import com.gccloud.dataroom.core.module.chart.components.ChartTabChart;
import com.gccloud.dataroom.core.module.chart.components.ScreenFlyMapChart;
import com.gccloud.dataroom.core.module.chart.dto.ChartDataSearchDTO;
import com.gccloud.dataroom.core.module.chart.service.BaseChartDataService;
import com.gccloud.dataroom.core.module.chart.service.ChartMockData;
import com.gccloud.dataroom.core.module.chart.vo.ChartDataVO;
import com.gccloud.dataroom.core.module.manage.dto.DataRoomPageDTO;
import com.gccloud.dataroom.core.module.manage.service.IDataRoomPageService;
import com.gccloud.common.utils.AssertUtils;
import com.gccloud.common.vo.R;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
/**
* 图表组件数据获取
* @author liuchengbiao
* @version 1.0
* @date 2022/8/8 15:11
*/
@Slf4j
@RestController("dataRoomChartController")
@RequestMapping("/bigScreen/chart/data")
@Api(tags = "图表组件数据获取")
public class ChartDataController {
@Resource
private IDataRoomPageService pageService;
@Resource
private BaseChartDataService baseChartDataService;
@PostMapping("/list")
@ApiOperation(value = "图表数据", position = 10, notes = "获取指定图表的数据(通过唯一编码)", produces = MediaType.APPLICATION_JSON_VALUE)
public R<ChartDataVO> basicTableList(@RequestBody ChartDataSearchDTO chartDataSearchDTO) {
PageEntity pageEntity = pageService.getByCode(chartDataSearchDTO.getPageCode());
AssertUtils.isTrue(pageEntity != null, "页面不存在");
BasePageDTO config = pageEntity.getConfig();
List<Chart> chartList = null;
if (config.getClass().equals(DataRoomPageDTO.class)) {
chartList = ((DataRoomPageDTO) config).getChartList();
}
if (chartList == null) {
ChartDataVO mockData = ChartMockData.getMockData(chartDataSearchDTO.getType());
return R.success(mockData);
}
Chart chart = getByCode(chartList, chartDataSearchDTO.getChartCode());
return getChartData(chartDataSearchDTO, config, chart);
}
@PostMapping("/chart")
@ApiOperation(value = "图表数据", position = 20, notes = "获取指定图表的数据(通过配置)", produces = MediaType.APPLICATION_JSON_VALUE)
public R<ChartDataVO> getChartData(@RequestBody ChartDataSearchDTO chartDataSearchDTO) {
PageEntity pageEntity = pageService.getByCode(chartDataSearchDTO.getPageCode());
AssertUtils.isTrue(pageEntity != null, "页面不存在");
BasePageDTO config = pageEntity.getConfig();
Chart chart = chartDataSearchDTO.getChart();
return getChartData(chartDataSearchDTO, config, chart);
}
@GetMapping("/chart/mock/{type}")
@ApiOperation(value = "图表模拟数据", position = 30, notes = "获取指定类型的图表模拟数据", produces = MediaType.APPLICATION_JSON_VALUE)
public R<ChartDataVO> getMockData(@PathVariable String type) {
ChartDataVO mockData = ChartMockData.getMockData(type);
return R.success(mockData);
}
/**
* 获取图表数据
* @param chartDataSearchDTO
* @param config
* @param chart
* @return
*/
private R<ChartDataVO> getChartData(ChartDataSearchDTO chartDataSearchDTO, BasePageDTO config, Chart chart) {
if (chart == null) {
ChartDataVO mockData = ChartMockData.getMockData(chartDataSearchDTO.getType());
return R.success(mockData);
}
try {
ChartDataVO chartDataVO = baseChartDataService.dataQuery(chart, chartDataSearchDTO);
//暂时未找到解决办法故在此拦截mqtt的前后端方式
// Object apiConfig=chartDataVO.getData();
// if ("frontend".equals(apiConfig.get("requestType"))) {
// chartDataVO.setExecutionByFrontend(true);
// }
//暂时未找到解决办法故在此拦截mqtt的前后端方式
if (chartDataVO == null) {
String type = chartDataSearchDTO.getType();
if (chart instanceof ScreenFlyMapChart) {
ScreenFlyMapChart screenFlyMapChart = (ScreenFlyMapChart) chart;
ScreenFlyMapChart.Customize customize = screenFlyMapChart.getCustomize();
// 兼容旧版地图等级
switch (customize.getLevel()) {
case "0":
type += "-world";
break;
case "1":
type += "-country";
break;
case "2":
type += "-province";
break;
default:
type += "-" + customize.getLevel();
}
}
chartDataVO = ChartMockData.getMockData(type);
}
return R.success(chartDataVO);
} catch (Exception e) {
log.error("图表数据获取失败", e);
ChartDataVO mockData = ChartMockData.getMockData(chartDataSearchDTO.getType());
return R.success(mockData);
}
}
/**
* 从组件列表中获取指定code的图表组件
* @param chartList
* @param code
* @return
*/
public Chart getByCode(List<Chart> chartList, String code) {
for (Chart chart : chartList) {
if (chart.getCode().equals(code)) {
return chart;
}
// 如果是Tab图表尝试从内部图表中获取
if (chart instanceof ChartTabChart) {
ChartTabChart chartTabChart = (ChartTabChart) chart;
Chart innerChart = chartTabChart.getInnerChart(code);
if (innerChart != null) {
return innerChart;
}
}
}
return null;
}
}

View File

@@ -0,0 +1,47 @@
package com.gccloud.dataroom.core.module.chart.dto;
import com.gccloud.dataroom.core.module.chart.bean.Chart;
import com.gccloud.dataroom.core.module.chart.bean.Filter;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.List;
/**
* 数据查询
* @author liuchengbiao
* @version 1.0
* @date 2022/8/8 15:11
*/
@Data
public class ChartDataSearchDTO {
@ApiModelProperty(notes = "页面编码")
private String pageCode;
@ApiModelProperty(notes = "图表编码")
private String chartCode;
@ApiModelProperty(notes = "内部图表编码")
private String innerChartCode;
@ApiModelProperty(notes = "类型")
private String type;
@ApiModelProperty(notes = "当前页")
private Integer current;
@ApiModelProperty(notes = "每页记录数")
private Integer size;
@ApiModelProperty(notes = "树父节点id")
private String treeParentId;
@ApiModelProperty(notes = "图表配置,仅在根据配置临时获取数据时使用")
private Chart chart;
@ApiModelProperty(notes = "过滤条件")
private List<Filter> filterList;
}

View File

@@ -0,0 +1,211 @@
package com.gccloud.dataroom.core.module.chart.service;
import com.gccloud.dataroom.core.constant.PageDesignConstant;
import com.gccloud.dataroom.core.module.chart.bean.Chart;
import com.gccloud.dataroom.core.module.chart.bean.Filter;
import com.gccloud.dataroom.core.module.chart.components.datasource.BaseChartDataSource;
import com.gccloud.dataroom.core.module.chart.components.datasource.DataSetDataSource;
import com.gccloud.dataroom.core.module.chart.dto.ChartDataSearchDTO;
import com.gccloud.dataroom.core.module.chart.vo.ChartDataVO;
import com.gccloud.common.exception.GlobalException;
import com.gccloud.common.utils.JSON;
import com.gccloud.common.vo.PageVO;
import com.gccloud.dataset.constant.DatasetConstant;
import com.gccloud.dataset.dto.DatasetParamDTO;
import com.gccloud.dataset.entity.DatasetEntity;
import com.gccloud.dataset.entity.config.JsonDataSetConfig;
import com.gccloud.dataset.params.ParamsClient;
import com.gccloud.dataset.service.IBaseDataSetService;
import com.gccloud.dataset.service.factory.DataSetServiceFactory;
import com.gccloud.dataset.vo.DatasetInfoVO;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.json.JSONArray;
import org.json.JSONObject;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.*;
/**
* @author liuchengbiao
* @version 1.0
* @date 2022/8/8 15:11
*/
@Data
@Slf4j
@Service("dataRoomBaseChartDataService")
public class BaseChartDataService {
@Resource
private DataSetServiceFactory dataSetServiceFactory;
@Resource
private ParamsClient paramsClient;
public ChartDataVO dataQuery(Chart chart, ChartDataSearchDTO searchDTO) {
BaseChartDataSource dataSource = chart.getDataSource();
if (dataSource == null) {
return null;
}
if (!dataSource.getClass().equals(DataSetDataSource.class)) {
return null;
}
DataSetDataSource dataSetDataSource = (DataSetDataSource) dataSource;
if (StringUtils.isBlank(dataSetDataSource.getBusinessKey())) {
return null;
}
IBaseDataSetService dataSetService = dataSetServiceFactory.buildById(dataSetDataSource.getBusinessKey());
DatasetEntity datasetEntity = dataSetService.getByIdFromCache(dataSetDataSource.getBusinessKey());
if (datasetEntity == null) {
return null;
}
if (DatasetConstant.DataSetType.JSON.equals(datasetEntity.getDatasetType())) {
return jsonDataQuery(datasetEntity, dataSetDataSource, dataSetService);
}
return dataSetDataQuery(dataSetDataSource, chart, searchDTO, dataSetService);
}
/**
* json类型的数据集数据处理
* @param dataSet
* @param dataSetDataSource
* @return
*/
private ChartDataVO jsonDataQuery(DatasetEntity dataSet, DataSetDataSource dataSetDataSource, IBaseDataSetService dataSetService) {
ChartDataVO dataDTO = new ChartDataVO();
JsonDataSetConfig config = (JsonDataSetConfig) dataSet.getConfig();
Object jsonContent = dataSetService.execute(dataSet.getId(), null);
List<Map<String, Object>> data = Lists.newArrayList();
if (jsonContent instanceof JSONArray) {
jsonContent = ((JSONArray) jsonContent).toList();
}
if (jsonContent instanceof ArrayList) {
ArrayList list = (ArrayList) jsonContent;
for (Object o : list) {
if (o instanceof HashMap) {
data.add((HashMap<String, Object>) o);
}
}
}
if (jsonContent instanceof HashMap) {
HashMap map = (HashMap) jsonContent;
data.add(map);
}
if (jsonContent instanceof JSONObject) {
JSONObject jsonObject = (JSONObject) jsonContent;
data.add(jsonObject.toMap());
}
HashMap<String, ChartDataVO.ColumnData> columnData = Maps.newHashMap();
Map<String, Object> fieldDesc = config.getFieldDesc();
fieldDesc.forEach((k, v) -> {
ChartDataVO.ColumnData column = new ChartDataVO.ColumnData();
column.setOriginalColumn(k);
column.setAlias(k);
column.setRemark(v.toString());
columnData.put(k, column);
});
dataDTO.setData(data);
dataDTO.setSuccess(true);
dataDTO.setColumnData(columnData);
return dataDTO;
}
/**
* 根据数据集数据源查询数据
* @param dataSource
* @return
*/
private ChartDataVO dataSetDataQuery(DataSetDataSource dataSource, Chart chart, ChartDataSearchDTO searchDTO, IBaseDataSetService dataSetService) {
ChartDataVO dataDTO = new ChartDataVO();
List<DatasetParamDTO> params = Lists.newArrayList();
if (StringUtils.isBlank(dataSource.getBusinessKey())) {
throw new GlobalException("图表未配置数据集");
}
DatasetInfoVO dataSetInfoVo = dataSetService.getInfoById(dataSource.getBusinessKey());
HashMap<String, ChartDataVO.ColumnData> columnData = Maps.newHashMap();
List<Map<String, Object>> fieldJson = dataSetInfoVo.getFields();
for (Map<String, Object> field : fieldJson) {
ChartDataVO.ColumnData column = new ChartDataVO.ColumnData();
column.setOriginalColumn(field.get(DatasetInfoVO.FIELD_NAME).toString());
column.setAlias(field.get(DatasetInfoVO.FIELD_NAME).toString());
column.setRemark(field.get(DatasetInfoVO.FIELD_DESC).toString());
String sourceTable = field.get(DatasetInfoVO.FIELD_SOURCE) == null ? "" : field.get(DatasetInfoVO.FIELD_SOURCE).toString();
column.setTableName(sourceTable);
String type = field.get(DatasetInfoVO.FIELD_TYPE) == null ? "" : field.get(DatasetInfoVO.FIELD_TYPE).toString();
column.setType(type);
columnData.put(field.get(DatasetInfoVO.FIELD_NAME).toString(), column);
}
if (chart.getType().equals(PageDesignConstant.BigScreen.Type.TABLES)) {
// 表格的话要按照dimensionFieldList对columnData进行排序
List<String> dimensionFieldList = dataSource.getDimensionFieldList();
LinkedHashMap<String, ChartDataVO.ColumnData> newColumnData = Maps.newLinkedHashMap();
dimensionFieldList.forEach(dimensionField -> newColumnData.put(dimensionField, columnData.get(dimensionField)));
// 剩下的字段按照原来的顺序放到后面
columnData.forEach((key, value) -> {
if (!newColumnData.containsKey(key)) {
newColumnData.put(key, value);
}
});
}
if (dataSource.getParams() != null && dataSource.getParams().size() > 0) {
String setString = JSON.toJSONString(dataSetInfoVo.getParams());
List<DatasetParamDTO> setParams = JSON.parseArray(setString, DatasetParamDTO.class);
for (DatasetParamDTO param : setParams) {
if (!dataSource.getParams().containsKey(param.getName())) {
continue;
}
String value = dataSource.getParams().get(param.getName()).toString();
// 如果传入了过滤条件,优先使用过滤条件
if (searchDTO.getFilterList() != null && searchDTO.getFilterList().size() > 0) {
for (Filter filter : searchDTO.getFilterList()) {
if (filter.getColumn() == null) {
continue;
}
if (filter.getColumn().equals(param.getName())) {
if (filter.getValue() == null || filter.getValue().size() == 0) {
continue;
}
value = filter.getValue().get(0);
break;
}
}
}
param.setValue(value);
param.setStatus(1);
params.add(param);
}
} else {
// 组件配置的数据集参数为空,则使用数据集默认的参数
List<DatasetParamDTO> setParams = dataSetInfoVo.getParams();
if (setParams == null) {
setParams = Lists.newArrayList();
}
String setString = JSON.toJSONString(setParams);
params = JSON.parseArray(setString, DatasetParamDTO.class);
}
dataDTO.setColumnData(columnData);
Object data;
log.info("查询数据集数据,参数:{}", JSON.toJSONString(params));
if (dataSource.getServerPagination() != null && dataSource.getServerPagination() && searchDTO.getSize() != null && searchDTO.getCurrent() != null) {
PageVO<Object> pageResult = dataSetService.execute(dataSource.getBusinessKey(), params, searchDTO.getCurrent(), searchDTO.getSize());
data = pageResult.getList();
dataDTO.setTotalCount((int)pageResult.getTotalCount());
dataDTO.setTotalPage((int)pageResult.getTotalPage());
} else {
data = dataSetService.execute(dataSource.getBusinessKey(), params);
}
boolean backendExecutionNeeded = dataSetService.checkBackendExecutionNeeded(dataSource.getBusinessKey());
dataDTO.setExecutionByFrontend(!backendExecutionNeeded);
dataDTO.setData(data);
dataDTO.setSuccess(true);
return dataDTO;
}
}

View File

@@ -0,0 +1,58 @@
package com.gccloud.dataroom.core.module.chart.service;
import com.gccloud.dataroom.core.constant.PageDesignConstant;
import com.gccloud.dataroom.core.module.chart.vo.ChartDataVO;
import com.gccloud.common.utils.JSON;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.stereotype.Service;
import java.io.IOException;
import java.io.InputStream;
/**
* @author hongyang
* @version 1.0
* @date 2022/8/25 17:09
*/
@Slf4j
@Service("dataRoomChartMockDataService")
public class ChartMockData {
public static ChartDataVO getMockData(String type) {
ChartDataVO chartDataDTO;
String fileName = "chart/mock/" + type + ".json";
if (PageDesignConstant.BigScreen.Type.SCREEN_SCROLL_BOARD.equals(type)) {
fileName = "chart/mock/tables.json";
}
if (PageDesignConstant.BigScreen.Type.SCREEN_SCROLL_RANKING.equals(type)) {
fileName = "chart/mock/ranking.json";
}
String json = "";
ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
try {
Resource[] resources = resolver.getResources(fileName);
Resource resource = resources[0];
if (!resource.exists()) {
return new ChartDataVO();
}
//获得文件流因为在jar文件中不能直接通过文件资源路径拿到文件但是可以在jar包中拿到文件流
InputStream stream = resource.getInputStream();
StringBuilder buffer = new StringBuilder();
byte[] bytes = new byte[1024];
for (int n; (n = stream.read(bytes)) != -1; ) {
buffer.append(new String(bytes, 0, n));
}
json = buffer.toString();
} catch (IOException e) {
log.error(ExceptionUtils.getStackTrace(e));
return new ChartDataVO();
}
chartDataDTO = JSON.parseObject(json, ChartDataVO.class);
return chartDataDTO;
}
}

View File

@@ -0,0 +1,74 @@
package com.gccloud.dataroom.core.module.chart.vo;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.Map;
/**
* 图表响应数据
* @author liuchengbiao
* @version 1.0
* @date 2022/8/8 15:11
*/
@Data
public class ChartDataVO {
/**
* 是否成功
*/
private Boolean success = Boolean.FALSE;
/**
* 是否前端执行
*/
private Boolean executionByFrontend = Boolean.FALSE;
/**
* 返回的数据
*/
@ApiModelProperty(notes = "返回的数据")
private Object data;
/**
* 总记录数在table类型的图表开启分页时使用
*/
@ApiModelProperty(notes = "总记录数")
private Integer totalCount = 0;
/**
* 总页数在table类型的图表开启分页时使用
*/
@ApiModelProperty(notes = "总页数")
private Integer totalPage = 0;
@ApiModelProperty(notes = "执行的SQL")
private String sql;
@ApiModelProperty(notes = "列属性")
private Map<String, ColumnData> columnData;
@Data
public static class ColumnData {
@ApiModelProperty(notes = "字段类型")
private String type;
@ApiModelProperty(notes = "表名")
private String tableName;
@ApiModelProperty(notes = "字段名")
private String originalColumn;
@ApiModelProperty(notes = "聚合函数")
private String aggregate;
@ApiModelProperty(notes = "别名")
private String alias;
@ApiModelProperty(notes = "备注")
private String remark;
}
}

View File

@@ -0,0 +1,96 @@
package com.gccloud.dataroom.core.module.file.controller;
import com.gccloud.common.permission.ApiPermission;
import com.gccloud.dataroom.core.module.file.dto.FileSearchDTO;
import com.gccloud.dataroom.core.module.file.entity.DataRoomFileEntity;
import com.gccloud.dataroom.core.module.file.service.IDataRoomFileService;
import com.gccloud.dataroom.core.module.file.service.IDataRoomOssService;
import com.gccloud.dataroom.core.module.file.vo.DataRoomFileVO;
import com.gccloud.common.controller.SuperController;
import com.gccloud.common.utils.BeanConvertUtils;
import com.gccloud.common.vo.PageVO;
import com.gccloud.common.vo.R;
import com.gccloud.dataroom.core.permission.Permission;
import com.swiot.common.annotation.Anonymous;
import io.swagger.annotations.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
/**
* 文件管理
*/
@Slf4j
@RestController
@Anonymous
@RequestMapping("/bigScreen/file")
@Api(tags = "文件管理")
@ApiSort(value = 100)
public class DataRoomFileController extends SuperController {
@Resource
private IDataRoomOssService sysOssService;
@Resource
private IDataRoomFileService fileService;
@ApiPermission(permissions = {Permission.File.VIEW})
@GetMapping(value = {"", "/"})
@ApiOperation(value = "列表", position = 10, notes = "分页查询文件", produces = MediaType.APPLICATION_JSON_VALUE)
@ApiImplicitParams({
@ApiImplicitParam(name = "current", value = "页码", paramType = "query", required = true, dataType = "int"),
@ApiImplicitParam(name = "size", value = "每页条数", paramType = "query", required = true, dataType = "int"),
@ApiImplicitParam(name = "searchKey", value = "查询条件", paramType = "query", dataType = "string")
})
public R<PageVO<DataRoomFileVO>> getPage(@ApiParam(name = "查询", value = "传入查询的业务条件", required = true) FileSearchDTO searchDTO) {
PageVO<DataRoomFileEntity> page = fileService.getPage(searchDTO);
PageVO<DataRoomFileVO> pageVO = BeanConvertUtils.convertPage(page, DataRoomFileVO.class);
return R.success(pageVO);
}
@ApiPermission(permissions = {Permission.File.UPLOAD})
@PostMapping("/upload")
@ApiOperation(value = "上传", notes = "上传", produces = MediaType.APPLICATION_JSON_VALUE)
public R<DataRoomFileEntity> upload(@RequestParam("file") MultipartFile file, @RequestParam(value = "module", required = false) String module, HttpServletResponse response, HttpServletRequest request) {
DataRoomFileEntity entity = new DataRoomFileEntity();
// 不同业务自己控制
if (StringUtils.isBlank(module)) {
module = "other";
}
entity.setModule(module);
sysOssService.upload(file, entity, response, request);
fileService.save(entity);
return R.success(entity);
}
@ApiPermission(permissions = {Permission.File.DOWNLOAD})
@PostMapping("/download/{id}")
@ApiOperation(value = "下载", notes = "下载资源", produces = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
public void download(@PathVariable("id") String id, HttpServletResponse response, HttpServletRequest request) {
sysOssService.download(id, response, request);
}
@ApiPermission(permissions = {Permission.File.VIEW})
@GetMapping("/getAllFileSuffix")
@ApiOperation(value = "获取所有文件后缀名", notes = "获取所有文件后缀名", produces = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
public R<List<String>> getAllFileSuffix() {
List<String> extensions = fileService.getAllExtension();
// 移除空后缀
extensions.remove("");
return R.success(extensions);
}
@ApiPermission(permissions = {Permission.File.DELETE})
@PostMapping("/delete/{id}")
@ApiOperation(value = "删除", notes = "删除", produces = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
public R<Boolean> delete(@PathVariable("id") String id) {
sysOssService.delete(id);
return R.success(true);
}
}

View File

@@ -0,0 +1,29 @@
package com.gccloud.dataroom.core.module.file.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.gccloud.dataroom.core.module.file.entity.DataRoomFileEntity;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* 文件
*/
@Mapper
public interface DataRoomFileDao extends BaseMapper<DataRoomFileEntity> {
/**
* 更新文件下载次数
*
* @param addCount
*/
void updateDownloadCount(@Param("addCount") Integer addCount, @Param("id") String fileId);
/**
* 获取所有文件后缀(去重)
* @return
*/
List<String> getAllExtension();
}

View File

@@ -0,0 +1,28 @@
package com.gccloud.dataroom.core.module.file.dto;
import com.gccloud.common.dto.SearchDTO;
import lombok.Data;
import java.util.List;
@Data
public class FileSearchDTO extends SearchDTO {
/**
* 所属模块
*/
private String module;
/**
* 文件后缀
*/
private String extension;
/**
* 文件后缀列表,批量过滤
*/
private List<String> extensionList;
}

View File

@@ -0,0 +1,55 @@
package com.gccloud.dataroom.core.module.file.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import com.gccloud.common.entity.SuperEntity;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.ToString;
import lombok.experimental.Accessors;
import java.io.Serializable;
/**
* 文件
*/
@Data
@Accessors(chain = true)
@TableName("big_screen_file")
@ApiModel
@ToString(callSuper = true)
public class DataRoomFileEntity extends SuperEntity implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty(notes = "业务所属模块,非必须,提供给业务作为分类标识使用")
private String module;
@ApiModelProperty(notes = "原文件名")
private String originalName;
@ApiModelProperty(notes = "新文件名")
private String newName;
@ApiModelProperty(notes = "后缀名(如: txt、png、doc、java等)")
private String extension;
@ApiModelProperty(notes = "存储路径")
private String path;
@ApiModelProperty(notes = "访问地址")
private String url;
@ApiModelProperty(notes = "文件大小")
private Long size;
@ApiModelProperty(notes = "下载次数")
private Integer downloadCount = 0;
@ApiModelProperty(notes = "上传用户")
private String userName;
@ApiModelProperty(notes = "桶名, 用于存储在云存储中的桶名")
private String bucket;
}

View File

@@ -0,0 +1,41 @@
package com.gccloud.dataroom.core.module.file.service;
import com.gccloud.dataroom.core.module.file.dto.FileSearchDTO;
import com.gccloud.dataroom.core.module.file.entity.DataRoomFileEntity;
import com.gccloud.common.service.ISuperService;
import com.gccloud.common.vo.PageVO;
import java.util.List;
/**
* 文件管理
*
* @author liuchengbiao
*/
public interface IDataRoomFileService extends ISuperService<DataRoomFileEntity> {
/**
* 分页查询
*
* @param searchDTO
* @return
*/
PageVO<DataRoomFileEntity> getPage(FileSearchDTO searchDTO);
/**
* 更新下载次数
*
* @param addCount
* @param fileId
*/
void updateDownloadCount(Integer addCount, String fileId);
/**
* 获取所有文件后缀(去重)
*
* @return
*/
List<String> getAllExtension();
}

View File

@@ -0,0 +1,63 @@
package com.gccloud.dataroom.core.module.file.service;
import com.gccloud.dataroom.core.module.file.entity.DataRoomFileEntity;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
/**
* 文件管理
*
* @author liuchengbiao
*/
public interface IDataRoomOssService {
/**
* 上传文件,文件名重新生成
*
* @param file
* @param entity
* @param response
* @param request
* @return
*/
DataRoomFileEntity upload(MultipartFile file, DataRoomFileEntity entity, HttpServletResponse response, HttpServletRequest request);
/**
* 上传文件, 保留传入的文件名
* @param inputStream
* @param fileName
* @param size
* @param entity
* @return
*/
DataRoomFileEntity upload(InputStream inputStream, String fileName, long size, DataRoomFileEntity entity);
/**
* 下载文件
*
* @param fileId
* @param response
* @param request
*/
void download(String fileId, HttpServletResponse response, HttpServletRequest request);
/**
* 删除文件
* @param fileId
*/
void delete(String fileId);
/**
* 复制文件,目前用于封面复制
* @param sourcePath
* @param targetPath
* @return 返回复制后的文件路径
*/
default String copy(String sourcePath, String targetPath) {return "";}
}

View File

@@ -0,0 +1,54 @@
package com.gccloud.dataroom.core.module.file.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gccloud.dataroom.core.module.file.dao.DataRoomFileDao;
import com.gccloud.dataroom.core.module.file.dto.FileSearchDTO;
import com.gccloud.dataroom.core.module.file.entity.DataRoomFileEntity;
import com.gccloud.dataroom.core.module.file.service.IDataRoomFileService;
import com.gccloud.common.exception.GlobalException;
import com.gccloud.common.utils.QueryWrapperUtils;
import com.gccloud.common.vo.PageVO;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Map;
/**
* 文件管理
*/
@Service
@Slf4j
@ConditionalOnProperty(prefix = "gc.starter.dataroom.component", name = "IDataRoomFileService", havingValue = "DataRoomFileServiceImpl", matchIfMissing = true)
public class DataRoomFileServiceImpl extends ServiceImpl<DataRoomFileDao, DataRoomFileEntity> implements IDataRoomFileService {
@Override
public PageVO<DataRoomFileEntity> getPage(FileSearchDTO searchDTO) {
LambdaQueryWrapper<DataRoomFileEntity> queryWrapper = QueryWrapperUtils.wrapperLike(new LambdaQueryWrapper(), searchDTO.getSearchKey(), DataRoomFileEntity::getOriginalName);
queryWrapper.eq(StringUtils.isNotBlank(searchDTO.getModule()), DataRoomFileEntity::getModule, searchDTO.getModule());
queryWrapper.eq(StringUtils.isNotBlank(searchDTO.getExtension()), DataRoomFileEntity::getExtension, searchDTO.getExtension());
if (searchDTO.getExtensionList() != null && searchDTO.getExtensionList().size() > 0) {
queryWrapper.in(DataRoomFileEntity::getExtension, searchDTO.getExtensionList());
}
queryWrapper.orderByDesc(DataRoomFileEntity::getCreateDate);
return page(searchDTO, queryWrapper);
}
@Override
public void updateDownloadCount(Integer addCount, String fileId) {
if (addCount <= 0) {
throw new GlobalException("下载次数不允许为负数或0");
}
baseMapper.updateDownloadCount(addCount, fileId);
}
@Override
public List<String> getAllExtension() {
// 去重获取所有文件后缀名
return baseMapper.getAllExtension();
}
}

View File

@@ -0,0 +1,154 @@
package com.gccloud.dataroom.core.module.file.service.impl;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.gccloud.common.exception.GlobalException;
import com.gccloud.dataroom.core.config.DataRoomConfig;
import com.gccloud.dataroom.core.config.bean.FileConfig;
import com.gccloud.dataroom.core.module.file.entity.DataRoomFileEntity;
import com.gccloud.dataroom.core.module.file.service.IDataRoomFileService;
import com.gccloud.dataroom.core.module.file.service.IDataRoomOssService;
import com.gccloud.dataroom.core.utils.FtpClientUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
/**
* ftp文件管理实现类
* 将文件上传至ftp服务器需要配置ftp服务器相关信息
* 由于该方案无法直接通过url访问文件所以需要手动在对应的服务器上部署nginx等服务将ftp服务器上的文件开放访问然后将该服务地址配置到gc.starter.file.urlPrefix中
* @author hongyang
* @version 1.0
* @date 2023/10/17 15:12
*/
@Service
@Slf4j
@ConditionalOnProperty(prefix = "gc.starter.file", name = "type", havingValue = "ftp")
public class DataRoomFtpFileServiceImpl implements IDataRoomOssService {
@Resource
private FtpClientUtil ftpUtil;
@Resource
private DataRoomConfig bigScreenConfig;
@Resource
private IDataRoomFileService sysFileService;
@Override
public DataRoomFileEntity upload(MultipartFile file, DataRoomFileEntity fileEntity, HttpServletResponse response, HttpServletRequest request) {
String originalFilename = file.getOriginalFilename();
// 提取文件后缀名
String extension = FilenameUtils.getExtension(originalFilename);
FileConfig fileConfig = bigScreenConfig.getFile();
if (!fileConfig.getAllowedFileExtensionName().contains("*") && !fileConfig.getAllowedFileExtensionName().contains(extension)) {
log.error("不支持 {} 文件类型",extension);
throw new GlobalException("不支持的文件类型");
}
// 重命名
String id = IdWorker.getIdStr();
String newFileName = id + "." + extension;
long size = file.getSize();
InputStream inputStream;
try {
inputStream = file.getInputStream();
} catch (IOException e) {
log.error("上传文件到FTP服务失败获取文件流失败");
log.error(ExceptionUtils.getStackTrace(e));
throw new GlobalException("获取文件流失败");
}
return this.upload(inputStream, newFileName, size, fileEntity);
}
@Override
public DataRoomFileEntity upload(InputStream inputStream, String fileName, long size, DataRoomFileEntity fileEntity) {
// 提取文件后缀名
String extension = FilenameUtils.getExtension(fileName);
// 上传的目标路径
String basePath = bigScreenConfig.getFile().getBasePath();
// 上传文件到ftp
boolean upload = ftpUtil.upload(basePath, fileName, inputStream);
if (!upload) {
log.error("上传文件到ftp失败");
throw new GlobalException("上传文件到ftp失败");
}
fileEntity.setOriginalName(fileName);
fileEntity.setNewName(fileName);
fileEntity.setPath(basePath);
fileEntity.setSize(size);
fileEntity.setExtension(extension);
fileEntity.setUrl("/" + fileName);
return fileEntity;
}
@Override
public void download(String fileId, HttpServletResponse response, HttpServletRequest request) {
DataRoomFileEntity fileEntity = sysFileService.getById(fileId);
if (fileEntity == null) {
response.setStatus(HttpStatus.NOT_FOUND.value());
log.error("下载的文件不存在");
return;
}
response.setContentType("application/x-msdownload");
response.setContentType("multipart/form-data");
// 不设置前端无法从header获取文件名
response.setHeader("Access-Control-Expose-Headers", "filename");
try {
response.setHeader("filename", URLEncoder.encode(fileEntity.getOriginalName(), "UTF-8"));
// 解决下载的文件不携带后缀
response.setHeader("Content-Disposition", "attachment;fileName="+URLEncoder.encode(fileEntity.getOriginalName(),"UTF-8"));
} catch (UnsupportedEncodingException e) {
log.error(ExceptionUtils.getStackTrace(e));
}
OutputStream outputStream;
try {
outputStream = response.getOutputStream();
} catch (IOException e) {
log.error(ExceptionUtils.getStackTrace(e));
response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
return;
}
boolean download = ftpUtil.download(fileEntity.getPath(), fileEntity.getNewName(), outputStream);
if (!download) {
log.error("下载文件失败");
response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
}
try {
outputStream.close();
} catch (IOException e) {
log.error(ExceptionUtils.getStackTrace(e));
}
sysFileService.updateDownloadCount(1, fileId);
}
@Override
public void delete(String fileId) {
DataRoomFileEntity fileEntity = sysFileService.getById(fileId);
if (fileEntity == null) {
log.error("删除的文件不存在");
return;
}
sysFileService.removeById(fileId);
// 删除ftp上的文件
ftpUtil.delete(fileEntity.getPath(), fileEntity.getNewName());
}
@Override
public String copy(String sourcePath, String targetPath) {
String basePath = bigScreenConfig.getFile().getBasePath() + File.separator;
boolean copySuccess = ftpUtil.copy(basePath + sourcePath, basePath + targetPath);
if (!copySuccess) {
return "";
}
return targetPath;
}
}

View File

@@ -0,0 +1,192 @@
package com.gccloud.dataroom.core.module.file.service.impl;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.gccloud.common.exception.GlobalException;
import com.gccloud.dataroom.core.config.DataRoomConfig;
import com.gccloud.dataroom.core.config.bean.FileConfig;
import com.gccloud.dataroom.core.module.file.entity.DataRoomFileEntity;
import com.gccloud.dataroom.core.module.file.service.IDataRoomFileService;
import com.gccloud.dataroom.core.module.file.service.IDataRoomOssService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
/**
* 文件管理
*/
@Slf4j
@Service
@ConditionalOnProperty(prefix = "gc.starter.file", name = "type", havingValue = "local", matchIfMissing = true)
public class DataRoomLocalFileServiceImpl implements IDataRoomOssService {
@Resource
private DataRoomConfig bigScreenConfig;
@Resource
private IDataRoomFileService sysFileService;
@Override
public DataRoomFileEntity upload(MultipartFile file, DataRoomFileEntity fileEntity, HttpServletResponse response, HttpServletRequest request) {
String originalFilename = file.getOriginalFilename();
// 提取文件后缀名
String extension = FilenameUtils.getExtension(originalFilename);
FileConfig fileConfig = bigScreenConfig.getFile();
if (!fileConfig.getAllowedFileExtensionName().contains("*") && !fileConfig.getAllowedFileExtensionName().contains(extension)) {
log.error("不支持 {} 文件类型",extension);
throw new GlobalException("不支持的文件类型");
}
// 重命名
String id = IdWorker.getIdStr();
String newFileName = id + "." + extension;
// 上传文件保存到的路径,根据实际情况修改,也可能是从配置文件获取到的文件存储路径
String basePath = bigScreenConfig.getFile().getBasePath();
String destPath = basePath + File.separator + newFileName;
long size = file.getSize();
try {
File dest = new File(destPath);
file.transferTo(dest);
} catch (Exception e) {
log.error(ExceptionUtils.getStackTrace(e));
log.error(String.format("文件 %s 存储到 %s 失败", originalFilename, destPath));
throw new GlobalException("文件上传失败");
}
fileEntity.setOriginalName(originalFilename);
fileEntity.setNewName(newFileName);
fileEntity.setPath(basePath);
fileEntity.setSize(size);
fileEntity.setExtension(extension);
fileEntity.setUrl("/" + newFileName);
return fileEntity;
}
@Override
public DataRoomFileEntity upload(InputStream inputStream, String fileName, long size, DataRoomFileEntity fileEntity) {
// 上传文件保存到的路径, 从配置文件获取
String basePath = bigScreenConfig.getFile().getBasePath();
// 提取文件后缀名
String extension = FilenameUtils.getExtension(fileName);
String destPath = basePath + File.separator + fileName;
try {
File dest = new File(destPath);
// 检查文件所在的目录是否存在,不存在则创建
String parent = dest.getParent();
File parentFile = new File(parent);
if (!parentFile.exists()) {
FileUtils.forceMkdir(parentFile);
}
FileOutputStream outputStream = new FileOutputStream(dest);
byte[] buffer = new byte[1024];
int length;
while ((length = inputStream.read(buffer)) > 0) {
outputStream.write(buffer, 0, length);
}
outputStream.close();
inputStream.close();
} catch (Exception e) {
log.error(ExceptionUtils.getStackTrace(e));
log.error(String.format("文件 %s 存储到 %s 失败", fileName, destPath));
throw new GlobalException("文件上传失败");
}
fileEntity.setOriginalName(fileName);
fileEntity.setNewName(fileName);
fileEntity.setPath(basePath);
fileEntity.setSize(size);
fileEntity.setExtension(extension);
fileEntity.setUrl("/" + fileName);
return fileEntity;
}
@Override
public void download(String fileId, HttpServletResponse response, HttpServletRequest request) {
DataRoomFileEntity fileEntity = sysFileService.getById(fileId);
if (fileEntity == null) {
response.setStatus(HttpStatus.NOT_FOUND.value());
log.error("下载的文件不存在");
return;
}
response.setContentType("application/x-msdownload");
response.setContentType("multipart/form-data");
// 不设置前端无法从header获取文件名
response.setHeader("Access-Control-Expose-Headers", "filename");
try {
response.setHeader("filename", URLEncoder.encode(fileEntity.getOriginalName(), "UTF-8"));
// 解决下载的文件不携带后缀
response.setHeader("Content-Disposition", "attachment;fileName="+URLEncoder.encode(fileEntity.getOriginalName(),"UTF-8"));
} catch (UnsupportedEncodingException e) {
log.error(ExceptionUtils.getStackTrace(e));
}
String filePath = fileEntity.getPath() + File.separator + fileEntity.getNewName();
File file = new File(filePath);
if (!file.exists()) {
response.setStatus(HttpStatus.NOT_FOUND.value());
log.error("下载的文件不存在");
return;
}
try {
InputStream is = new FileInputStream(file);
IOUtils.copy(is, response.getOutputStream());
is.close();
response.getOutputStream().close();
} catch (Exception e) {
response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
log.error(String.format("下载文件%s失败", fileEntity.getOriginalName()));
} finally {
sysFileService.updateDownloadCount(1, fileId);
}
}
@Override
public void delete(String fileId) {
DataRoomFileEntity fileEntity = sysFileService.getById(fileId);
sysFileService.removeById(fileId);
if (fileEntity == null) {
log.error("删除的文件不存在");
return;
}
String filePath = fileEntity.getPath() + File.separator + fileEntity.getNewName();
File file = new File(filePath);
if (!file.exists()) {
log.error("删除的文件不存在");
return;
}
file.delete();
}
@Override
public String copy(String sourcePath, String targetPath) {
String basePath = bigScreenConfig.getFile().getBasePath() + File.separator;
File sourceFile = new File(basePath + sourcePath);
File targetFile = new File(basePath + targetPath);
// 检查源文件是否存在
if (!sourceFile.exists()) {
log.error("复制源文件不存在:{}", sourcePath);
return "";
}
// 检查源文件是否是文件夹
if (sourceFile.isDirectory()) {
log.error("源文件为文件夹:{},无法复制", sourcePath);
return "";
}
try {
FileUtils.copyFile(sourceFile, targetFile);
} catch (IOException e) {
log.error(String.format("文件 %s 复制到 %s 失败", sourcePath, targetPath));
log.error(ExceptionUtils.getStackTrace(e));
return "";
}
return targetPath;
}
}

View File

@@ -0,0 +1,216 @@
package com.gccloud.dataroom.core.module.file.service.impl;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.gccloud.common.exception.GlobalException;
import com.gccloud.dataroom.core.config.DataRoomConfig;
import com.gccloud.dataroom.core.config.bean.FileConfig;
import com.gccloud.dataroom.core.config.bean.DataRoomMinioConfig;
import com.gccloud.dataroom.core.module.file.entity.DataRoomFileEntity;
import com.gccloud.dataroom.core.module.file.service.IDataRoomFileService;
import com.gccloud.dataroom.core.module.file.service.IDataRoomOssService;
import com.gccloud.dataroom.core.utils.MinioFileInterface;
import com.gccloud.dataroom.core.utils.PathUtils;
import io.minio.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
/**
* Minio文件管理
*
* @author Acechengui
*/
@Slf4j
@Service
@ConditionalOnProperty(prefix = "gc.starter.file", name = "type", havingValue = "minio")
public class DataRoomMinioServiceImpl implements IDataRoomOssService {
@Resource
private MinioClient minioclient;
@Resource
private DataRoomConfig bigScreenConfig;
@Resource
private IDataRoomFileService sysFileService;
@Resource
private MinioFileInterface minioFileInterface;
/**
* 上传文件
*/
@Override
public DataRoomFileEntity upload(MultipartFile file, DataRoomFileEntity fileEntity, HttpServletResponse response, HttpServletRequest request) {
String originalFilename = file.getOriginalFilename();
// 提取文件后缀名
String extension = FilenameUtils.getExtension(originalFilename);
FileConfig fileConfig = bigScreenConfig.getFile();
if (!fileConfig.getAllowedFileExtensionName().contains("*") && !fileConfig.getAllowedFileExtensionName().contains(extension)) {
log.error("不支持 {} 文件类型", extension);
throw new GlobalException("不支持的文件类型");
}
String module = request.getParameter("module");
// 不同业务自己控制
if (StringUtils.isBlank(module)) {
fileEntity.setModule("other");
}
// 重命名
String newFileName = IdWorker.getIdStr() + "." + extension;
// 组装路径:获取当前日期并格式化为"yyyy/mm/dd"格式的字符串
String basePath = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy/MM/dd"));
String filePath = basePath + "/" + newFileName;
DataRoomMinioConfig minioConfig = bigScreenConfig.getFile().getMinio();
try (InputStream inputStream = file.getInputStream()) {
PutObjectArgs args = PutObjectArgs.builder()
.bucket(minioConfig.getBucketName())
.object(filePath)
.stream(inputStream, file.getSize(), -1)
.contentType(file.getContentType())
.build();
minioclient.putObject(args);
} catch (Exception e) {
log.error("上传文件到Minio失败");
log.error(ExceptionUtils.getStackTrace(e));
throw new GlobalException("上传文件失败");
}
// 现在url存储文件的相对路径对于minio来说就是bucketName/文件名
String url = "/" + minioConfig.getBucketName() + "/" + filePath;
fileEntity.setOriginalName(originalFilename);
fileEntity.setNewName(newFileName);
fileEntity.setPath(filePath);
fileEntity.setSize(file.getSize());
fileEntity.setExtension(extension);
fileEntity.setUrl(url);
fileEntity.setModule(module);
fileEntity.setBucket(minioConfig.getBucketName());
return fileEntity;
}
@Override
public DataRoomFileEntity upload(InputStream inputStream, String fileName, long size, DataRoomFileEntity entity) {
fileName = PathUtils.normalizePath(fileName);
String extension = FilenameUtils.getExtension(fileName);
DataRoomMinioConfig minioConfig = bigScreenConfig.getFile().getMinio();
long fileSize = size == 0 ? -1 : size;
// 使用minio的最小分片大小
long partSize = fileSize == -1 ? ObjectWriteArgs.MIN_MULTIPART_SIZE : -1;
try {
PutObjectArgs args = PutObjectArgs.builder()
.bucket(minioConfig.getBucketName())
.object(fileName)
.stream(inputStream, fileSize, partSize)
.contentType("image/png")
.build();
minioclient.putObject(args);
} catch (Exception e) {
log.error("上传文件到Minio失败");
log.error(ExceptionUtils.getStackTrace(e));
throw new GlobalException("上传文件失败");
} finally {
IOUtils.closeQuietly(inputStream);
}
// 现在url存储文件的相对路径对于minio来说就是bucketName/文件名
String url = "/" + minioConfig.getBucketName() + "/" + fileName;
entity.setOriginalName(fileName);
entity.setNewName(fileName);
entity.setPath(fileName);
entity.setSize(fileSize);
entity.setExtension(extension);
entity.setUrl(url);
entity.setBucket(minioConfig.getBucketName());
return entity;
}
/**
* 下载文件
*/
@Override
public void download(String fileId, HttpServletResponse response, HttpServletRequest request) {
DataRoomFileEntity fileEntity = sysFileService.getById(fileId);
if (fileEntity == null) {
response.setStatus(HttpStatus.NOT_FOUND.value());
log.error("下载的文件不存在");
return;
}
response.setContentType("application/x-msdownload");
response.setContentType("multipart/form-data");
// 不设置前端无法从header获取文件名
response.setHeader("Access-Control-Expose-Headers", "filename");
try {
response.setHeader("filename", URLEncoder.encode(fileEntity.getOriginalName(), "UTF-8"));
// 解决下载的文件不携带后缀
response.setHeader("Content-Disposition", "attachment;fileName=" + URLEncoder.encode(fileEntity.getOriginalName(), "UTF-8"));
} catch (UnsupportedEncodingException e) {
log.error("文件名编码失败");
log.error(ExceptionUtils.getStackTrace(e));
}
try {
InputStream is = minioFileInterface.download(fileEntity.getPath());
IOUtils.copy(is, response.getOutputStream());
is.close();
response.getOutputStream().close();
} catch (Exception e) {
response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
log.error("下载文件失败: {}", fileEntity.getPath());
log.error(ExceptionUtils.getStackTrace(e));
} finally {
sysFileService.updateDownloadCount(1, fileId);
}
}
/**
* 删除文件
*/
@Override
public void delete(String fileId) {
DataRoomFileEntity fileEntity = sysFileService.getById(fileId);
if (fileEntity == null) {
log.error("删除的文件不存在");
return;
}
sysFileService.removeById(fileId);
String path = fileEntity.getPath();
try {
minioFileInterface.deleteObject(path);
} catch (Exception e) {
log.error("删除Minio文件失败: {}", path);
log.error(ExceptionUtils.getStackTrace(e));
}
}
@Override
public String copy(String sourcePath, String targetPath) {
DataRoomMinioConfig minioConfig = bigScreenConfig.getFile().getMinio();
CopySource source = CopySource.builder().bucket(minioConfig.getBucketName()).object(sourcePath).build();
CopyObjectArgs args = CopyObjectArgs.builder()
.bucket(minioConfig.getBucketName())
.object(PathUtils.normalizePath(targetPath))
.source(source)
.build();
try {
minioclient.copyObject(args);
} catch (Exception e) {
log.error("复制Minio文件失败: {}", sourcePath);
log.error(ExceptionUtils.getStackTrace(e));
return "";
}
return minioConfig.getBucketName() + "/" + targetPath;
}
}

View File

@@ -0,0 +1,157 @@
package com.gccloud.dataroom.core.module.file.service.impl;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.gccloud.common.exception.GlobalException;
import com.gccloud.dataroom.core.config.DataRoomConfig;
import com.gccloud.dataroom.core.config.bean.FileConfig;
import com.gccloud.dataroom.core.module.file.entity.DataRoomFileEntity;
import com.gccloud.dataroom.core.module.file.service.IDataRoomFileService;
import com.gccloud.dataroom.core.module.file.service.IDataRoomOssService;
import com.gccloud.dataroom.core.utils.SftpClientUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
/**
* sftp文件管理实现类
* 将文件上传至sftp服务器需要配置sftp服务器相关信息
* 由于该方案无法直接通过url访问文件所以需要手动在对应的服务器上部署nginx等服务将sftp服务器上的文件开放访问然后将该服务地址配置到gc.starter.file.urlPrefix中
* @author hongyang
* @version 1.0
* @date 2023/10/17 15:12
*/
@Slf4j
@Service
@ConditionalOnProperty(prefix = "gc.starter.file", name = "type", havingValue = "sftp")
public class DataRoomSftpFileServiceImpl implements IDataRoomOssService {
@Resource
private SftpClientUtils sftpUtil;
@Resource
private DataRoomConfig bigScreenConfig;
@Resource
private IDataRoomFileService sysFileService;
@Override
public DataRoomFileEntity upload(MultipartFile file, DataRoomFileEntity fileEntity, HttpServletResponse response, HttpServletRequest request) {
String originalFilename = file.getOriginalFilename();
// 提取文件后缀名
String extension = FilenameUtils.getExtension(originalFilename);
FileConfig fileConfig = bigScreenConfig.getFile();
if (!fileConfig.getAllowedFileExtensionName().contains("*") && !fileConfig.getAllowedFileExtensionName().contains(extension)) {
log.error("不支持 {} 文件类型",extension);
throw new GlobalException("不支持的文件类型");
}
long size = file.getSize();
// 重命名
String id = IdWorker.getIdStr();
String newFileName = id + "." + extension;
InputStream inputStream;
try {
inputStream = file.getInputStream();
} catch (IOException e) {
log.error("上传文件到SFTP服务失败获取文件流失败");
log.error(ExceptionUtils.getStackTrace(e));
throw new GlobalException("获取文件流失败");
}
this.upload(inputStream, newFileName, size, fileEntity);
return fileEntity;
}
@Override
public DataRoomFileEntity upload(InputStream inputStream, String fileName, long size, DataRoomFileEntity fileEntity) {
// 提取文件后缀名
String extension = FilenameUtils.getExtension(fileName);
// 上传的目标路径
String basePath = bigScreenConfig.getFile().getBasePath();
// 上传文件到sftp
boolean upload = sftpUtil.upload(basePath, fileName, inputStream);
if (!upload) {
log.error("上传文件到sftp失败");
throw new GlobalException("上传文件到sftp失败");
}
fileEntity.setOriginalName(fileName);
fileEntity.setNewName(fileName);
fileEntity.setPath(basePath);
fileEntity.setSize(size);
fileEntity.setExtension(extension);
fileEntity.setUrl("/" + fileName);
return fileEntity;
}
@Override
public void download(String fileId, HttpServletResponse response, HttpServletRequest request) {
DataRoomFileEntity fileEntity = sysFileService.getById(fileId);
if (fileEntity == null) {
response.setStatus(HttpStatus.NOT_FOUND.value());
log.error("下载的文件不存在");
return;
}
response.setContentType("application/x-msdownload");
response.setContentType("multipart/form-data");
// 不设置前端无法从header获取文件名
response.setHeader("Access-Control-Expose-Headers", "filename");
try {
response.setHeader("filename", URLEncoder.encode(fileEntity.getOriginalName(), "UTF-8"));
// 解决下载的文件不携带后缀
response.setHeader("Content-Disposition", "attachment;fileName="+URLEncoder.encode(fileEntity.getOriginalName(),"UTF-8"));
} catch (UnsupportedEncodingException e) {
log.error(ExceptionUtils.getStackTrace(e));
}
OutputStream outputStream;
try {
outputStream = response.getOutputStream();
} catch (IOException e) {
log.error(ExceptionUtils.getStackTrace(e));
response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
return;
}
boolean download = sftpUtil.download(fileEntity.getPath(), fileEntity.getNewName(), outputStream);
if (!download) {
log.error("下载文件失败");
response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
}
try {
outputStream.close();
} catch (IOException e) {
log.error(ExceptionUtils.getStackTrace(e));
}
sysFileService.updateDownloadCount(1, fileId);
}
@Override
public void delete(String fileId) {
DataRoomFileEntity fileEntity = sysFileService.getById(fileId);
if (fileEntity == null) {
log.error("删除的文件不存在");
return;
}
sysFileService.removeById(fileId);
// 删除sftp上的文件
sftpUtil.delete(fileEntity.getPath(), fileEntity.getNewName());
}
@Override
public String copy(String sourcePath, String targetPath) {
String basePath = bigScreenConfig.getFile().getBasePath() + File.separator;
boolean copySuccess = sftpUtil.copy(basePath + sourcePath, basePath + targetPath);
if (!copySuccess) {
return "";
}
return targetPath;
}
}

View File

@@ -0,0 +1,153 @@
package com.gccloud.dataroom.core.module.file.service.pool.ftp;
import com.gccloud.dataroom.core.config.DataRoomConfig;
import com.gccloud.dataroom.core.config.bean.DataRoomFtpConfig;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPReply;
import org.apache.commons.pool2.PooledObject;
import org.apache.commons.pool2.PooledObjectFactory;
import org.apache.commons.pool2.impl.DefaultPooledObject;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
/**
* FtpClient 工厂连接对象
* @author hongyang
* @version 1.0
* @date 2023/10/18 10:17
*/
@Slf4j
@Component
@ConditionalOnProperty(prefix = "gc.starter.file", name = "type", havingValue = "ftp")
public class FtpClientFactory implements PooledObjectFactory<FTPClient> {
/**
* 注入 ftp 连接配置
*/
@Resource
private DataRoomConfig config;
/**
* 创建连接到池中
*
* @return
* @throws Exception
*/
@Override
public PooledObject<FTPClient> makeObject() throws Exception {
log.info("创建ftp连接");
DataRoomFtpConfig ftp = config.getFile().getFtp();
FTPClient ftpClient = new FTPClient();
ftpClient.setConnectTimeout(ftp.getClientTimeout());
ftpClient.connect(ftp.getHost(), ftp.getPort());
int reply = ftpClient.getReplyCode();
if (!FTPReply.isPositiveCompletion(reply)) {
ftpClient.disconnect();
return null;
}
boolean success;
if (StringUtils.isBlank(ftp.getUsername())) {
success = ftpClient.login("anonymous", "anonymous");
} else {
success = ftpClient.login(ftp.getUsername(), ftp.getPassword());
}
if (!success) {
return null;
}
ftpClient.setFileType(ftp.getTransferFileType());
ftpClient.setBufferSize(1024);
ftpClient.setControlEncoding(ftp.getEncoding());
if (ftp.isPassiveMode()) {
ftpClient.enterLocalPassiveMode();
}
log.debug("创建ftp连接");
return new DefaultPooledObject<>(ftpClient);
}
/**
* 链接状态检查
*
* @param pool
* @return
*/
@Override
public boolean validateObject(PooledObject<FTPClient> pool) {
FTPClient ftpClient = pool.getObject();
try {
return ftpClient != null && ftpClient.sendNoOp();
} catch (Exception e) {
return false;
}
}
/**
* 销毁连接,当连接池空闲数量达到上限时,调用此方法销毁连接
*
* @param pool
* @throws Exception
*/
@Override
public void destroyObject(PooledObject<FTPClient> pool) throws Exception {
FTPClient ftpClient = pool.getObject();
if (ftpClient != null) {
try {
ftpClient.disconnect();
log.debug("销毁ftp连接");
} catch (Exception e) {
log.error("销毁FtpClient异常");
log.error(ExceptionUtils.getStackTrace(e));
}
}
}
/**
* 钝化连接
* 在连接被归还到连接池时,调用此方法
* @param p
* @throws Exception
*/
@Override
public void passivateObject(PooledObject<FTPClient> p) throws Exception{
FTPClient ftpClient = p.getObject();
try {
ftpClient.changeWorkingDirectory(config.getFile().getBasePath());
// 钝化链接时如果logout下次再使用重新连接时间会长所以先不做logout操作
/*
* ftpClient.logout();
* if (ftpClient.isConnected()) {
* ftpClient.disconnect();
* }
*/
} catch (Exception e) {
log.error("钝化FtpClient异常");
log.error(ExceptionUtils.getStackTrace(e));
}
}
/**
* 激活连接
* 在连接从连接池中取出时,调用此方法
* @param pool
* @throws Exception
*/
@Override
public void activateObject(PooledObject<FTPClient> pool) throws Exception {
DataRoomFtpConfig ftp = config.getFile().getFtp();
FTPClient ftpClient = pool.getObject();
if (!ftpClient.isConnected()) {
log.info("ftp连接已关闭重新连接");
ftpClient.connect(ftp.getHost(),ftp.getPort());
ftpClient.login(ftp.getUsername(), ftp.getPassword());
}
ftpClient.setControlEncoding(ftp.getEncoding());
ftpClient.changeWorkingDirectory(config.getFile().getBasePath());
// 设置上传文件类型为二进制,否则将无法打开文件
ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
}
}

View File

@@ -0,0 +1,79 @@
package com.gccloud.dataroom.core.module.file.service.pool.ftp;
import com.gccloud.dataroom.core.config.bean.DataRoomFtpConfig;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.pool2.impl.GenericObjectPool;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
/**
* @author hongyang
* @version 1.0
* @date 2023/10/18 10:20
*/
@Slf4j
@Component
@ConditionalOnProperty(prefix = "gc.starter.file", name = "type", havingValue = "ftp")
public class FtpPoolServiceImpl {
/**
* ftp 连接池生成
*/
private GenericObjectPool<FTPClient> pool;
/**
* ftp 客户端配置文件
*/
@Resource
private DataRoomFtpConfig config;
/**
* ftp 客户端工厂
*/
@Resource
private FtpClientFactory factory;
/**
* 初始化pool
*/
@PostConstruct
private void initPool() {
log.info("初始化FTP连接池");
this.pool = new GenericObjectPool<FTPClient>(this.factory, this.config);
}
/**
* 获取ftpClient
*/
public FTPClient borrowObject() {
log.info("获取 FTPClient");
if (this.pool != null) {
try {
return this.pool.borrowObject();
} catch (Exception e) {
log.error("获取 FTPClient 失败 ", e);
}
}
return null;
}
/**
* 归还 ftpClient
*/
public void returnObject(FTPClient ftpClient) {
if (this.pool == null || ftpClient == null) {
return;
}
try {
ftpClient.changeWorkingDirectory("/");
} catch (Exception e) {
log.error("FTPClient 重置目录失败 ", e);
}
this.pool.returnObject(ftpClient);
}
}

View File

@@ -0,0 +1,105 @@
package com.gccloud.dataroom.core.module.file.service.pool.sftp;
import com.gccloud.dataroom.core.config.bean.DataRoomSftpConfig;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.apache.commons.pool2.BasePooledObjectFactory;
import org.apache.commons.pool2.PooledObject;
import org.apache.commons.pool2.impl.DefaultPooledObject;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.Properties;
/**
* SFTP 工厂连接对象
* @author hongyang
* @version 1.0
* @date 2023/10/18 15:17
*/
@Slf4j
@Component
@ConditionalOnProperty(prefix = "gc.starter.file", name = "type", havingValue = "sftp")
public class SftpClientFactory extends BasePooledObjectFactory<ChannelSftp>{
@Resource
private DataRoomSftpConfig config;
/**
* 新建对象
*/
@Override
public ChannelSftp create() {
ChannelSftp channel = null;
try {
// 用户名密码不能为空
if (StringUtils.isBlank(config.getUsername()) || StringUtils.isBlank(config.getPassword())) {
log.error("SFTP用户名密码不能为空");
return null;
}
JSch jsch = new JSch();
// 设置私钥
if (StringUtils.isNotBlank(config.getPrivateKey())) {
jsch.addIdentity(config.getPrivateKey());
}
// jsch的session需要补充设置sshConfig.put("PreferredAuthentications", "publickey,keyboard-interactive,password")来跳过Kerberos认证同样的HutoolSFTPUtil工具类里面也有这个问题
Session sshSession = jsch.getSession(config.getUsername(), config.getHost(), config.getPort());
sshSession.setPassword(config.getPassword());
Properties sshConfig = new Properties();
// “StrictHostKeyChecking”如果设置成“yes”ssh就不会自动把计算机的密匙加入“$HOME/.ssh/known_hosts”文件并且一旦计算机的密匙发生了变化就拒绝连接。
sshConfig.put("StrictHostKeyChecking", "no");
sshSession.setConfig(sshConfig);
sshSession.connect();
channel = (ChannelSftp) sshSession.openChannel("sftp");
channel.connect();
} catch (Exception e) {
log.error("连接 sftp 失败,请检查配置");
log.error(ExceptionUtils.getStackTrace(e));
}
return channel;
}
/**
* 创建一个连接
*
* @param channelSftp
* @return
*/
@Override
public PooledObject<ChannelSftp> wrap(ChannelSftp channelSftp) {
return new DefaultPooledObject<>(channelSftp);
}
/**
* 销毁一个连接
*
* @param p
*/
@Override
public void destroyObject(PooledObject<ChannelSftp> p) {
ChannelSftp channelSftp = p.getObject();
channelSftp.disconnect();
}
@Override
public boolean validateObject(final PooledObject<ChannelSftp> p) {
final ChannelSftp channelSftp = p.getObject();
try {
if (channelSftp.isClosed()) {
return false;
}
channelSftp.cd("/");
} catch (Exception e) {
log.error("ChannelSftp 不可用");
log.error(ExceptionUtils.getStackTrace(e));
return false;
}
return true;
}
}

View File

@@ -0,0 +1,74 @@
package com.gccloud.dataroom.core.module.file.service.pool.sftp;
import com.gccloud.dataroom.core.config.bean.DataRoomSftpConfig;
import com.jcraft.jsch.ChannelSftp;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.pool2.impl.GenericObjectPool;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
/**
* Sftp 连接池服务类
* @author hongyang
* @version 1.0
* @date 2023/10/18 15:21
*/
@Slf4j
@Component
@ConditionalOnProperty(prefix = "gc.starter.file", name = "type", havingValue = "sftp")
public class SftpPoolService {
/**
* ftp 连接池生成
*/
private GenericObjectPool<ChannelSftp> pool;
/**
* ftp 客户端配置文件
*/
@Resource
private DataRoomSftpConfig config;
/**
* ftp 客户端工厂
*/
@Resource
private SftpClientFactory factory;
/**
* 初始化pool
*/
@PostConstruct
private void initPool() {
log.info("初始化SFTP连接池");
this.pool = new GenericObjectPool<ChannelSftp>(this.factory, this.config);
}
/**
* 获取sftp
*/
public ChannelSftp borrowObject() {
if (this.pool != null) {
try {
return this.pool.borrowObject();
} catch (Exception e) {
log.error("获取 ChannelSftp 失败", e);
e.printStackTrace();
}
}
return null;
}
/**
* 归还 sftp
*/
public void returnObject(ChannelSftp channelSftp) {
if (this.pool != null && channelSftp != null) {
this.pool.returnObject(channelSftp);
}
}
}

View File

@@ -0,0 +1,25 @@
package com.gccloud.dataroom.core.module.file.vo;
import com.gccloud.dataroom.core.module.file.entity.DataRoomFileEntity;
import lombok.Data;
import java.io.Serializable;
import java.text.DecimalFormat;
@Data
public class DataRoomFileVO extends DataRoomFileEntity implements Serializable {
/**
* 暂用空间根据size进行计算出来
*/
private String space;
public String getSpace() {
long size = this.getSize();
if (size <= 0) {
return "0";
}
final String[] units = new String[]{"B", "KB", "MB", "GB", "TB"};
int digitGroups = (int) (Math.log10(size) / Math.log10(1000));
return new DecimalFormat("#,##0.##").format(size / Math.pow(1000, digitGroups)) + " " + units[digitGroups];
}
}

View File

@@ -0,0 +1,193 @@
package com.gccloud.dataroom.core.module.manage.controller;
import com.gccloud.dataroom.core.config.DataRoomConfig;
import com.gccloud.dataroom.core.constant.DataRoomConst;
import com.gccloud.dataroom.core.module.basic.entity.PageEntity;
import com.gccloud.dataroom.core.module.basic.entity.PagePreviewEntity;
import com.gccloud.dataroom.core.module.manage.dto.DataRoomPageDTO;
import com.gccloud.dataroom.core.module.manage.dto.DataRoomSearchDTO;
import com.gccloud.dataroom.core.module.manage.service.IDataRoomPagePreviewService;
import com.gccloud.dataroom.core.module.manage.service.IDataRoomPageService;
import com.gccloud.dataroom.core.module.manage.vo.StaticFileVO;
import com.gccloud.dataroom.core.permission.Permission;
import com.gccloud.common.permission.ApiPermission;
import com.gccloud.dataroom.core.utils.Webjars;
import com.gccloud.common.exception.GlobalException;
import com.gccloud.common.utils.BeanConvertUtils;
import com.gccloud.common.validator.ValidatorUtils;
import com.gccloud.common.validator.group.Insert;
import com.gccloud.common.validator.group.Update;
import com.gccloud.common.vo.MixinsResp;
import com.gccloud.common.vo.PageVO;
import com.gccloud.common.vo.R;
import com.google.common.collect.Lists;
import com.swiot.common.annotation.Anonymous;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.List;
/**
* @author hongyang
* @version 1.0
* @date 2023/3/13 10:55
*/
@Slf4j
@RestController
@RequestMapping("/bigScreen/design")
@Api(tags = "大屏页以及大屏组件设计")
public class DataRoomPageController {
@Resource
private IDataRoomPageService bigScreenPageService;
@Resource
private DataRoomConfig bigScreenConfig;
@Resource
private IDataRoomPagePreviewService previewService;
@ApiPermission(permissions = {Permission.DataRoom.VIEW})
@GetMapping("/info/code/{code}")
@ApiOperation(value = "大屏页/组件详情", position = 10, produces = MediaType.APPLICATION_JSON_VALUE)
public MixinsResp<DataRoomPageDTO> info(@PathVariable("code") String code) {
if (code.startsWith(IDataRoomPagePreviewService.PREVIEW_KEY)) {
PagePreviewEntity preview = previewService.getByCode(code);
MixinsResp<DataRoomPageDTO> r = new MixinsResp<DataRoomPageDTO>().setData((DataRoomPageDTO) preview.getConfig());
r.setCode(DataRoomConst.Response.Code.SUCCESS);
return r;
}
PageEntity bigScreen = bigScreenPageService.getByCode(code);
DataRoomPageDTO bigScreenPageDTO = (DataRoomPageDTO) bigScreen.getConfig();
BeanConvertUtils.convert(bigScreen, bigScreenPageDTO);
MixinsResp<DataRoomPageDTO> resp = new MixinsResp<DataRoomPageDTO>().setData(bigScreenPageDTO);
resp.setCode(DataRoomConst.Response.Code.SUCCESS);
return resp;
}
@ApiPermission(permissions = {Permission.DataRoom.VIEW})
@GetMapping("/page")
@ApiOperation(value = "大屏/组件分页列表", position = 10, produces = MediaType.APPLICATION_JSON_VALUE)
public MixinsResp<PageVO<PageEntity>> page(DataRoomSearchDTO searchDTO) {
PageVO<PageEntity> page = bigScreenPageService.getByCategory(searchDTO);
MixinsResp<PageVO<PageEntity>> resp = new MixinsResp<PageVO<PageEntity>>().setData(page);
resp.setCode(DataRoomConst.Response.Code.SUCCESS);
return resp;
}
@ApiPermission(permissions = {Permission.DataRoom.ADD})
@PostMapping("/add")
@ApiOperation(value = "从空白新增大屏/组件", position = 20, produces = MediaType.APPLICATION_JSON_VALUE)
public R<String> add(@RequestBody DataRoomPageDTO bigScreenPageDTO) {
System.out.println("bigScreenPageDTO:"+ bigScreenPageDTO);
ValidatorUtils.validateEntity(bigScreenPageDTO, Insert.class);
bigScreenPageService.add(bigScreenPageDTO);
return R.success(bigScreenPageDTO.getCode());
}
@ApiPermission(permissions = {Permission.DataRoom.UPDATE})
@PostMapping("/update")
@ApiOperation(value = "修改大屏/组件", position = 30, produces = MediaType.APPLICATION_JSON_VALUE)
public R<String> update(@RequestBody DataRoomPageDTO bigScreenPageDTO) {
if (Boolean.TRUE.equals(bigScreenPageDTO.getIsPreview())) {
// 保存到预览临时缓存表
String code = previewService.add(bigScreenPageDTO);
return R.success(code);
}
ValidatorUtils.validateEntity(bigScreenPageDTO, Update.class);
bigScreenPageService.update(bigScreenPageDTO);
return R.success(bigScreenPageDTO.getCode());
}
@ApiPermission(permissions = {Permission.DataRoom.DELETE})
@PostMapping("/delete/{code}")
@ApiOperation(value = "删除大屏/组件", position = 40, produces = MediaType.APPLICATION_JSON_VALUE)
public R<Void> delete(@PathVariable String code) {
PageEntity bigScreenPage = bigScreenPageService.getByCode(code);
if (bigScreenPage == null) {
return R.success();
}
bigScreenPageService.deleteByCode(code);
return R.success();
}
@ApiPermission(permissions = {Permission.DataRoom.ADD})
@PostMapping("/copy/{code}")
@ApiOperation(value = "复制大屏/组件", position = 50, produces = MediaType.APPLICATION_JSON_VALUE)
public R<String> copy(@PathVariable String code) {
PageEntity bigScreenPage = bigScreenPageService.getByCode(code);
if (bigScreenPage == null) {
throw new GlobalException("大屏页不存在");
}
String newCode = bigScreenPageService.copy(bigScreenPage);
return R.success(newCode);
}
@ApiPermission(permissions = {Permission.DataRoom.ADD})
@PostMapping("/add/template")
@ApiOperation(value = "从模板新增大屏页", position = 20, produces = MediaType.APPLICATION_JSON_VALUE)
public R<String> addByTemplate(@RequestBody DataRoomPageDTO bigScreenPageDTO) {
String code = bigScreenPageService.addByTemplate(bigScreenPageDTO);
return R.success(code);
}
@PostMapping("/get/template")
@ApiOperation(value = "根据模板获取配置", position = 20, produces = MediaType.APPLICATION_JSON_VALUE)
public MixinsResp<DataRoomPageDTO> getByTemplate(@RequestBody DataRoomPageDTO bigScreenPageDTO) {
DataRoomPageDTO config = bigScreenPageService.getConfigByTemplate(bigScreenPageDTO);
MixinsResp<DataRoomPageDTO> resp = new MixinsResp<DataRoomPageDTO>().setData(config);
resp.setCode(DataRoomConst.Response.Code.SUCCESS);
return resp;
}
@ApiPermission
@GetMapping("/bg/list")
@ApiOperation(value = "背景图片列表", position = 60, produces = MediaType.APPLICATION_JSON_VALUE)
public R<List<StaticFileVO>> getBgList() {
List<String> staticFileList = Webjars.BIG_SCREEN_BG;
List<StaticFileVO> bgList = Lists.newArrayList();
String urlPrefix = bigScreenConfig.getFile().getUrlPrefix() + "bigScreenBg/";
for (String fileName : staticFileList) {
StaticFileVO fileVO = new StaticFileVO();
fileVO.setUrl(urlPrefix + fileName);
fileVO.setName(fileName);
bgList.add(fileVO);
}
return R.success(bgList);
}
@ApiPermission
@GetMapping("/map/list/{level}")
@ApiOperation(value = "地图数据列表", position = 60, produces = MediaType.APPLICATION_JSON_VALUE)
public R<List<StaticFileVO>> getMapJsonList(@PathVariable("level") String level) {
List<String> staticFileList = Lists.newArrayList();
if ("country".equals(level)) {
staticFileList = Webjars.COUNTRY_MAP_DATA;
}
if ("province".equals(level)) {
staticFileList = Webjars.PROVINCE_MAP_DATA;
}
List<StaticFileVO> bgList = Lists.newArrayList();
String urlPrefix = "static/chinaMap/" + level + "/";
for (String fileName : staticFileList) {
StaticFileVO fileVO = new StaticFileVO();
fileVO.setUrl(fileName);
fileVO.setName(fileName.replace(".json", ""));
bgList.add(fileVO);
}
return R.success(bgList);
}
@ApiPermission
@PostMapping("/name/repeat")
@ApiOperation(value = "大屏/组件名称是否重复", position = 60, produces = MediaType.APPLICATION_JSON_VALUE)
public R<Boolean> nameRepeat(@RequestBody PageEntity pageEntity) {
boolean repeat = bigScreenPageService.checkNameRepeat(pageEntity);
return R.success(repeat);
}
}

View File

@@ -0,0 +1,139 @@
package com.gccloud.dataroom.core.module.manage.dto;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.gccloud.common.utils.EmptyAsNullDeserializer;
import com.gccloud.common.validator.group.Insert;
import com.gccloud.common.validator.group.Update;
import com.gccloud.dataroom.core.constant.PageDesignConstant;
import com.gccloud.dataroom.core.module.basic.dto.BasePageDTO;
import com.gccloud.dataroom.core.module.chart.bean.Chart;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import java.util.List;
/**
* 大屏页面
* @author hongyang
* @version 1.0
* @date 2023/3/13 10:49
*/
@Data
public class DataRoomPageDTO extends BasePageDTO {
@JsonDeserialize(using = EmptyAsNullDeserializer.class)
@NotBlank(message = "id不能为空", groups = Update.class)
@ApiModelProperty(notes = "主键id")
private String id;
@NotBlank(message = "名称不能为空", groups = {Update.class, Insert.class})
@ApiModelProperty(notes = "大屏名称")
private String name;
@NotBlank(message = "编码不能为空", groups = {Update.class})
@ApiModelProperty(notes = "大屏唯一标识符")
private String code;
@ApiModelProperty(notes = "大屏页图标")
private String icon;
@ApiModelProperty(notes = "大屏首页封面")
private String coverPicture;
@ApiModelProperty(notes = "大屏页颜色")
private String iconColor;
@ApiModelProperty(notes = "排序")
private Integer orderNum;
@ApiModelProperty(notes = "备注")
private String remark;
@ApiModelProperty(notes = "大屏整体样式")
private String style;
@ApiModelProperty(notes = "父节点编码")
private String parentCode;
@ApiModelProperty(notes = "图表数据")
private List<Chart> chartList;
@ApiModelProperty(notes = "页面模板id")
private String pageTemplateId;
/**
* 参考:{@link PageDesignConstant.Type}
*/
@NotBlank(message = "类型不能为空", groups = {Update.class, Insert.class})
@ApiModelProperty(notes = "类型")
private String type;
@ApiModelProperty(notes = "页面配置")
private PageConfig pageConfig;
@ApiModelProperty(notes = "所属应用编码")
private String appCode;
@ApiModelProperty(notes = "是否预览")
private Boolean isPreview;
@Data
public static class CacheDataSet {
@ApiModelProperty(notes = "数据集名称")
private String name;
@ApiModelProperty(notes = "数据集id")
private String dataSetId;
}
@Data
public static class PageConfig {
@ApiModelProperty(notes = "宽度")
private Integer w;
@ApiModelProperty(notes = "高度")
private Integer h;
@ApiModelProperty(notes = "背景色")
private String bgColor;
@ApiModelProperty(notes = "明亮模式背景色")
private String lightBgColor;
@ApiModelProperty(notes = "背景图")
private String bg;
@ApiModelProperty(notes = "明亮模式背景图")
private String lightBg;
@ApiModelProperty(notes = "自定义主题")
private String customTheme;
@ApiModelProperty(notes = "透明度")
private Float opacity;
@ApiModelProperty(notes = "缓存数据集")
private List<CacheDataSet> cacheDataSets;
@ApiModelProperty(notes = "自适应类型")
private String fitMode;
@ApiModelProperty(notes = "定时刷新配置")
private List<RefreshConfig> refreshConfig;
}
@Data
public static class RefreshConfig {
@ApiModelProperty(notes = "组件编码")
private String code;
@ApiModelProperty(notes = "刷新时间,单位秒")
private Integer time;
}
}

View File

@@ -0,0 +1,22 @@
package com.gccloud.dataroom.core.module.manage.dto;
import com.gccloud.common.dto.SearchDTO;
import lombok.Data;
/**
* @author hongynag
* @version 1.0
*/
@Data
public class DataRoomSearchDTO extends SearchDTO {
/**
* 所属分组
*/
private String parentCode;
/**
* 类型
*/
private String type;
}

View File

@@ -0,0 +1,51 @@
package com.gccloud.dataroom.core.module.manage.extend;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* @author hongyang
* @version 1.0
* @date 2023/8/1 15:10
*/
@Component
public class DataRoomExtendClient {
@Autowired(required = false)
private IDataRoomExtendService extendService;
/**
* 删除大屏后的扩展方法
* @param code
*/
public void deleteByCode(String code) {
if (extendService != null) {
extendService.deleteByCode(code);
}
}
/**
* 大屏新增后的处理
* @param code 新增的大屏code
*/
public void afterAdd(String code) {
if (extendService != null) {
extendService.afterAdd(code);
}
}
/**
* 大屏删除后的处理
* @param code 删除的大屏code
*/
public void afterDelete(String code) {
if (extendService != null) {
extendService.afterDelete(code);
}
}
}

View File

@@ -0,0 +1,34 @@
package com.gccloud.dataroom.core.module.manage.extend;
import java.util.List;
/**
* 大屏扩展接口
* @author hongyang
* @version 1.0
* @date 2023/8/1 15:10
*/
public interface IDataRoomExtendService {
/**
* 大屏删除拓展
* 会在大屏删除后调用
* 已废弃请使用afterDelete方法
* @param code
*/
@Deprecated
default void deleteByCode(String code) {}
/**
* 大屏新增后的处理, 可在此处处理权限等
* @param code 新增的大屏code
*/
default void afterAdd(String code) {}
/**
* 大屏删除后的处理, 可在此处处理权限等
* @param code 删除的大屏code
*/
default void afterDelete(String code) {}
}

View File

@@ -0,0 +1,36 @@
package com.gccloud.dataroom.core.module.manage.service;
import com.gccloud.common.service.ISuperService;
import com.gccloud.dataroom.core.module.basic.entity.PagePreviewEntity;
import com.gccloud.dataroom.core.module.manage.dto.DataRoomPageDTO;
/**
* @author hongyang
* @version 1.0
* @date 2023/9/13 10:10
*/
public interface IDataRoomPagePreviewService extends ISuperService<PagePreviewEntity> {
String PREVIEW_KEY = "preview";
/**
* 保存大屏预览数据
* @param bigScreenPageDTO
* @return
*/
String add(DataRoomPageDTO bigScreenPageDTO);
/**
* 根据code获取大屏预览数据
* @param code
* @return
*/
PagePreviewEntity getByCode(String code);
/**
* 清理预览数据
*/
void clear();
}

View File

@@ -0,0 +1,70 @@
package com.gccloud.dataroom.core.module.manage.service;
import com.gccloud.dataroom.core.module.basic.entity.PageEntity;
import com.gccloud.dataroom.core.module.basic.service.IBasePageService;
import com.gccloud.dataroom.core.module.manage.dto.DataRoomPageDTO;
import com.gccloud.dataroom.core.module.manage.dto.DataRoomSearchDTO;
import com.gccloud.common.vo.PageVO;
/**
* @author hongyang
* @version 1.0
* @date 2023/3/13 10:59
*/
public interface IDataRoomPageService extends IBasePageService {
/**
* 从空白新增大屏页
*
* @param bigScreenPageDTO
* @return
*/
String add(DataRoomPageDTO bigScreenPageDTO);
/**
* 从模板新增大屏页
*
* @param bigScreenPageDTO
* @return
*/
String addByTemplate(DataRoomPageDTO bigScreenPageDTO);
/**
* 根据编码获取大屏页配置
*
* @param bigScreenPageDTO
* @return
*/
DataRoomPageDTO getConfigByTemplate(DataRoomPageDTO bigScreenPageDTO);
/**
* 分页查询
*
* @param searchDTO
* @return
*/
PageVO<PageEntity> getByCategory(DataRoomSearchDTO searchDTO);
/**
* 更新大屏页
*
* @param bigScreenPageDTO
*/
void update(DataRoomPageDTO bigScreenPageDTO);
/**
* 复制大屏页
* @param screenEntity
* @return
*/
String copy(PageEntity screenEntity);
/**
* 根据编码删除
*
* @param code
*/
void deleteByCode(String code);
}

View File

@@ -0,0 +1,71 @@
package com.gccloud.dataroom.core.module.manage.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gccloud.common.exception.GlobalException;
import com.gccloud.common.utils.BeanConvertUtils;
import com.gccloud.dataroom.core.module.basic.dao.DataRoomPagePreviewDao;
import com.gccloud.dataroom.core.module.basic.entity.PagePreviewEntity;
import com.gccloud.dataroom.core.module.chart.bean.Chart;
import com.gccloud.dataroom.core.module.manage.dto.DataRoomPageDTO;
import com.gccloud.dataroom.core.module.manage.service.IDataRoomPagePreviewService;
import com.gccloud.dataroom.core.utils.CodeGenerateUtils;
import org.springframework.stereotype.Service;
import java.util.Date;
import java.util.List;
/**
* @author hongyang
* @version 1.0
* @date 2023/9/13 10:11
*/
@Service
public class DataRoomPagePreviewServiceImpl extends ServiceImpl<DataRoomPagePreviewDao, PagePreviewEntity> implements IDataRoomPagePreviewService {
@Override
public String add(DataRoomPageDTO bigScreenPageDTO) {
String originalCode = bigScreenPageDTO.getCode();
String code = PREVIEW_KEY + "_" + originalCode;
LambdaQueryWrapper<PagePreviewEntity> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(PagePreviewEntity::getCode, code);
List<PagePreviewEntity> list = this.list(queryWrapper);
if (list != null && !list.isEmpty()) {
// 有则直接更新
PagePreviewEntity pagePreviewEntity = list.get(0);
bigScreenPageDTO.setCode(code);
pagePreviewEntity.setConfig(bigScreenPageDTO);
pagePreviewEntity.setCreateDate(new Date());
this.updateById(pagePreviewEntity);
return code;
}
// 没有则新增
bigScreenPageDTO.setCode(code);
PagePreviewEntity pagePreviewEntity = BeanConvertUtils.convert(bigScreenPageDTO, PagePreviewEntity.class);
pagePreviewEntity.setCreateDate(new Date());
pagePreviewEntity.setConfig(bigScreenPageDTO);
this.save(pagePreviewEntity);
return code;
}
@Override
public PagePreviewEntity getByCode(String code) {
LambdaQueryWrapper<PagePreviewEntity> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(PagePreviewEntity::getCode, code);
List<PagePreviewEntity> list = this.list(queryWrapper);
if (list == null || list.isEmpty()) {
throw new GlobalException("大屏预览数据不存在,可能已过期");
}
return list.get(0);
}
@Override
public void clear() {
// 清除创建时间超过一天的预览数据
Date date = new Date();
date.setTime(date.getTime() - 24 * 60 * 60 * 1000);
LambdaQueryWrapper<PagePreviewEntity> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.le(PagePreviewEntity::getCreateDate, date);
this.delete(queryWrapper);
}
}

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