forked from github/dataease
Merge branch 'main' of github.com:dataease/dataease into main
This commit is contained in:
commit
defdc1123c
@ -13,6 +13,9 @@ import io.dataease.auth.util.RsaUtil;
|
||||
import io.dataease.commons.utils.BeanUtils;
|
||||
import io.dataease.commons.utils.CodingUtil;
|
||||
import io.dataease.commons.utils.ServletUtils;
|
||||
/*import io.dataease.plugins.config.SpringContextUtil;
|
||||
import io.dataease.plugins.xpack.dto.response.SysSettingDto;
|
||||
import io.dataease.plugins.xpack.service.DePluginXpackService;*/
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.shiro.SecurityUtils;
|
||||
@ -105,6 +108,14 @@ public class AuthServer implements AuthApi {
|
||||
SysUserEntity userById = authUserService.getUserById(4L);
|
||||
String nickName = userById.getNickName();
|
||||
System.out.println(nickName);
|
||||
/* Map<String, DePluginXpackService> beansOfType = SpringContextUtil.getApplicationContext().getBeansOfType(DePluginXpackService.class);
|
||||
for (Map.Entry entry : beansOfType.entrySet()) {
|
||||
Object key = entry.getKey();
|
||||
DePluginXpackService value = (DePluginXpackService)entry.getValue();
|
||||
List<SysSettingDto> sysSettingDtos = value.systemSettings();
|
||||
String name = entry.getValue().getClass().getName();
|
||||
System.out.println("key: "+ key + ", value: "+ name);
|
||||
}*/
|
||||
return "apple";
|
||||
}
|
||||
}
|
||||
|
@ -46,7 +46,12 @@ public class ShiroServiceImpl implements ShiroService {
|
||||
filterChainDefinitionMap.put("/chart/view/getData/**", ANON);
|
||||
|
||||
|
||||
filterChainDefinitionMap.put("/system/ui/**", ANON);
|
||||
filterChainDefinitionMap.put("/PluginDemo.js", ANON);
|
||||
filterChainDefinitionMap.put("/DeXPack.js", ANON);
|
||||
|
||||
filterChainDefinitionMap.put("/api/auth/test", ANON);
|
||||
filterChainDefinitionMap.put("/api/xpack/test", ANON);
|
||||
|
||||
filterChainDefinitionMap.put("/api/auth/login", ANON);
|
||||
filterChainDefinitionMap.put("/api/auth/validateName", ANON);
|
||||
|
35
backend/src/main/java/io/dataease/base/domain/MyPlugin.java
Normal file
35
backend/src/main/java/io/dataease/base/domain/MyPlugin.java
Normal file
@ -0,0 +1,35 @@
|
||||
package io.dataease.base.domain;
|
||||
|
||||
import java.io.Serializable;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class MyPlugin implements Serializable {
|
||||
private Long pluginId;
|
||||
|
||||
private String name;
|
||||
|
||||
private Boolean free;
|
||||
|
||||
private Integer cost;
|
||||
|
||||
private String descript;
|
||||
|
||||
private String version;
|
||||
|
||||
private Integer installType;
|
||||
|
||||
private String creator;
|
||||
|
||||
private Long releaseTime;
|
||||
|
||||
private Long installTime;
|
||||
|
||||
private String moduleName;
|
||||
|
||||
private String beanName;
|
||||
|
||||
private String icon;
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
}
|
1050
backend/src/main/java/io/dataease/base/domain/MyPluginExample.java
Normal file
1050
backend/src/main/java/io/dataease/base/domain/MyPluginExample.java
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,30 @@
|
||||
package io.dataease.base.mapper;
|
||||
|
||||
import io.dataease.base.domain.MyPlugin;
|
||||
import io.dataease.base.domain.MyPluginExample;
|
||||
import java.util.List;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
public interface MyPluginMapper {
|
||||
long countByExample(MyPluginExample example);
|
||||
|
||||
int deleteByExample(MyPluginExample example);
|
||||
|
||||
int deleteByPrimaryKey(Long pluginId);
|
||||
|
||||
int insert(MyPlugin record);
|
||||
|
||||
int insertSelective(MyPlugin record);
|
||||
|
||||
List<MyPlugin> selectByExample(MyPluginExample example);
|
||||
|
||||
MyPlugin selectByPrimaryKey(Long pluginId);
|
||||
|
||||
int updateByExampleSelective(@Param("record") MyPlugin record, @Param("example") MyPluginExample example);
|
||||
|
||||
int updateByExample(@Param("record") MyPlugin record, @Param("example") MyPluginExample example);
|
||||
|
||||
int updateByPrimaryKeySelective(MyPlugin record);
|
||||
|
||||
int updateByPrimaryKey(MyPlugin record);
|
||||
}
|
338
backend/src/main/java/io/dataease/base/mapper/MyPluginMapper.xml
Normal file
338
backend/src/main/java/io/dataease/base/mapper/MyPluginMapper.xml
Normal file
@ -0,0 +1,338 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="io.dataease.base.mapper.MyPluginMapper">
|
||||
<resultMap id="BaseResultMap" type="io.dataease.base.domain.MyPlugin">
|
||||
<id column="plugin_id" jdbcType="BIGINT" property="pluginId" />
|
||||
<result column="name" jdbcType="VARCHAR" property="name" />
|
||||
<result column="free" jdbcType="BIT" property="free" />
|
||||
<result column="cost" jdbcType="INTEGER" property="cost" />
|
||||
<result column="descript" jdbcType="VARCHAR" property="descript" />
|
||||
<result column="version" jdbcType="VARCHAR" property="version" />
|
||||
<result column="install_type" jdbcType="INTEGER" property="installType" />
|
||||
<result column="creator" jdbcType="VARCHAR" property="creator" />
|
||||
<result column="release_time" jdbcType="BIGINT" property="releaseTime" />
|
||||
<result column="install_time" jdbcType="BIGINT" property="installTime" />
|
||||
<result column="module_name" jdbcType="VARCHAR" property="moduleName" />
|
||||
<result column="bean_name" jdbcType="VARCHAR" property="beanName" />
|
||||
<result column="icon" jdbcType="VARCHAR" property="icon" />
|
||||
</resultMap>
|
||||
<sql id="Example_Where_Clause">
|
||||
<where>
|
||||
<foreach collection="oredCriteria" item="criteria" separator="or">
|
||||
<if test="criteria.valid">
|
||||
<trim prefix="(" prefixOverrides="and" suffix=")">
|
||||
<foreach collection="criteria.criteria" item="criterion">
|
||||
<choose>
|
||||
<when test="criterion.noValue">
|
||||
and ${criterion.condition}
|
||||
</when>
|
||||
<when test="criterion.singleValue">
|
||||
and ${criterion.condition} #{criterion.value}
|
||||
</when>
|
||||
<when test="criterion.betweenValue">
|
||||
and ${criterion.condition} #{criterion.value} and #{criterion.secondValue}
|
||||
</when>
|
||||
<when test="criterion.listValue">
|
||||
and ${criterion.condition}
|
||||
<foreach close=")" collection="criterion.value" item="listItem" open="(" separator=",">
|
||||
#{listItem}
|
||||
</foreach>
|
||||
</when>
|
||||
</choose>
|
||||
</foreach>
|
||||
</trim>
|
||||
</if>
|
||||
</foreach>
|
||||
</where>
|
||||
</sql>
|
||||
<sql id="Update_By_Example_Where_Clause">
|
||||
<where>
|
||||
<foreach collection="example.oredCriteria" item="criteria" separator="or">
|
||||
<if test="criteria.valid">
|
||||
<trim prefix="(" prefixOverrides="and" suffix=")">
|
||||
<foreach collection="criteria.criteria" item="criterion">
|
||||
<choose>
|
||||
<when test="criterion.noValue">
|
||||
and ${criterion.condition}
|
||||
</when>
|
||||
<when test="criterion.singleValue">
|
||||
and ${criterion.condition} #{criterion.value}
|
||||
</when>
|
||||
<when test="criterion.betweenValue">
|
||||
and ${criterion.condition} #{criterion.value} and #{criterion.secondValue}
|
||||
</when>
|
||||
<when test="criterion.listValue">
|
||||
and ${criterion.condition}
|
||||
<foreach close=")" collection="criterion.value" item="listItem" open="(" separator=",">
|
||||
#{listItem}
|
||||
</foreach>
|
||||
</when>
|
||||
</choose>
|
||||
</foreach>
|
||||
</trim>
|
||||
</if>
|
||||
</foreach>
|
||||
</where>
|
||||
</sql>
|
||||
<sql id="Base_Column_List">
|
||||
plugin_id, `name`, `free`, cost, descript, version, install_type, creator, release_time,
|
||||
install_time, module_name, bean_name, icon
|
||||
</sql>
|
||||
<select id="selectByExample" parameterType="io.dataease.base.domain.MyPluginExample" resultMap="BaseResultMap">
|
||||
select
|
||||
<if test="distinct">
|
||||
distinct
|
||||
</if>
|
||||
<include refid="Base_Column_List" />
|
||||
from my_plugin
|
||||
<if test="_parameter != null">
|
||||
<include refid="Example_Where_Clause" />
|
||||
</if>
|
||||
<if test="orderByClause != null">
|
||||
order by ${orderByClause}
|
||||
</if>
|
||||
</select>
|
||||
<select id="selectByPrimaryKey" parameterType="java.lang.Long" resultMap="BaseResultMap">
|
||||
select
|
||||
<include refid="Base_Column_List" />
|
||||
from my_plugin
|
||||
where plugin_id = #{pluginId,jdbcType=BIGINT}
|
||||
</select>
|
||||
<delete id="deleteByPrimaryKey" parameterType="java.lang.Long">
|
||||
delete from my_plugin
|
||||
where plugin_id = #{pluginId,jdbcType=BIGINT}
|
||||
</delete>
|
||||
<delete id="deleteByExample" parameterType="io.dataease.base.domain.MyPluginExample">
|
||||
delete from my_plugin
|
||||
<if test="_parameter != null">
|
||||
<include refid="Example_Where_Clause" />
|
||||
</if>
|
||||
</delete>
|
||||
<insert id="insert" parameterType="io.dataease.base.domain.MyPlugin">
|
||||
insert into my_plugin (plugin_id, `name`, `free`,
|
||||
cost, descript, version,
|
||||
install_type, creator, release_time,
|
||||
install_time, module_name, bean_name,
|
||||
icon)
|
||||
values (#{pluginId,jdbcType=BIGINT}, #{name,jdbcType=VARCHAR}, #{free,jdbcType=BIT},
|
||||
#{cost,jdbcType=INTEGER}, #{descript,jdbcType=VARCHAR}, #{version,jdbcType=VARCHAR},
|
||||
#{installType,jdbcType=INTEGER}, #{creator,jdbcType=VARCHAR}, #{releaseTime,jdbcType=BIGINT},
|
||||
#{installTime,jdbcType=BIGINT}, #{moduleName,jdbcType=VARCHAR}, #{beanName,jdbcType=VARCHAR},
|
||||
#{icon,jdbcType=VARCHAR})
|
||||
</insert>
|
||||
<insert id="insertSelective" parameterType="io.dataease.base.domain.MyPlugin">
|
||||
insert into my_plugin
|
||||
<trim prefix="(" suffix=")" suffixOverrides=",">
|
||||
<if test="pluginId != null">
|
||||
plugin_id,
|
||||
</if>
|
||||
<if test="name != null">
|
||||
`name`,
|
||||
</if>
|
||||
<if test="free != null">
|
||||
`free`,
|
||||
</if>
|
||||
<if test="cost != null">
|
||||
cost,
|
||||
</if>
|
||||
<if test="descript != null">
|
||||
descript,
|
||||
</if>
|
||||
<if test="version != null">
|
||||
version,
|
||||
</if>
|
||||
<if test="installType != null">
|
||||
install_type,
|
||||
</if>
|
||||
<if test="creator != null">
|
||||
creator,
|
||||
</if>
|
||||
<if test="releaseTime != null">
|
||||
release_time,
|
||||
</if>
|
||||
<if test="installTime != null">
|
||||
install_time,
|
||||
</if>
|
||||
<if test="moduleName != null">
|
||||
module_name,
|
||||
</if>
|
||||
<if test="beanName != null">
|
||||
bean_name,
|
||||
</if>
|
||||
<if test="icon != null">
|
||||
icon,
|
||||
</if>
|
||||
</trim>
|
||||
<trim prefix="values (" suffix=")" suffixOverrides=",">
|
||||
<if test="pluginId != null">
|
||||
#{pluginId,jdbcType=BIGINT},
|
||||
</if>
|
||||
<if test="name != null">
|
||||
#{name,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="free != null">
|
||||
#{free,jdbcType=BIT},
|
||||
</if>
|
||||
<if test="cost != null">
|
||||
#{cost,jdbcType=INTEGER},
|
||||
</if>
|
||||
<if test="descript != null">
|
||||
#{descript,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="version != null">
|
||||
#{version,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="installType != null">
|
||||
#{installType,jdbcType=INTEGER},
|
||||
</if>
|
||||
<if test="creator != null">
|
||||
#{creator,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="releaseTime != null">
|
||||
#{releaseTime,jdbcType=BIGINT},
|
||||
</if>
|
||||
<if test="installTime != null">
|
||||
#{installTime,jdbcType=BIGINT},
|
||||
</if>
|
||||
<if test="moduleName != null">
|
||||
#{moduleName,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="beanName != null">
|
||||
#{beanName,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="icon != null">
|
||||
#{icon,jdbcType=VARCHAR},
|
||||
</if>
|
||||
</trim>
|
||||
</insert>
|
||||
<select id="countByExample" parameterType="io.dataease.base.domain.MyPluginExample" resultType="java.lang.Long">
|
||||
select count(*) from my_plugin
|
||||
<if test="_parameter != null">
|
||||
<include refid="Example_Where_Clause" />
|
||||
</if>
|
||||
</select>
|
||||
<update id="updateByExampleSelective" parameterType="map">
|
||||
update my_plugin
|
||||
<set>
|
||||
<if test="record.pluginId != null">
|
||||
plugin_id = #{record.pluginId,jdbcType=BIGINT},
|
||||
</if>
|
||||
<if test="record.name != null">
|
||||
`name` = #{record.name,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="record.free != null">
|
||||
`free` = #{record.free,jdbcType=BIT},
|
||||
</if>
|
||||
<if test="record.cost != null">
|
||||
cost = #{record.cost,jdbcType=INTEGER},
|
||||
</if>
|
||||
<if test="record.descript != null">
|
||||
descript = #{record.descript,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="record.version != null">
|
||||
version = #{record.version,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="record.installType != null">
|
||||
install_type = #{record.installType,jdbcType=INTEGER},
|
||||
</if>
|
||||
<if test="record.creator != null">
|
||||
creator = #{record.creator,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="record.releaseTime != null">
|
||||
release_time = #{record.releaseTime,jdbcType=BIGINT},
|
||||
</if>
|
||||
<if test="record.installTime != null">
|
||||
install_time = #{record.installTime,jdbcType=BIGINT},
|
||||
</if>
|
||||
<if test="record.moduleName != null">
|
||||
module_name = #{record.moduleName,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="record.beanName != null">
|
||||
bean_name = #{record.beanName,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="record.icon != null">
|
||||
icon = #{record.icon,jdbcType=VARCHAR},
|
||||
</if>
|
||||
</set>
|
||||
<if test="_parameter != null">
|
||||
<include refid="Update_By_Example_Where_Clause" />
|
||||
</if>
|
||||
</update>
|
||||
<update id="updateByExample" parameterType="map">
|
||||
update my_plugin
|
||||
set plugin_id = #{record.pluginId,jdbcType=BIGINT},
|
||||
`name` = #{record.name,jdbcType=VARCHAR},
|
||||
`free` = #{record.free,jdbcType=BIT},
|
||||
cost = #{record.cost,jdbcType=INTEGER},
|
||||
descript = #{record.descript,jdbcType=VARCHAR},
|
||||
version = #{record.version,jdbcType=VARCHAR},
|
||||
install_type = #{record.installType,jdbcType=INTEGER},
|
||||
creator = #{record.creator,jdbcType=VARCHAR},
|
||||
release_time = #{record.releaseTime,jdbcType=BIGINT},
|
||||
install_time = #{record.installTime,jdbcType=BIGINT},
|
||||
module_name = #{record.moduleName,jdbcType=VARCHAR},
|
||||
bean_name = #{record.beanName,jdbcType=VARCHAR},
|
||||
icon = #{record.icon,jdbcType=VARCHAR}
|
||||
<if test="_parameter != null">
|
||||
<include refid="Update_By_Example_Where_Clause" />
|
||||
</if>
|
||||
</update>
|
||||
<update id="updateByPrimaryKeySelective" parameterType="io.dataease.base.domain.MyPlugin">
|
||||
update my_plugin
|
||||
<set>
|
||||
<if test="name != null">
|
||||
`name` = #{name,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="free != null">
|
||||
`free` = #{free,jdbcType=BIT},
|
||||
</if>
|
||||
<if test="cost != null">
|
||||
cost = #{cost,jdbcType=INTEGER},
|
||||
</if>
|
||||
<if test="descript != null">
|
||||
descript = #{descript,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="version != null">
|
||||
version = #{version,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="installType != null">
|
||||
install_type = #{installType,jdbcType=INTEGER},
|
||||
</if>
|
||||
<if test="creator != null">
|
||||
creator = #{creator,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="releaseTime != null">
|
||||
release_time = #{releaseTime,jdbcType=BIGINT},
|
||||
</if>
|
||||
<if test="installTime != null">
|
||||
install_time = #{installTime,jdbcType=BIGINT},
|
||||
</if>
|
||||
<if test="moduleName != null">
|
||||
module_name = #{moduleName,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="beanName != null">
|
||||
bean_name = #{beanName,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="icon != null">
|
||||
icon = #{icon,jdbcType=VARCHAR},
|
||||
</if>
|
||||
</set>
|
||||
where plugin_id = #{pluginId,jdbcType=BIGINT}
|
||||
</update>
|
||||
<update id="updateByPrimaryKey" parameterType="io.dataease.base.domain.MyPlugin">
|
||||
update my_plugin
|
||||
set `name` = #{name,jdbcType=VARCHAR},
|
||||
`free` = #{free,jdbcType=BIT},
|
||||
cost = #{cost,jdbcType=INTEGER},
|
||||
descript = #{descript,jdbcType=VARCHAR},
|
||||
version = #{version,jdbcType=VARCHAR},
|
||||
install_type = #{installType,jdbcType=INTEGER},
|
||||
creator = #{creator,jdbcType=VARCHAR},
|
||||
release_time = #{releaseTime,jdbcType=BIGINT},
|
||||
install_time = #{installTime,jdbcType=BIGINT},
|
||||
module_name = #{moduleName,jdbcType=VARCHAR},
|
||||
bean_name = #{beanName,jdbcType=VARCHAR},
|
||||
icon = #{icon,jdbcType=VARCHAR}
|
||||
where plugin_id = #{pluginId,jdbcType=BIGINT}
|
||||
</update>
|
||||
</mapper>
|
@ -0,0 +1,11 @@
|
||||
package io.dataease.base.mapper.ext;
|
||||
|
||||
import io.dataease.base.domain.MyPlugin;
|
||||
import io.dataease.base.mapper.ext.query.GridExample;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface ExtSysPluginMapper {
|
||||
|
||||
List<MyPlugin> query(GridExample example);
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
|
||||
<mapper namespace="io.dataease.base.mapper.ext.ExtSysPluginMapper">
|
||||
|
||||
|
||||
|
||||
|
||||
<select id="query" parameterType="io.dataease.base.mapper.ext.query.GridExample" resultMap="io.dataease.base.mapper.MyPluginMapper.BaseResultMap">
|
||||
select *
|
||||
from my_plugin
|
||||
<if test="_parameter != null">
|
||||
<include refid="io.dataease.base.mapper.ext.query.GridSql.gridCondition" />
|
||||
</if>
|
||||
<if test="orderByClause != null">
|
||||
order by ${orderByClause}
|
||||
</if>
|
||||
<if test="orderByClause == null">
|
||||
order by install_time desc
|
||||
</if>
|
||||
|
||||
</select>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</mapper>
|
115
backend/src/main/java/io/dataease/commons/utils/DeFileUtils.java
Normal file
115
backend/src/main/java/io/dataease/commons/utils/DeFileUtils.java
Normal file
@ -0,0 +1,115 @@
|
||||
package io.dataease.commons.utils;
|
||||
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.channels.FileChannel;
|
||||
|
||||
public class DeFileUtils {
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Java文件操作 获取不带扩展名的文件名
|
||||
*/
|
||||
public static String getFileNameNoEx(String filename) {
|
||||
if ((filename != null) && (filename.length() > 0)) {
|
||||
int dot = filename.lastIndexOf('.');
|
||||
if ((dot > -1) && (dot < (filename.length()))) {
|
||||
return filename.substring(0, dot);
|
||||
}
|
||||
}
|
||||
return filename;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取文件扩展名,不带 .
|
||||
*/
|
||||
public static String getExtensionName(String filename) {
|
||||
if ((filename != null) && (filename.length() > 0)) {
|
||||
int dot = filename.lastIndexOf('.');
|
||||
if ((dot > -1) && (dot < (filename.length() - 1))) {
|
||||
return filename.substring(dot + 1);
|
||||
}
|
||||
}
|
||||
return filename;
|
||||
}
|
||||
/**
|
||||
* 将文件名解析成文件的上传路径
|
||||
*/
|
||||
public static File upload(MultipartFile file, String filePath) {
|
||||
String name = getFileNameNoEx(file.getOriginalFilename());
|
||||
String suffix = getExtensionName(file.getOriginalFilename());
|
||||
try {
|
||||
String fileName = name + "." + suffix;
|
||||
String path = filePath + fileName;
|
||||
// getCanonicalFile 可解析正确各种路径
|
||||
File dest = new File(path).getCanonicalFile();
|
||||
// 检测是否存在目录
|
||||
if (!dest.getParentFile().exists()) {
|
||||
if (!dest.getParentFile().mkdirs()) {
|
||||
System.out.println("was not successful.");
|
||||
}
|
||||
}
|
||||
// 文件写入
|
||||
// file.transferTo(dest);
|
||||
FileOutputStream fileOutputStream = new FileOutputStream(dest);
|
||||
fileOutputStream.write(file.getBytes());
|
||||
fileOutputStream.flush();
|
||||
fileOutputStream.close();
|
||||
return dest;
|
||||
} catch (Exception e) {
|
||||
LogUtil.error(e.getMessage(), e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static String copy(File source, String targetDir) throws IOException{
|
||||
String name = source.getName();
|
||||
String destPath = null;
|
||||
if (targetDir.endsWith("/") || targetDir.endsWith("\\")){
|
||||
destPath = targetDir + name;
|
||||
}else{
|
||||
destPath = targetDir + "/" + name;
|
||||
}
|
||||
File DestFile = new File(destPath);
|
||||
if (!DestFile.getParentFile().exists()) {
|
||||
DestFile.getParentFile().mkdirs();
|
||||
}
|
||||
copyFileUsingFileChannels(source, DestFile);
|
||||
return destPath;
|
||||
}
|
||||
|
||||
private static void copyFileUsingFileChannels(File source, File dest) throws IOException {
|
||||
FileChannel inputChannel = null;
|
||||
FileChannel outputChannel = null;
|
||||
try {
|
||||
inputChannel = new FileInputStream(source).getChannel();
|
||||
outputChannel = new FileOutputStream(dest).getChannel();
|
||||
outputChannel.transferFrom(inputChannel, 0, inputChannel.size());
|
||||
} finally {
|
||||
inputChannel.close();
|
||||
outputChannel.close();
|
||||
}
|
||||
}
|
||||
|
||||
public static String readJson(File file) {
|
||||
String str = null;
|
||||
try {
|
||||
FileReader fileReader = new FileReader(file);
|
||||
Reader reader = new InputStreamReader(new FileInputStream(file), "utf-8");
|
||||
int ch=0;
|
||||
StringBuffer sb = new StringBuffer();
|
||||
while ((ch = reader.read()) != -1) {
|
||||
sb.append((char) ch);
|
||||
}
|
||||
fileReader.close();
|
||||
reader.close();
|
||||
str = sb.toString();
|
||||
return str;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
141
backend/src/main/java/io/dataease/commons/utils/ZipUtils.java
Normal file
141
backend/src/main/java/io/dataease/commons/utils/ZipUtils.java
Normal file
@ -0,0 +1,141 @@
|
||||
package io.dataease.commons.utils;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.Enumeration;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipException;
|
||||
import java.util.zip.ZipFile;
|
||||
import java.util.zip.ZipInputStream;
|
||||
|
||||
public class ZipUtils {
|
||||
|
||||
|
||||
/**
|
||||
* 解压文件
|
||||
*
|
||||
* @param zipFilePath 解压文件路径
|
||||
* @param outputFolder 输出解压文件路径
|
||||
*/
|
||||
public static void unZipIt(String zipFilePath, String outputFolder) {
|
||||
byte[] buffer = new byte[1024];
|
||||
|
||||
File folder = new File(outputFolder);
|
||||
if (!folder.exists()) {
|
||||
folder.mkdir();
|
||||
}
|
||||
try {
|
||||
//get the zip file content
|
||||
ZipInputStream zis = new ZipInputStream(new FileInputStream(zipFilePath));
|
||||
ZipEntry ze = zis.getNextEntry();
|
||||
while (ze != null) {
|
||||
String fileName = ze.getName();
|
||||
File newFile = new File(outputFolder + File.separator + fileName);
|
||||
System.out.println("file unzip : " + newFile.getAbsoluteFile());
|
||||
//大部分网络上的源码,这里没有判断子目录
|
||||
if (ze.isDirectory()) {
|
||||
if (!newFile.mkdirs()) {
|
||||
System.out.println("was not successful.");
|
||||
}
|
||||
} else {
|
||||
if (!new File(newFile.getParent()).mkdirs()) {
|
||||
System.out.println("was not successful.");
|
||||
}
|
||||
FileOutputStream fos = new FileOutputStream(newFile);
|
||||
int len;
|
||||
while ((len = zis.read(buffer)) != -1) {
|
||||
fos.write(buffer, 0, len);
|
||||
}
|
||||
fos.close();
|
||||
}
|
||||
ze = zis.getNextEntry();
|
||||
}
|
||||
zis.closeEntry();
|
||||
zis.close();
|
||||
System.out.println("Done");
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static void unzip(File source, String out) throws IOException {
|
||||
try (ZipInputStream zis = new ZipInputStream(new FileInputStream(source))) {
|
||||
|
||||
ZipEntry entry = zis.getNextEntry();
|
||||
|
||||
while (entry != null) {
|
||||
|
||||
File file = new File(out, entry.getName());
|
||||
|
||||
if (entry.isDirectory()) {
|
||||
if (!file.mkdirs()) {
|
||||
System.out.println("was not successful.");
|
||||
}
|
||||
} else {
|
||||
File parent = file.getParentFile();
|
||||
|
||||
if (!parent.exists()) {
|
||||
if (!parent.mkdirs()) {
|
||||
System.out.println("was not successful.");
|
||||
}
|
||||
}
|
||||
|
||||
try (BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file))) {
|
||||
|
||||
byte[] buffer = new byte[Math.toIntExact(entry.getSize())];
|
||||
|
||||
int location;
|
||||
|
||||
while ((location = zis.read(buffer)) != -1) {
|
||||
bos.write(buffer, 0, location);
|
||||
}
|
||||
}
|
||||
}
|
||||
entry = zis.getNextEntry();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 把所有文件都直接解压到指定目录(忽略子文件夹)
|
||||
*
|
||||
* @param zipFile
|
||||
* @param folderPath
|
||||
* @throws ZipException
|
||||
* @throws IOException
|
||||
*/
|
||||
public static void upZipFile(File zipFile, String folderPath) throws ZipException, IOException {
|
||||
File desDir = new File(folderPath);
|
||||
if (!desDir.exists()) {
|
||||
if (!desDir.mkdirs()) {
|
||||
System.out.println("was not successful.");
|
||||
}
|
||||
}
|
||||
ZipFile zf = new ZipFile(zipFile);
|
||||
for (Enumeration<?> entries = zf.entries(); entries.hasMoreElements(); ) {
|
||||
ZipEntry entry = ((ZipEntry) entries.nextElement());
|
||||
InputStream in = zf.getInputStream(entry);
|
||||
File desFile = new File(folderPath, java.net.URLEncoder.encode(entry.getName(), "UTF-8"));
|
||||
|
||||
if (!desFile.exists()) {
|
||||
File fileParentDir = desFile.getParentFile();
|
||||
if (!fileParentDir.exists()) {
|
||||
if (!fileParentDir.mkdirs()) {
|
||||
System.out.println("was not successful.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
OutputStream out = new FileOutputStream(desFile);
|
||||
byte[] buffer = new byte[1024 * 1024];
|
||||
int realLength = in.read(buffer);
|
||||
while (realLength != -1) {
|
||||
out.write(buffer, 0, realLength);
|
||||
realLength = in.read(buffer);
|
||||
}
|
||||
|
||||
out.close();
|
||||
in.close();
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
package io.dataease.controller.sys;
|
||||
|
||||
import com.github.pagehelper.Page;
|
||||
import com.github.pagehelper.PageHelper;
|
||||
import io.dataease.base.domain.MyPlugin;
|
||||
import io.dataease.commons.utils.PageUtils;
|
||||
import io.dataease.commons.utils.Pager;
|
||||
import io.dataease.controller.sys.base.BaseGridRequest;
|
||||
import io.dataease.service.sys.PluginService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
@RestController
|
||||
@Api(tags = "系统:插件管理")
|
||||
@RequestMapping("/api/plugin")
|
||||
public class SysPluginController {
|
||||
|
||||
@Autowired
|
||||
private PluginService pluginService;
|
||||
|
||||
@ApiOperation("查询已安装插件")
|
||||
@PostMapping("/pluginGrid/{goPage}/{pageSize}")
|
||||
public Pager<List<MyPlugin>> pluginGrid(@PathVariable int goPage, @PathVariable int pageSize, @RequestBody BaseGridRequest request) {
|
||||
Page<Object> page = PageHelper.startPage(goPage, pageSize, true);
|
||||
return PageUtils.setPageInfo(page, pluginService.query(request));
|
||||
}
|
||||
|
||||
@PostMapping("upload")
|
||||
public Map<String, Object> localUpload(@RequestParam("file") MultipartFile file) throws Exception {
|
||||
return pluginService.localInstall(file);
|
||||
}
|
||||
}
|
@ -17,6 +17,8 @@ public class ChartViewFieldDTO implements Serializable {
|
||||
|
||||
private String originName;
|
||||
|
||||
private String dataeaseName;
|
||||
|
||||
private String name;
|
||||
|
||||
private String type;
|
||||
|
@ -0,0 +1,51 @@
|
||||
package io.dataease.plugins.config;
|
||||
|
||||
import io.dataease.plugins.loader.ClassloaderResponsity;
|
||||
import io.dataease.plugins.loader.ModuleClassLoader;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Component
|
||||
public class LoadjarUtil {
|
||||
|
||||
public List<?> loadJar(String jarPath){
|
||||
File jar = new File(jarPath);
|
||||
URI uri = jar.toURI();
|
||||
String moduleName = jarPath.substring(jarPath.lastIndexOf("/")+1,jarPath.lastIndexOf("."));
|
||||
try {
|
||||
|
||||
if(ClassloaderResponsity.getInstance().containsClassLoader(moduleName)){
|
||||
ClassloaderResponsity.getInstance().removeClassLoader(moduleName);
|
||||
}
|
||||
|
||||
ModuleClassLoader classLoader = new ModuleClassLoader(new URL[]{uri.toURL()}, Thread.currentThread().getContextClassLoader());
|
||||
SpringContextUtil.getBeanFactory().setBeanClassLoader(classLoader);
|
||||
Thread.currentThread().setContextClassLoader(classLoader);
|
||||
classLoader.initBean();
|
||||
ClassloaderResponsity.getInstance().addClassLoader(moduleName,classLoader);
|
||||
|
||||
} catch (MalformedURLException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return SpringContextUtil.getAllBean();
|
||||
}
|
||||
|
||||
public List<Map<String, Object>> deleteModule(String moduleName){
|
||||
if(ClassloaderResponsity.getInstance().containsClassLoader(moduleName)){
|
||||
ClassloaderResponsity.getInstance().removeClassLoader(moduleName);
|
||||
}
|
||||
return beans();
|
||||
}
|
||||
public List<Map<String, Object>> beans(){
|
||||
return SpringContextUtil.getAllBean();
|
||||
}
|
||||
}
|
@ -0,0 +1,85 @@
|
||||
package io.dataease.plugins.config;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Component
|
||||
public class SpringContextUtil implements ApplicationContextAware {
|
||||
|
||||
//获取bean工厂,用来实现动态注入bean
|
||||
//不能使用其他类加载器加载bean
|
||||
//否则会出现异常:类未找到,类未定义
|
||||
public static DefaultListableBeanFactory getBeanFactory(){
|
||||
return (DefaultListableBeanFactory) getApplicationContext().getAutowireCapableBeanFactory();
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static List<Map<String, Object>> getAllBean() {
|
||||
|
||||
|
||||
List<Map<String, Object>> list = new ArrayList<>();
|
||||
|
||||
|
||||
String[] beans = getApplicationContext()
|
||||
.getBeanDefinitionNames();
|
||||
|
||||
for (String beanName : beans) {
|
||||
Class<?> beanType = getApplicationContext()
|
||||
.getType(beanName);
|
||||
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
|
||||
map.put("BeanName", beanName);
|
||||
map.put("beanType", beanType);
|
||||
map.put("package", beanType.getPackage());
|
||||
list.add(map);
|
||||
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 上下文对象实例
|
||||
*/
|
||||
private static ApplicationContext applicationContext;
|
||||
|
||||
|
||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
||||
this.applicationContext = applicationContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取applicationContext
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static ApplicationContext getApplicationContext() {
|
||||
return applicationContext;
|
||||
}
|
||||
|
||||
|
||||
public static Object getBean(String name) {
|
||||
return getApplicationContext().getBean(name);
|
||||
}
|
||||
|
||||
public static <T> T getBean(Class<T> clazz) {
|
||||
return getApplicationContext().getBean(clazz);
|
||||
}
|
||||
|
||||
public static <T> T getBean(String name, Class<T> clazz) {
|
||||
return getApplicationContext().getBean(name, clazz);
|
||||
}
|
||||
}
|
@ -0,0 +1,65 @@
|
||||
package io.dataease.plugins.loader;
|
||||
|
||||
import io.dataease.plugins.config.SpringContextUtil;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public class ClassloaderResponsity {
|
||||
|
||||
|
||||
private static Logger logger = LoggerFactory.getLogger(ClassloaderResponsity.class);
|
||||
|
||||
private ClassloaderResponsity(){}
|
||||
|
||||
|
||||
private Map<String,ModuleClassLoader> responsityMap = new ConcurrentHashMap<>();
|
||||
|
||||
|
||||
|
||||
public void addClassLoader(String moduleName,ModuleClassLoader moduleClassLoader){
|
||||
responsityMap.put(moduleName,moduleClassLoader);
|
||||
}
|
||||
|
||||
public boolean containsClassLoader(String key){
|
||||
return responsityMap.containsKey(key);
|
||||
}
|
||||
|
||||
public ModuleClassLoader getClassLoader(String key){
|
||||
return responsityMap.get(key);
|
||||
}
|
||||
|
||||
public void removeClassLoader(String moduleName){
|
||||
ModuleClassLoader moduleClassLoader = responsityMap.get(moduleName);
|
||||
try {
|
||||
List<String> registeredBean = moduleClassLoader.getRegisteredBean();
|
||||
|
||||
for (String beanName : registeredBean) {
|
||||
logger.info("删除bean:"+beanName);
|
||||
SpringContextUtil.getBeanFactory().removeBeanDefinition(beanName);
|
||||
}
|
||||
|
||||
moduleClassLoader.close();
|
||||
responsityMap.remove(moduleName);
|
||||
|
||||
} catch (IOException e) {
|
||||
logger.error("删除"+moduleName+"模块发生错误");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
private static class ClassloaderResponsityHodler{
|
||||
private static ClassloaderResponsity instamce = new ClassloaderResponsity();
|
||||
}
|
||||
|
||||
public static ClassloaderResponsity getInstance(){
|
||||
return ClassloaderResponsityHodler.instamce;
|
||||
}
|
||||
}
|
@ -0,0 +1,189 @@
|
||||
package io.dataease.plugins.loader;
|
||||
|
||||
import io.dataease.plugins.config.SpringContextUtil;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.stereotype.Repository;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.StringUtils;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.util.*;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarFile;
|
||||
|
||||
public class ModuleClassLoader extends URLClassLoader {
|
||||
|
||||
//属于本类加载器加载的jar包
|
||||
private JarFile jarFile;
|
||||
|
||||
//保存已经加载过的Class对象
|
||||
private Map<String,Class> cacheClassMap = new HashMap<>();
|
||||
|
||||
//保存本类加载器加载的class字节码
|
||||
private Map<String,byte[]> classBytesMap = new HashMap<>();
|
||||
|
||||
//需要注册的spring bean的name集合
|
||||
private List<String> registeredBean = new ArrayList<>();
|
||||
|
||||
|
||||
//构造
|
||||
public ModuleClassLoader(URL[] urls, ClassLoader parent) {
|
||||
super(urls, parent);
|
||||
URL url = urls[0];
|
||||
String path = url.getPath();
|
||||
try {
|
||||
jarFile = new JarFile(path);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
//初始化类加载器执行类加载
|
||||
init();
|
||||
}
|
||||
|
||||
|
||||
|
||||
//重写loadClass方法
|
||||
//改写loadClass方式
|
||||
@Override
|
||||
public Class<?> loadClass(String name) throws ClassNotFoundException {
|
||||
if(findLoadedClass(name)==null){
|
||||
return super.loadClass(name);
|
||||
}else{
|
||||
return cacheClassMap.get(name);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 方法描述 初始化类加载器,保存字节码
|
||||
* @method init
|
||||
*/
|
||||
private void init() {
|
||||
|
||||
//解析jar包每一项
|
||||
Enumeration<JarEntry> en = jarFile.entries();
|
||||
InputStream input = null;
|
||||
try{
|
||||
while (en.hasMoreElements()) {
|
||||
JarEntry je = en.nextElement();
|
||||
String name = je.getName();
|
||||
//这里添加了路径扫描限制
|
||||
if (name.endsWith(".class")) {
|
||||
String className = name.replace(".class", "").replaceAll("/", ".");
|
||||
input = jarFile.getInputStream(je);
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
int bufferSize = 4096;
|
||||
byte[] buffer = new byte[bufferSize];
|
||||
int bytesNumRead = 0;
|
||||
while ((bytesNumRead = input.read(buffer)) != -1) {
|
||||
baos.write(buffer, 0, bytesNumRead);
|
||||
}
|
||||
byte[] classBytes = baos.toByteArray();
|
||||
classBytesMap.put(className,classBytes);
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
if(input!=null){
|
||||
try {
|
||||
input.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//将jar中的每一个class字节码进行Class载入
|
||||
for (Map.Entry<String, byte[]> entry : classBytesMap.entrySet()) {
|
||||
String key = entry.getKey();
|
||||
Class<?> aClass = null;
|
||||
try {
|
||||
aClass = loadClass(key);
|
||||
} catch (ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
cacheClassMap.put(key,aClass);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 方法描述 初始化spring bean
|
||||
* @method initBean
|
||||
*/
|
||||
public void initBean(){
|
||||
for (Map.Entry<String, Class> entry : cacheClassMap.entrySet()) {
|
||||
String className = entry.getKey();
|
||||
Class<?> cla = entry.getValue();
|
||||
if(isSpringBeanClass(cla)){
|
||||
BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(cla);
|
||||
BeanDefinition beanDefinition = beanDefinitionBuilder.getRawBeanDefinition();
|
||||
//设置当前bean定义对象是单利的
|
||||
beanDefinition.setScope("singleton");
|
||||
|
||||
//将变量首字母置小写
|
||||
String beanName = StringUtils.uncapitalize(className);
|
||||
|
||||
beanName = beanName.substring(beanName.lastIndexOf(".")+1);
|
||||
beanName = StringUtils.uncapitalize(beanName);
|
||||
|
||||
SpringContextUtil.getBeanFactory().registerBeanDefinition(beanName,beanDefinition);
|
||||
registeredBean.add(beanName);
|
||||
System.out.println("注册bean:"+beanName);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//获取当前类加载器注册的bean
|
||||
//在移除当前类加载器的时候需要手动删除这些注册的bean
|
||||
public List<String> getRegisteredBean() {
|
||||
return registeredBean;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 方法描述 判断class对象是否带有spring的注解
|
||||
* @method isSpringBeanClass
|
||||
* @param cla jar中的每一个class
|
||||
* @return true 是spring bean false 不是spring bean
|
||||
*/
|
||||
public boolean isSpringBeanClass(Class<?> cla){
|
||||
if(cla==null){
|
||||
return false;
|
||||
}
|
||||
//是否是接口
|
||||
if(cla.isInterface()){
|
||||
return false;
|
||||
}
|
||||
|
||||
//是否是抽象类
|
||||
if( Modifier.isAbstract(cla.getModifiers())){
|
||||
return false;
|
||||
}
|
||||
|
||||
if(cla.getAnnotation(Component.class)!=null){
|
||||
return true;
|
||||
}
|
||||
if(cla.getAnnotation(Repository.class)!=null){
|
||||
return true;
|
||||
}
|
||||
if(cla.getAnnotation(Service.class)!=null){
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
@ -150,7 +150,7 @@ public class ChartViewService {
|
||||
// data = sparkCalc.getData(table.getId(), fields, xAxis, yAxis, "tmp_" + view.getId().split("-")[0], extFilterList);
|
||||
|
||||
// 连接doris,构建doris数据源查询
|
||||
Datasource ds = (Datasource) CommonBeanFactory.getBean("DorisDatasource");
|
||||
Datasource ds = (Datasource) CommonBeanFactory.getBean("DorisDatasource");
|
||||
DatasourceProvider datasourceProvider = ProviderFactory.getProvider(ds.getType());
|
||||
DatasourceRequest datasourceRequest = new DatasourceRequest();
|
||||
datasourceRequest.setDatasource(ds);
|
||||
@ -199,9 +199,9 @@ public class ChartViewService {
|
||||
for (int i = 0; i < fields.size(); i++) {
|
||||
ChartViewFieldDTO chartViewFieldDTO = fields.get(i);
|
||||
if (chartViewFieldDTO.getDeType() == 0 || chartViewFieldDTO.getDeType() == 1) {
|
||||
d.put(fields.get(i).getOriginName(), ele[i]);
|
||||
d.put(fields.get(i).getDataeaseName(), ele[i]);
|
||||
} else if (chartViewFieldDTO.getDeType() == 2 || chartViewFieldDTO.getDeType() == 3) {
|
||||
d.put(fields.get(i).getOriginName(), new BigDecimal(ele[i]).setScale(2, RoundingMode.HALF_UP));
|
||||
d.put(fields.get(i).getDataeaseName(), new BigDecimal(ele[i]).setScale(2, RoundingMode.HALF_UP));
|
||||
}
|
||||
}
|
||||
tableRow.add(d);
|
||||
@ -231,7 +231,7 @@ public class ChartViewService {
|
||||
}
|
||||
DatasetTableField field = request.getDatasetTableField();
|
||||
filter.append(" AND ")
|
||||
.append(field.getOriginName())
|
||||
.append(field.getDataeaseName())
|
||||
.append(" ")
|
||||
.append(transMysqlFilterTerm(request.getOperator()))
|
||||
.append(" ");
|
||||
@ -259,12 +259,12 @@ public class ChartViewService {
|
||||
|
||||
public String transMysqlSQL(String table, List<ChartViewFieldDTO> xAxis, List<ChartViewFieldDTO> yAxis, List<ChartExtFilterRequest> extFilterRequestList) {
|
||||
// 字段汇总 排序等
|
||||
String[] field = yAxis.stream().map(y -> "CAST(" + y.getSummary() + "(" + y.getOriginName() + ") AS DECIMAL(20,2)) AS _" + y.getSummary() + "_" + (StringUtils.equalsIgnoreCase(y.getOriginName(), "*") ? "" : y.getOriginName())).toArray(String[]::new);
|
||||
String[] group = xAxis.stream().map(ChartViewFieldDTO::getOriginName).toArray(String[]::new);
|
||||
String[] field = yAxis.stream().map(y -> "CAST(" + y.getSummary() + "(" + y.getDataeaseName() + ") AS " + (y.getDeType() == 2 ? "DECIMAL(20,0)" : "DECIMAL(20,2)") + ") AS _" + y.getSummary() + "_" + (StringUtils.equalsIgnoreCase(y.getDataeaseName(), "*") ? "" : y.getDataeaseName())).toArray(String[]::new);
|
||||
String[] group = xAxis.stream().map(ChartViewFieldDTO::getDataeaseName).toArray(String[]::new);
|
||||
String[] xOrder = xAxis.stream().filter(f -> StringUtils.isNotEmpty(f.getSort()) && !StringUtils.equalsIgnoreCase(f.getSort(), "none"))
|
||||
.map(f -> f.getOriginName() + " " + f.getSort()).toArray(String[]::new);
|
||||
.map(f -> f.getDataeaseName() + " " + f.getSort()).toArray(String[]::new);
|
||||
String[] yOrder = yAxis.stream().filter(f -> StringUtils.isNotEmpty(f.getSort()) && !StringUtils.equalsIgnoreCase(f.getSort(), "none"))
|
||||
.map(f -> "_" + f.getSummary() + "_" + (StringUtils.equalsIgnoreCase(f.getOriginName(), "*") ? "" : f.getOriginName()) + " " + f.getSort()).toArray(String[]::new);
|
||||
.map(f -> "_" + f.getSummary() + "_" + (StringUtils.equalsIgnoreCase(f.getDataeaseName(), "*") ? "" : f.getDataeaseName()) + " " + f.getSort()).toArray(String[]::new);
|
||||
String[] order = Arrays.copyOf(xOrder, xOrder.length + yOrder.length);
|
||||
System.arraycopy(yOrder, 0, order, xOrder.length, yOrder.length);
|
||||
|
||||
@ -272,7 +272,7 @@ public class ChartViewService {
|
||||
.map(x -> {
|
||||
String[] s = x.getFilter().stream().map(f -> {
|
||||
StringBuilder filter = new StringBuilder();
|
||||
filter.append(" AND ").append(x.getOriginName()).append(transMysqlFilterTerm(f.getTerm()));
|
||||
filter.append(" AND ").append(x.getDataeaseName()).append(transMysqlFilterTerm(f.getTerm()));
|
||||
if (StringUtils.containsIgnoreCase(f.getTerm(), "null")) {
|
||||
} else if (StringUtils.containsIgnoreCase(f.getTerm(), "in")) {
|
||||
filter.append("('").append(StringUtils.join(f.getValue(), "','")).append("')");
|
||||
@ -301,7 +301,7 @@ public class ChartViewService {
|
||||
.map(y -> {
|
||||
String[] s = y.getFilter().stream().map(f -> {
|
||||
StringBuilder filter = new StringBuilder();
|
||||
filter.append(" AND _").append(y.getSummary()).append("_").append(StringUtils.equalsIgnoreCase(y.getOriginName(), "*") ? "" : y.getOriginName()).append(transMysqlFilterTerm(f.getTerm()));
|
||||
filter.append(" AND _").append(y.getSummary()).append("_").append(StringUtils.equalsIgnoreCase(y.getDataeaseName(), "*") ? "" : y.getDataeaseName()).append(transMysqlFilterTerm(f.getTerm()));
|
||||
if (StringUtils.containsIgnoreCase(f.getTerm(), "null")) {
|
||||
} else if (StringUtils.containsIgnoreCase(f.getTerm(), "in")) {
|
||||
filter.append("('").append(StringUtils.join(f.getValue(), "','")).append("')");
|
||||
|
@ -74,6 +74,11 @@ public class DataSetTableService {
|
||||
|
||||
public DatasetTable save(DatasetTable datasetTable) throws Exception {
|
||||
checkName(datasetTable);
|
||||
if (StringUtils.equalsIgnoreCase(datasetTable.getType(), "sql")) {
|
||||
DataSetTableRequest dataSetTableRequest = new DataSetTableRequest();
|
||||
BeanUtils.copyBean(dataSetTableRequest, datasetTable);
|
||||
getSQLPreview(dataSetTableRequest);
|
||||
}
|
||||
if (StringUtils.isEmpty(datasetTable.getId())) {
|
||||
datasetTable.setId(UUID.randomUUID().toString());
|
||||
datasetTable.setCreateBy(AuthUtils.getUser().getUsername());
|
||||
@ -163,6 +168,7 @@ public class DataSetTableService {
|
||||
.tableId(dataSetTableRequest.getId())
|
||||
.originName("*")
|
||||
.name("记录数*")
|
||||
.dataeaseName("*")
|
||||
.type("INT")
|
||||
.checked(true)
|
||||
.columnIndex(999)
|
||||
@ -221,7 +227,7 @@ public class DataSetTableService {
|
||||
|
||||
String table = dataTableInfoDTO.getTable();
|
||||
datasourceRequest.setQuery(createQuerySQL(ds.getType(), table, fieldArray) + " LIMIT " + (page - 1) * pageSize + "," + realSize);
|
||||
|
||||
LogUtil.info(datasourceRequest.getQuery());
|
||||
try {
|
||||
data.addAll(datasourceProvider.getData(datasourceRequest));
|
||||
} catch (Exception e) {
|
||||
@ -241,7 +247,7 @@ public class DataSetTableService {
|
||||
|
||||
String sql = dataTableInfoDTO.getSql();
|
||||
datasourceRequest.setQuery(createQuerySQL(ds.getType(), " (" + sql + ") AS tmp ", fieldArray) + " LIMIT " + (page - 1) * pageSize + "," + realSize);
|
||||
|
||||
LogUtil.info(datasourceRequest.getQuery());
|
||||
try {
|
||||
data.addAll(datasourceProvider.getData(datasourceRequest));
|
||||
} catch (Exception e) {
|
||||
@ -260,7 +266,7 @@ public class DataSetTableService {
|
||||
datasourceRequest.setDatasource(ds);
|
||||
String table = DorisTableUtils.dorisName(dataSetTableRequest.getId());
|
||||
datasourceRequest.setQuery(createQuerySQL(ds.getType(), table, fieldArray) + " LIMIT " + (page - 1) * pageSize + "," + realSize);
|
||||
|
||||
LogUtil.info(datasourceRequest.getQuery());
|
||||
try {
|
||||
data.addAll(jdbcProvider.getData(datasourceRequest));
|
||||
} catch (Exception e) {
|
||||
@ -280,7 +286,7 @@ public class DataSetTableService {
|
||||
datasourceRequest.setDatasource(ds);
|
||||
String table = DorisTableUtils.dorisName(dataSetTableRequest.getId());
|
||||
datasourceRequest.setQuery(createQuerySQL(ds.getType(), table, fieldArray) + " LIMIT " + (page - 1) * pageSize + "," + realSize);
|
||||
|
||||
LogUtil.info(datasourceRequest.getQuery());
|
||||
try {
|
||||
data.addAll(jdbcProvider.getData(datasourceRequest));
|
||||
} catch (Exception e) {
|
||||
@ -320,7 +326,11 @@ public class DataSetTableService {
|
||||
DatasourceRequest datasourceRequest = new DatasourceRequest();
|
||||
datasourceRequest.setDatasource(ds);
|
||||
String sql = new Gson().fromJson(dataSetTableRequest.getInfo(), DataTableInfoDTO.class).getSql();
|
||||
datasourceRequest.setQuery("SELECT * FROM (" + sql + ") AS tmp LIMIT 0,1000");
|
||||
// 使用输入的sql先预执行一次,并拿到所有字段
|
||||
datasourceRequest.setQuery(sql);
|
||||
List<TableFiled> previewFields = datasourceProvider.fetchResultField(datasourceRequest);
|
||||
// 正式执行
|
||||
datasourceRequest.setQuery("SELECT * FROM (" + sql + ") AS tmp ORDER BY " + previewFields.get(0).getFieldName() + " LIMIT 0,1000");
|
||||
Map<String, List> result = datasourceProvider.fetchResultAndField(datasourceRequest);
|
||||
List<String[]> data = result.get("dataList");
|
||||
List<TableFiled> fields = result.get("fieldList");
|
||||
@ -353,8 +363,12 @@ public class DataSetTableService {
|
||||
|
||||
DataTableInfoDTO dataTableInfoDTO = new Gson().fromJson(dataSetTableRequest.getInfo(), DataTableInfoDTO.class);
|
||||
List<DataSetTableUnionDTO> list = dataSetTableUnionService.listByTableId(dataTableInfoDTO.getList().get(0).getTableId());
|
||||
String sql = getCustomSQL(dataTableInfoDTO, list);
|
||||
// 使用输入的sql先预执行一次,并拿到所有字段
|
||||
datasourceRequest.setQuery(sql);
|
||||
List<TableFiled> previewFields = jdbcProvider.fetchResultField(datasourceRequest);
|
||||
|
||||
datasourceRequest.setQuery(getCustomSQL(dataTableInfoDTO, list));
|
||||
datasourceRequest.setQuery("SELECT * FROM (" + sql + ") AS tmp ORDER BY " + previewFields.get(0).getFieldName() + " LIMIT 0,1000");
|
||||
Map<String, List> result = jdbcProvider.fetchResultAndField(datasourceRequest);
|
||||
List<String[]> data = result.get("dataList");
|
||||
List<TableFiled> fields = result.get("fieldList");
|
||||
@ -543,11 +557,11 @@ public class DataSetTableService {
|
||||
DatasourceTypes datasourceType = DatasourceTypes.valueOf(type);
|
||||
switch (datasourceType) {
|
||||
case mysql:
|
||||
return MessageFormat.format("SELECT {0} FROM {1}", StringUtils.join(fields, ","), table);
|
||||
return MessageFormat.format("SELECT {0} FROM {1} ORDER BY " + (fields.length > 0 ? fields[0] : "null"), StringUtils.join(fields, ","), table);
|
||||
case sqlServer:
|
||||
return MessageFormat.format("SELECT {0} FROM {1}", StringUtils.join(fields, ","), table);
|
||||
return MessageFormat.format("SELECT {0} FROM {1} ORDER BY " + (fields.length > 0 ? fields[0] : "null"), StringUtils.join(fields, ","), table);
|
||||
default:
|
||||
return MessageFormat.format("SELECT {0} FROM {1}", StringUtils.join(fields, ","), table);
|
||||
return MessageFormat.format("SELECT {0} FROM {1} ORDER BY " + (fields.length > 0 ? fields[0] : "null"), StringUtils.join(fields, ","), table);
|
||||
}
|
||||
}
|
||||
|
||||
|
134
backend/src/main/java/io/dataease/service/sys/PluginService.java
Normal file
134
backend/src/main/java/io/dataease/service/sys/PluginService.java
Normal file
@ -0,0 +1,134 @@
|
||||
package io.dataease.service.sys;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import io.dataease.base.domain.MyPlugin;
|
||||
import io.dataease.base.mapper.MyPluginMapper;
|
||||
import io.dataease.base.mapper.ext.ExtSysPluginMapper;
|
||||
import io.dataease.base.mapper.ext.query.GridExample;
|
||||
import io.dataease.commons.utils.BeanUtils;
|
||||
import io.dataease.commons.utils.DeFileUtils;
|
||||
import io.dataease.commons.utils.ZipUtils;
|
||||
import io.dataease.controller.sys.base.BaseGridRequest;
|
||||
import io.dataease.plugins.config.LoadjarUtil;
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
@Service
|
||||
public class PluginService {
|
||||
|
||||
@Value("${dataease.plugin.dir:/opt/dataease/plugins/}")
|
||||
private String pluginDir;
|
||||
|
||||
private final static String pluginJsonName = "plugin.json";
|
||||
|
||||
@Resource
|
||||
private ExtSysPluginMapper extSysPluginMapper;
|
||||
|
||||
@Resource
|
||||
private MyPluginMapper myPluginMapper;
|
||||
|
||||
@Resource
|
||||
private LoadjarUtil loadjarUtil;
|
||||
|
||||
public List<MyPlugin> query(BaseGridRequest request) {
|
||||
GridExample gridExample = request.convertExample();
|
||||
List<MyPlugin> results = extSysPluginMapper.query(gridExample);
|
||||
return results;
|
||||
}
|
||||
|
||||
/**
|
||||
* 从本地安装处插件
|
||||
* @param file
|
||||
* @return
|
||||
*/
|
||||
public Map<String, Object> localInstall(MultipartFile file) {
|
||||
//1.上传文件到服务器pluginDir目录下
|
||||
File dest = DeFileUtils.upload(file, pluginDir+"temp/");
|
||||
//2.解压目标文件dest 得到plugin.json和jar
|
||||
String folder = pluginDir+"folder/";
|
||||
try {
|
||||
ZipUtils.upZipFile(dest, folder);
|
||||
} catch (IOException e) {
|
||||
// 需要删除文件
|
||||
e.printStackTrace();
|
||||
}
|
||||
//3.解析plugin.json 失败则 直接返回错误 删除文件
|
||||
File folderFile = new File(folder);
|
||||
File[] jsonFiles = folderFile.listFiles(this::isPluginJson);
|
||||
if (ArrayUtils.isEmpty(jsonFiles)) {
|
||||
throw new RuntimeException("缺少插件描述文件");
|
||||
}
|
||||
MyPlugin myPlugin = formatJsonFile(jsonFiles[0]);
|
||||
//4.加载jar包 失败则 直接返回错误 删除文件
|
||||
File[] jarFiles = folderFile.listFiles(this::isPluginJar);
|
||||
if (ArrayUtils.isEmpty(jarFiles)) {
|
||||
throw new RuntimeException("缺少插件jar文件");
|
||||
}
|
||||
File jarFile = jarFiles[0];
|
||||
String jarRoot = pluginDir+"jar/";
|
||||
String jarPath = null;
|
||||
try {
|
||||
jarPath = DeFileUtils.copy(jarFile, jarRoot);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
loadjarUtil.loadJar(jarPath);
|
||||
//5.写表到my_plugin
|
||||
myPlugin.setPluginId(0L);
|
||||
myPluginMapper.insert(myPlugin);
|
||||
return null;
|
||||
}
|
||||
|
||||
//判断当前文件是否实插件描述文件
|
||||
//文件名称必须plugin.json
|
||||
private boolean isPluginJson(File file) {
|
||||
return StringUtils.equals(file.getName(), pluginJsonName);
|
||||
}
|
||||
|
||||
private boolean isPluginJar(File file) {
|
||||
String name = file.getName();
|
||||
return StringUtils.equals(DeFileUtils.getExtensionName(name), "jar");
|
||||
}
|
||||
|
||||
/**
|
||||
* 从plugin.json文件反序列化为MyPlugin实例对象
|
||||
* @return
|
||||
*/
|
||||
private MyPlugin formatJsonFile(File file) {
|
||||
String str = DeFileUtils.readJson(file);
|
||||
Gson gson = new Gson();
|
||||
Map<String, Object> myPlugin = gson.fromJson(str, Map.class);
|
||||
myPlugin.put("free", (Double)myPlugin.get("free") > 0.0);
|
||||
MyPlugin result = new MyPlugin();
|
||||
try {
|
||||
org.apache.commons.beanutils.BeanUtils.populate(result, myPlugin);
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
} catch (InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
//BeanUtils.copyBean(result, myPlugin);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 从插件商城远程安装插件
|
||||
* 2.0版本实现
|
||||
* @param params
|
||||
* @return
|
||||
*/
|
||||
public Map<String, Object> remoteInstall(Map<String, Object> params) {
|
||||
return null;
|
||||
}
|
||||
}
|
@ -239,3 +239,35 @@ INSERT INTO `sys_users_roles` VALUES (19, 4);
|
||||
COMMIT;
|
||||
|
||||
SET FOREIGN_KEY_CHECKS = 1;
|
||||
|
||||
SET NAMES utf8mb4;
|
||||
SET FOREIGN_KEY_CHECKS = 0;
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for my_plugin
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `my_plugin`;
|
||||
CREATE TABLE `my_plugin` (
|
||||
`plugin_id` bigint(20) NOT NULL COMMENT '主键',
|
||||
`name` varchar(255) DEFAULT NULL COMMENT '插件名称',
|
||||
`free` tinyint(1) DEFAULT NULL COMMENT '是否免费',
|
||||
`cost` int(10) DEFAULT NULL COMMENT '费用',
|
||||
`descript` varchar(255) DEFAULT NULL COMMENT '描述',
|
||||
`version` varchar(255) DEFAULT NULL COMMENT '版本号',
|
||||
`install_type` int(4) DEFAULT NULL COMMENT '安装类型',
|
||||
`creator` varchar(255) DEFAULT NULL COMMENT '开发者',
|
||||
`release_time` bigint(13) DEFAULT NULL COMMENT '发布时间',
|
||||
`install_time` bigint(13) DEFAULT NULL COMMENT '安装时间',
|
||||
`module_name` varchar(255) DEFAULT NULL COMMENT 'jar包名称',
|
||||
`bean_name` varchar(40) DEFAULT NULL COMMENT 'bean名称',
|
||||
`icon` varchar(255) DEFAULT NULL COMMENT '图标',
|
||||
PRIMARY KEY (`plugin_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of my_plugin
|
||||
-- ----------------------------
|
||||
BEGIN;
|
||||
COMMIT;
|
||||
|
||||
SET FOREIGN_KEY_CHECKS = 1;
|
||||
|
@ -67,7 +67,7 @@
|
||||
<!-- <table tableName="datasource"/>-->
|
||||
<!-- <table tableName="sys_dict"/>-->
|
||||
<!-- <table tableName="sys_dict_item"/>-->
|
||||
<table tableName="dataset_table_field"/>
|
||||
<table tableName="my_plugin"/>
|
||||
<!-- <table tableName="panel_design"/>-->
|
||||
|
||||
|
||||
|
@ -35,6 +35,7 @@
|
||||
"umy-ui": "^1.1.6",
|
||||
"vcolorpicker": "^1.1.0",
|
||||
"vue": "2.6.10",
|
||||
"vue-axios": "3.2.4",
|
||||
"vue-clipboard2": "0.3.1",
|
||||
"vue-codemirror": "^4.0.6",
|
||||
"vue-i18n": "7.3.2",
|
||||
|
@ -4,7 +4,8 @@
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
|
||||
<!-- <link rel="icon" href="<%= BASE_URL %>favicon.ico">-->
|
||||
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
|
||||
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
|
||||
<title><%= webpackConfig.name %></title>
|
||||
</head>
|
||||
<body>
|
||||
|
13
frontend/src/api/system/plugin.js
Normal file
13
frontend/src/api/system/plugin.js
Normal file
@ -0,0 +1,13 @@
|
||||
import request from '@/utils/request'
|
||||
const pathMap = {
|
||||
queryPath: '/api/plugin/pluginGrid/'
|
||||
}
|
||||
export function pluginLists(page, size, data) {
|
||||
return request({
|
||||
url: pathMap.queryPath + page + '/' + size,
|
||||
method: 'post',
|
||||
data,
|
||||
loading: true
|
||||
})
|
||||
}
|
||||
|
53
frontend/src/components/AsyncComponent/index.vue
Normal file
53
frontend/src/components/AsyncComponent/index.vue
Normal file
@ -0,0 +1,53 @@
|
||||
<template>
|
||||
<component
|
||||
:is="mode"
|
||||
v-bind="$attrs"
|
||||
v-on="$listeners"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Axios from 'axios'
|
||||
|
||||
export default {
|
||||
name: 'AsyncComponent',
|
||||
inheritAttrs: true,
|
||||
props: {
|
||||
// 父组件提供请求地址
|
||||
url: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
resData: '',
|
||||
mode: ''
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
url: {
|
||||
immediate: true,
|
||||
async handler(val, oldVal) {
|
||||
if (!this.url) return
|
||||
// Cache 缓存 根据 url 参数
|
||||
if (!window.SyncComponentCache) {
|
||||
window.SyncComponentCache = {}
|
||||
}
|
||||
let res
|
||||
if (!window.SyncComponentCache[this.url]) {
|
||||
window.SyncComponentCache[this.url] = Axios.get(this.url)
|
||||
res = await window.SyncComponentCache[this.url]
|
||||
} else {
|
||||
res = await window.SyncComponentCache[this.url]
|
||||
}
|
||||
const Fn = Function
|
||||
this.mode = new Fn(`return ${res.data}`)()
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
@ -812,9 +812,10 @@ export default {
|
||||
target_field: '被关联字段',
|
||||
union_relation: '关联关系',
|
||||
pls_setting_union_success: '请正确设置关联关系',
|
||||
invalid_dataset:'Kettle未运行,无效数据集',
|
||||
invalid_dataset: 'Kettle未运行,无效数据集',
|
||||
check_all: '全选',
|
||||
can_not_union_self: '被关联表不能与关联表相同'
|
||||
can_not_union_self: '被关联表不能与关联表相同',
|
||||
float: '小数'
|
||||
},
|
||||
datasource: {
|
||||
datasource: '数据源',
|
||||
@ -887,5 +888,20 @@ export default {
|
||||
back: '返回',
|
||||
view: '视图',
|
||||
edit: '编辑'
|
||||
},
|
||||
plugin: {
|
||||
local_install: '本地安装',
|
||||
remote_install: '远程安装',
|
||||
name: '插件名称',
|
||||
free: '是否免费',
|
||||
cost: '费用',
|
||||
descript: '描述',
|
||||
version: '版本',
|
||||
creator: '作者',
|
||||
install_time: '安装时间',
|
||||
release_time: '时间',
|
||||
un_install: '卸载',
|
||||
uninstall_confirm: '确定卸载该插件',
|
||||
uninstall_cancel: '取消卸载插件'
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,8 @@ import Cookies from 'js-cookie'
|
||||
import '@/styles/index.scss' // global css
|
||||
import ElementUI from 'element-ui'
|
||||
import Fit2CloudUI from 'fit2cloud-ui'
|
||||
|
||||
import axios from 'axios'
|
||||
import VueAxios from 'vue-axios'
|
||||
import i18n from './lang' // internationalization
|
||||
import App from './App'
|
||||
import store from './store'
|
||||
@ -59,6 +60,7 @@ Vue.use(ElementUI, {
|
||||
Vue.use(Fit2CloudUI, {
|
||||
i18n: (key, value) => i18n.t(key, value)
|
||||
})
|
||||
Vue.use(VueAxios, axios)
|
||||
Vue.use(filter)
|
||||
Vue.use(directives)
|
||||
Vue.use(message)
|
||||
|
@ -85,7 +85,7 @@ export const constantRoutes = [
|
||||
{
|
||||
path: '/',
|
||||
component: Layout,
|
||||
redirect: '/panel',
|
||||
redirect: '/panel/index',
|
||||
hidden: true
|
||||
}
|
||||
|
||||
|
@ -28,24 +28,34 @@
|
||||
<el-col class="panel-height" style="width: 235px;border-top:solid 1px #dcdfe6;padding: 0 15px;overflow-y: auto;">
|
||||
<dataset-custom-field :table="table" :checked-list="checkedList" @getChecked="getChecked" />
|
||||
</el-col>
|
||||
<el-col class="panel-height" style="flex: 1;overflow: scroll;">
|
||||
<ux-grid
|
||||
ref="plxTable"
|
||||
size="mini"
|
||||
style="width: 100%;"
|
||||
:height="height"
|
||||
:checkbox-config="{highlight: true}"
|
||||
:width-resize="true"
|
||||
>
|
||||
<ux-table-column
|
||||
v-for="field in fields"
|
||||
:key="field.fieldName"
|
||||
min-width="200px"
|
||||
:field="field.fieldName"
|
||||
:title="field.remarks"
|
||||
:resizable="true"
|
||||
/>
|
||||
</ux-grid>
|
||||
<el-col class="panel-height" style="flex: 1;overflow: hidden;">
|
||||
<el-card class="box-card dataPreview" shadow="never">
|
||||
<div slot="header" class="clearfix">
|
||||
<span>{{ $t('dataset.data_preview') }}</span>
|
||||
</div>
|
||||
<ux-grid
|
||||
ref="plxTable"
|
||||
size="mini"
|
||||
style="width: 100%;"
|
||||
:height="height"
|
||||
:checkbox-config="{highlight: true}"
|
||||
:width-resize="true"
|
||||
>
|
||||
<ux-table-column
|
||||
v-for="field in fields"
|
||||
:key="field.fieldName"
|
||||
min-width="200px"
|
||||
:field="field.fieldName"
|
||||
:title="field.remarks"
|
||||
:resizable="true"
|
||||
/>
|
||||
</ux-grid>
|
||||
<span class="table-count">
|
||||
{{ $t('dataset.preview_show') }}
|
||||
<span class="span-number">1000</span>
|
||||
{{ $t('dataset.preview_item') }}
|
||||
</span>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-col>
|
||||
</el-col>
|
||||
@ -101,7 +111,7 @@ export default {
|
||||
const that = this
|
||||
setTimeout(function() {
|
||||
const currentHeight = document.documentElement.clientHeight
|
||||
that.height = currentHeight - 56 - 15 - 26 - 25 - 43 - 15
|
||||
that.height = currentHeight - 56 - 15 - 26 - 25 - 43 - 16 - 37 - 20 - 10
|
||||
}, 10)
|
||||
},
|
||||
|
||||
@ -207,6 +217,14 @@ export default {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
.dataPreview>>>.el-card__header{
|
||||
padding: 6px 8px;
|
||||
}
|
||||
|
||||
.dataPreview>>>.el-card__body{
|
||||
padding:10px;
|
||||
}
|
||||
|
||||
span{
|
||||
font-size: 14px;
|
||||
}
|
||||
@ -214,4 +232,11 @@ export default {
|
||||
.panel-height{
|
||||
height: calc(100vh - 56px - 15px - 26px - 25px - 43px);
|
||||
}
|
||||
|
||||
.span-number{
|
||||
color: #f18126;
|
||||
}
|
||||
.table-count{
|
||||
color: #606266;
|
||||
}
|
||||
</style>
|
||||
|
@ -11,9 +11,9 @@
|
||||
>
|
||||
<ux-table-column
|
||||
v-for="field in fields"
|
||||
:key="field.originName"
|
||||
:key="field.dataeaseName"
|
||||
min-width="200px"
|
||||
:field="field.originName"
|
||||
:field="field.dataeaseName"
|
||||
:title="field.name"
|
||||
:resizable="true"
|
||||
/>
|
||||
|
@ -12,19 +12,37 @@
|
||||
</el-row>
|
||||
<el-divider />
|
||||
<el-table :data="tableFields" size="mini" :max-height="maxHeight">
|
||||
<el-table-column property="type" :label="$t('dataset.field_type')" width="100">
|
||||
<el-table-column property="type" :label="$t('dataset.field_type')" width="180">
|
||||
<template slot-scope="scope">
|
||||
<span v-if="scope.row.deType === 0">
|
||||
<svg-icon v-if="scope.row.deType === 0" icon-class="field_text" class="field-icon-text" />
|
||||
<span class="field-class">{{ $t('dataset.text') }}</span>
|
||||
</span>
|
||||
<span v-if="scope.row.deType === 1">
|
||||
<svg-icon v-if="scope.row.deType === 1" icon-class="field_time" class="field-icon-time" />
|
||||
<span class="field-class">{{ $t('dataset.time') }}</span>
|
||||
</span>
|
||||
<span v-if="scope.row.deType === 2 || scope.row.deType === 3">
|
||||
<svg-icon v-if="scope.row.deType === 2 || scope.row.deType === 3" icon-class="field_value" class="field-icon-value" />
|
||||
<span class="field-class">{{ $t('dataset.value') }}</span>
|
||||
<el-select v-model="scope.row.deType" size="mini" style="display: inline-block;width: 26px;">
|
||||
<el-option
|
||||
v-for="item in fields"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
>
|
||||
<span style="float: left">
|
||||
<svg-icon v-if="item.value === 0" icon-class="field_text" class="field-icon-text" />
|
||||
<svg-icon v-if="item.value === 1" icon-class="field_time" class="field-icon-time" />
|
||||
<svg-icon v-if="item.value === 2 || item.value === 3" icon-class="field_value" class="field-icon-value" />
|
||||
</span>
|
||||
<span style="float: left; color: #8492a6; font-size: 12px">{{ item.label }}</span>
|
||||
</el-option>
|
||||
</el-select>
|
||||
<span style="margin-left: 8px;">
|
||||
<span v-if="scope.row.deType === 0">
|
||||
<svg-icon v-if="scope.row.deType === 0" icon-class="field_text" class="field-icon-text" />
|
||||
<span class="field-class">{{ $t('dataset.text') }}</span>
|
||||
</span>
|
||||
<span v-if="scope.row.deType === 1">
|
||||
<svg-icon v-if="scope.row.deType === 1" icon-class="field_time" class="field-icon-time" />
|
||||
<span class="field-class">{{ $t('dataset.time') }}</span>
|
||||
</span>
|
||||
<span v-if="scope.row.deType === 2 || scope.row.deType === 3">
|
||||
<svg-icon v-if="scope.row.deType === 2 || scope.row.deType === 3" icon-class="field_value" class="field-icon-value" />
|
||||
<span v-if="scope.row.deType === 2" class="field-class">{{ $t('dataset.value') }}</span>
|
||||
<span v-if="scope.row.deType === 3" class="field-class">{{ $t('dataset.value') + '(' + $t('dataset.float') + ')' }}</span>
|
||||
</span>
|
||||
</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
@ -58,7 +76,13 @@ export default {
|
||||
data() {
|
||||
return {
|
||||
maxHeight: 'auto',
|
||||
tableFields: []
|
||||
tableFields: [],
|
||||
fields: [
|
||||
{ label: this.$t('dataset.text'), value: 0 },
|
||||
{ label: this.$t('dataset.time'), value: 1 },
|
||||
{ label: this.$t('dataset.value'), value: 2 },
|
||||
{ label: this.$t('dataset.value') + '(' + this.$t('dataset.float') + ')', value: 3 }
|
||||
]
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
@ -108,4 +132,10 @@ export default {
|
||||
.field-class{
|
||||
font-size: 12px !important;
|
||||
}
|
||||
.el-select>>>input{
|
||||
padding-right: 10px;
|
||||
}
|
||||
.el-select>>>.el-input__suffix{
|
||||
right: 0;
|
||||
}
|
||||
</style>
|
||||
|
@ -31,7 +31,7 @@
|
||||
<el-tab-pane :label="$t('dataset.data_preview')" name="dataPreview">
|
||||
<tab-data-preview :table="table" :fields="fields" :data="data" :page="page" :form="tableViewRowForm" @reSearch="reSearch" />
|
||||
</el-tab-pane>
|
||||
<el-tab-pane v-if="table.type !== 'custom'" :label="$t('dataset.join_view')" name="joinView">
|
||||
<el-tab-pane v-if="table.type !== 'custom' && table.mode === 1" :label="$t('dataset.join_view')" name="joinView">
|
||||
<union-view :table="table" />
|
||||
</el-tab-pane>
|
||||
<el-tab-pane v-if="table.mode === 1 && (table.type === 'db' || table.type === 'sql')" :label="$t('dataset.update_info')" name="updateInfo">
|
||||
|
162
frontend/src/views/system/plugin/index.vue
Normal file
162
frontend/src/views/system/plugin/index.vue
Normal file
@ -0,0 +1,162 @@
|
||||
<template>
|
||||
<layout-content v-loading="$store.getters.loadingMap[$store.getters.currentPath]">
|
||||
<complex-table
|
||||
:data="data"
|
||||
:columns="columns"
|
||||
:search-config="searchConfig"
|
||||
:pagination-config="paginationConfig"
|
||||
@search="search"
|
||||
>
|
||||
<template #toolbar>
|
||||
<!-- <el-button @click="create">{{ $t('plugin.local_install') }}</el-button> -->
|
||||
|
||||
<el-upload
|
||||
:action="baseUrl+'api/plugin/upload'"
|
||||
:multiple="false"
|
||||
:show-file-list="false"
|
||||
:file-list="fileList"
|
||||
accept=".zip"
|
||||
:before-upload="beforeUpload"
|
||||
:on-success="uploadSuccess"
|
||||
:on-error="uploadFail"
|
||||
name="file"
|
||||
:headers="headers"
|
||||
>
|
||||
<el-button size="mini" type="primary" :disabled="uploading">
|
||||
<span v-if="!uploading" style="font-size: 12px;">{{ $t('plugin.local_install') }}</span>
|
||||
<span v-if="uploading" style="font-size: 12px;"><i class="el-icon-loading" /> {{ $t('dataset.uploading') }}</span>
|
||||
</el-button>
|
||||
</el-upload>
|
||||
</template>
|
||||
|
||||
<el-table-column prop="name" :label="$t('plugin.name')" />
|
||||
<el-table-column prop="free" :label="$t('plugin.free')" />
|
||||
<el-table-column prop="cost" :label="$t('plugin.cost')" />
|
||||
|
||||
<el-table-column :show-overflow-tooltip="true" prop="descript" :label="$t('plugin.descript')" />
|
||||
<el-table-column prop="version" :label="$t('plugin.version')" />
|
||||
<el-table-column prop="creator" :label="$t('plugin.creator')" />
|
||||
|
||||
<el-table-column prop="installTime" :label="$t('plugin.install_time')">
|
||||
<template v-slot:default="scope">
|
||||
<span>{{ scope.row.installTime | timestampFormatDate }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<fu-table-operations :buttons="buttons" label="操作" fix />
|
||||
</complex-table>
|
||||
|
||||
</layout-content>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import LayoutContent from '@/components/business/LayoutContent'
|
||||
import ComplexTable from '@/components/business/complex-table'
|
||||
|
||||
import { checkPermission } from '@/utils/permission'
|
||||
import { formatCondition } from '@/utils/index'
|
||||
import { pluginLists } from '@/api/system/plugin'
|
||||
import { getToken } from '@/utils/auth'
|
||||
export default {
|
||||
|
||||
components: { ComplexTable, LayoutContent },
|
||||
data() {
|
||||
return {
|
||||
header: '',
|
||||
columns: [],
|
||||
buttons: [
|
||||
{
|
||||
label: this.$t('commons.delete'), icon: 'el-icon-delete', type: 'danger', click: this.del,
|
||||
show: checkPermission(['user:del'])
|
||||
}
|
||||
],
|
||||
searchConfig: {
|
||||
useQuickSearch: false,
|
||||
quickPlaceholder: '按名称搜索',
|
||||
components: [
|
||||
{ field: 'name', label: '名称', component: 'FuComplexInput' }
|
||||
|
||||
// {
|
||||
// field: 'u.enabled',
|
||||
// label: '状态',
|
||||
// component: 'FuComplexSelect',
|
||||
// options: [
|
||||
// { label: '启用', value: '1' },
|
||||
// { label: '禁用', value: '0' }
|
||||
// ],
|
||||
// multiple: false
|
||||
// }
|
||||
]
|
||||
},
|
||||
paginationConfig: {
|
||||
currentPage: 1,
|
||||
pageSize: 10,
|
||||
total: 0
|
||||
},
|
||||
data: [],
|
||||
uploading: false,
|
||||
baseUrl: process.env.VUE_APP_BASE_API,
|
||||
fileList: [],
|
||||
headers: { Authorization: getToken() }
|
||||
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.search()
|
||||
},
|
||||
|
||||
methods: {
|
||||
|
||||
search(condition) {
|
||||
const temp = formatCondition(condition)
|
||||
const param = temp || {}
|
||||
const { currentPage, pageSize } = this.paginationConfig
|
||||
pluginLists(currentPage, pageSize, param).then(response => {
|
||||
this.data = response.data.listObject
|
||||
this.paginationConfig.total = response.data.itemCount
|
||||
})
|
||||
},
|
||||
beforeUpload(file) {
|
||||
this.uploading = true
|
||||
},
|
||||
uploadFail(response, file, fileList) {
|
||||
this.uploading = false
|
||||
},
|
||||
uploadSuccess(response, file, fileList) {
|
||||
console.log(response)
|
||||
console.log(file)
|
||||
console.log(fileList)
|
||||
// this.path = response.data.path
|
||||
// this.fields = response.data.fields
|
||||
// this.data = response.data.data
|
||||
// const datas = this.data
|
||||
// this.$refs.plxTable.reloadData(datas)
|
||||
|
||||
// if (file.name.lastIndexOf('.') > 0) {
|
||||
// this.name = file.name.substring(0, file.name.lastIndexOf('.'))
|
||||
// }
|
||||
// this.fileList = fileList
|
||||
this.uploading = false
|
||||
},
|
||||
|
||||
del(row) {
|
||||
this.$confirm(this.$t('user.delete_confirm'), '', {
|
||||
confirmButtonText: this.$t('commons.confirm'),
|
||||
cancelButtonText: this.$t('commons.cancel'),
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
// delUser(encodeURIComponent(row.userId)).then(res => {
|
||||
// this.$success(this.$t('commons.delete_success'))
|
||||
// this.search()
|
||||
// })
|
||||
}).catch(() => {
|
||||
this.$info(this.$t('commons.delete_cancel'))
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
@ -1,34 +1,41 @@
|
||||
<template>
|
||||
<el-card>
|
||||
<el-tabs v-model="activeName" class="system-setting">
|
||||
<ui-setting v-if="!test" />
|
||||
<!-- <el-tabs v-model="activeName" class="system-setting">
|
||||
<el-tab-pane label="显示设置" name="ui">
|
||||
<ui-setting />
|
||||
</el-tab-pane>
|
||||
<el-tab-pane :label="$t('system_parameter_setting.mailbox_service_settings')" name="email">
|
||||
<email-setting />
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</el-tabs> -->
|
||||
<async-component v-if="test" url="http://localhost:8081/PluginDemo.js" @execute-axios="executeAxios" />
|
||||
</el-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import EmailSetting from './EmailSetting'
|
||||
import UiSetting from './UiSetting'
|
||||
import AsyncComponent from '@/components/AsyncComponent'
|
||||
export default {
|
||||
name: 'SystemParameterSetting',
|
||||
components: {
|
||||
UiSetting,
|
||||
EmailSetting
|
||||
AsyncComponent
|
||||
|
||||
// 'MsDisplay': display.default,
|
||||
// 'MsAuth': auth.default
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
activeName: 'ui'
|
||||
activeName: 'ui',
|
||||
test: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// hasLicense
|
||||
executeAxios(options) {
|
||||
console.log(options)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
Loading…
Reference in New Issue
Block a user