Merge remote-tracking branch 'origin/dev-1.13.0'

This commit is contained in:
datagear 2020-10-12 11:25:15 +08:00
commit f218fb5f51
179 changed files with 9556 additions and 1028 deletions

View File

@ -1,14 +1,15 @@
下一主版本:
导出看板功能;
数据分析添加项目概念,用于分组管理数据集、图表、看板;
表格图表轮播效果;
ok 导出看板功能;
ok 数据分析添加项目概念,用于分组管理数据集、图表、看板;
ok 文件类数据集支持选择服务器端文件:管理员维护和授权服务器端目录,用户可选择授权目录内的文件;
ok 表格图表轮播效果;
看板展示页面可显示数据集结果数据;
修复分页查询设置页大小无效的BUG
修复数据管理功能插入操作不支持SQL Server的IDENTITY_INSERT特性的BUG
更新山东省地图;
修复环形饼图无法调整环大小的BUG
修复系统禁用匿名用户后分享给匿名用户的图表、看板展示链接无法访问的BUG主要用于支持外部系统iframe嵌入集成
ok 修复分页查询设置页大小无效的BUG
ok 修复数据管理功能插入操作不支持SQL Server的IDENTITY_INSERT特性的BUG
ok 更新山东省地图;
ok 修复环形饼图无法调整环大小的BUG
ok 修复系统禁用匿名用户后分享给匿名用户的图表、看板展示链接无法访问的BUG主要用于支持外部系统iframe嵌入集成
下一修订版本:
@ -26,6 +27,7 @@
待研究:
应用级集成;
动态属性数据集;
看板可视化编辑;
3D图表
UI改进改进现有的UI样式或者替换为更流行的UI

View File

@ -7,7 +7,7 @@
<parent>
<groupId>org.datagear</groupId>
<artifactId>datagear</artifactId>
<version>1.12.0</version>
<version>1.13.0</version>
</parent>
<artifactId>datagear-analysis</artifactId>

View File

@ -64,6 +64,9 @@ public interface DataSet extends Identifiable
/**
* 给定的参数映射表是否可用于{@linkplain #getResult(Map)}
* <p>
* 通常是{@code paramValues}包含{@linkplain #getParams()}中的所有{@linkplain DataSetParam#isRequired()}参数值
* </p>
*
* @param paramValues
* @return
@ -77,7 +80,9 @@ public interface DataSet extends Identifiable
* </p>
*
* @param paramValues
* {@linkplain #getParams()}所描述的参数值映射表其关键字是{@linkplain DataSetParam#getName()}
* 包含{@linkplain #getParams()}所描述的参数值映射表应是符合{@linkplain #isReady(Map)}校验的
* 其关键字是{@linkplain DataSetParam#getName()}
* 参数值映射表并不要求与{@linkplain #getParams()}一一对应通常是包含相同或者更多的项
* @return
* @throws DataSetException
*/

View File

@ -111,6 +111,15 @@ public interface TemplateDashboardWidgetResManager
*/
void copyFrom(String id, File directory) throws IOException;
/**
* 将指定{@linkplain TemplateDashboardWidget#getId()}的所有资源拷贝至目标目录
*
* @param id
* @param directory
* @throws IOException
*/
void copyTo(String id, File directory) throws IOException;
/**
* 是否包含指定名称的资源
*

View File

@ -258,30 +258,22 @@ public abstract class AbstractDataSet extends AbstractIdentifiable implements Da
return maps;
}
/**
* 只有当{@linkplain #hasParam()}{@code true}时才将指定文本作为Freemarker模板解析
*
* @param text
* @param paramValues
* @return
*/
protected String resolveAsFmkTemplateIfHasParam(String text, Map<String, ?> paramValues)
{
if (!hasParam())
return text;
return resolveAsFmkTemplate(text, paramValues);
}
/**
* 将指定文本作为Freemarker模板解析
* <p>
* 注意即使此数据集没有定义任何参数{@linkplain #hasParam()}{@code false}此方法也必须将{@code text}作为模板解析因为存在如下应用场景
* 用户不定义数据集参数但却定义模板内容之后用户自行在DataSet.getResult(Map&lt;String,?&gt;)参数映射表中传递模板内容所须的参数值
* </p>
*
* @param text
* @param paramValues
* @return
*/
protected String resolveAsFmkTemplate(String text, Map<String, ?> paramValues)
public String resolveAsFmkTemplate(String text, Map<String, ?> paramValues)
{
// if (!hasParam())
// return text;
if (text == null)
return null;

View File

@ -226,7 +226,20 @@ public abstract class AbstractExcelDataSet extends AbstractResolvableDataSet imp
protected ResolvedDataSetResult resolveResult(Map<String, ?> paramValues, List<DataSetProperty> properties)
throws DataSetException
{
File file = getExcelFile(paramValues);
File file = null;
try
{
file = getExcelFile(paramValues);
}
catch (DataSetException e)
{
throw e;
}
catch (Throwable t)
{
throw new DataSetSourceParseException(t);
}
ResolvedDataSetResult result = null;
@ -677,8 +690,7 @@ public abstract class AbstractExcelDataSet extends AbstractResolvableDataSet imp
*
* @param paramValues
* @return
* @throws DataSetException
* @throws Throwable
*/
protected abstract File getExcelFile(Map<String, ?> paramValues) throws DataSetException;
protected abstract File getExcelFile(Map<String, ?> paramValues) throws Throwable;
}

View File

@ -12,7 +12,6 @@ import java.io.Reader;
import java.util.List;
import java.util.Map;
import org.datagear.analysis.DataSetException;
import org.datagear.analysis.DataSetProperty;
import org.datagear.util.IOUtil;
@ -70,7 +69,7 @@ public abstract class AbstractJsonFileDataSet extends AbstractJsonDataSet
*
* @param paramValues
* @return
* @throws DataSetException
* @throws Throwable
*/
protected abstract File getJsonFile(Map<String, ?> paramValues) throws DataSetException;
protected abstract File getJsonFile(Map<String, ?> paramValues) throws Throwable;
}

View File

@ -26,10 +26,10 @@ import org.datagear.util.FileUtil;
*/
public class CsvDirectoryFileDataSet extends AbstractCsvFileDataSet
{
/** JSON文件所在的目录 */
/** CSV文件所在的目录 */
private File directory;
/** JSON文件名 */
/** CSV文件名 */
private String fileName;
public CsvDirectoryFileDataSet()

View File

@ -73,7 +73,7 @@ public class CsvValueDataSet extends AbstractCsvDataSet
@Override
protected TemplateResolvedSource<Reader> getCsvReader(Map<String, ?> paramValues) throws Throwable
{
String csv = resolveAsFmkTemplateIfHasParam(this.value, paramValues);
String csv = resolveAsFmkTemplate(this.value, paramValues);
return new TemplateResolvedSource<>(IOUtil.getReader(csv), csv);
}
}

View File

@ -25,7 +25,7 @@ import freemarker.template.TemplateException;
* 专用于数据集模板且采用Freemarker作为模板语言的{@linkplain TemplateResolver}
* <p>
* 此类的{@linkplain #setDataSetTemplateStandardConfig(Configuration)}定义了很多数据集模板规范
* 这些规范不应被更改因为会影响用已定义数据集的模板
* 这些规范不应被更改因为会影响用已定义数据集的模板
* </p>
*
* @author datagear@163.com
@ -39,7 +39,7 @@ public class DataSetFmkTemplateResolver implements TemplateResolver
public DataSetFmkTemplateResolver()
{
this(500);
this(1000);
}
public DataSetFmkTemplateResolver(int cacheCapacity)

View File

@ -7,6 +7,11 @@
*/
package org.datagear.analysis.support;
import java.util.Collection;
import java.util.Map;
import org.datagear.analysis.DataNameType;
import org.datagear.analysis.DataSet;
import org.datagear.analysis.DataSetParam;
import org.datagear.analysis.DataSetParam.DataType;
@ -23,6 +28,21 @@ public class DataSetParamValueConverter extends DataValueConverter
super();
}
/**
* 转换参数值映射表返回一个经转换的新映射表
* <p>
* 注意此方法必须遵循如下规则如果{@code paramValues}中有未在{@code dataSetParams}中定义的项那么它应原样写入返回映射表中
* 因为对于支持<code>Freemarker</code>{@linkplain DataSet}实现类比如{@linkplain SqlDataSet}
* 存在不定义{@linkplain DataSet#getParams()}而传递参数给内部<code>Freemarker</code>模板的应用场景
* </p>
*/
@Override
public Map<String, Object> convert(Map<String, ?> paramValues, Collection<? extends DataNameType> dataSetParams)
throws DataValueConvertionException
{
return super.convert(paramValues, dataSetParams);
}
@Override
protected Object convertValue(Object value, String type) throws DataValueConvertionException
{

View File

@ -27,10 +27,15 @@ public abstract class DataValueConverter
public static final Pattern PATTERN_DECIMAL_NUMBER = Pattern.compile("^[^\\.]+\\.[^\\.]+$");
/**
* 转换数据值映射表
* 转换数据值映射表返回一个经转换的新映射表
* <p>
* 如果{@code nameValues}中有未在{@code dataNameTypes}中定义的项那么它将原样写入返回映射表中
* </p>
*
* @param nameValues
* 原始名/值映射表允许为{@code null}
* @param dataNameTypes
* /类型集合允许为{@code null}
* @return
* @throws DataValueConvertionException
*/
@ -42,17 +47,20 @@ public abstract class DataValueConverter
Map<String, Object> re = new HashMap<>(nameValues);
for (DataNameType dnt : dataNameTypes)
if (dataNameTypes != null)
{
String name = dnt.getName();
for (DataNameType dnt : dataNameTypes)
{
String name = dnt.getName();
if (!nameValues.containsKey(name))
continue;
if (!nameValues.containsKey(name))
continue;
Object value = nameValues.get(name);
value = convert(value, dnt.getType());
Object value = nameValues.get(name);
value = convert(value, dnt.getType());
re.put(name, value);
re.put(name, value);
}
}
return re;

View File

@ -148,6 +148,13 @@ public class FileTemplateDashboardWidgetResManager extends AbstractTemplateDashb
IOUtil.copy(directory, myDirectory, false);
}
@Override
public void copyTo(String id, File directory) throws IOException
{
File myDirectory = FileUtil.getDirectory(this.rootDirectory, id);
IOUtil.copy(myDirectory, directory, false);
}
@Override
public boolean containsResource(String id, String name)
{

View File

@ -404,17 +404,17 @@ public class HttpDataSet extends AbstractResolvableDataSet
protected String resolveTemplateUri(Map<String, ?> paramValues) throws Throwable
{
return resolveAsFmkTemplateIfHasParam(this.uri, paramValues);
return resolveAsFmkTemplate(this.uri, paramValues);
}
protected String resolveTemplateHeaderContent(Map<String, ?> paramValues) throws Throwable
{
return resolveAsFmkTemplateIfHasParam(this.headerContent, paramValues);
return resolveAsFmkTemplate(this.headerContent, paramValues);
}
protected String resolveTemplateRequestContent(Map<String, ?> paramValues) throws Throwable
{
return resolveAsFmkTemplateIfHasParam(this.requestContent, paramValues);
return resolveAsFmkTemplate(this.requestContent, paramValues);
}
protected ClassicHttpRequest createHttpRequest(String uri) throws Throwable

View File

@ -64,7 +64,7 @@ public class JsonValueDataSet extends AbstractJsonDataSet
@Override
protected TemplateResolvedSource<Reader> getJsonReader(Map<String, ?> paramValues) throws Throwable
{
String json = resolveAsFmkTemplateIfHasParam(this.value, paramValues);
String json = resolveAsFmkTemplate(this.value, paramValues);
return new TemplateResolvedSource<>(IOUtil.getReader(json), json);
}
}

View File

@ -1,57 +0,0 @@
/*
* Copyright (c) 2018 datagear.tech. All Rights Reserved.
*/
/**
*
*/
package org.datagear.analysis.support;
import org.datagear.analysis.DataSetException;
/**
* 宏计算异常
*
* @author datagear@163.com
*
*/
public class MacroEvalException extends DataSetException
{
private static final long serialVersionUID = 1L;
private String macro;
public MacroEvalException(String macro)
{
super();
this.macro = macro;
}
public MacroEvalException(String macro, String message)
{
super(message);
this.macro = macro;
}
public MacroEvalException(String macro, Throwable cause)
{
super(cause);
this.macro = macro;
}
public MacroEvalException(String macro, String message, Throwable cause)
{
super(message, cause);
this.macro = macro;
}
public String getMacro()
{
return macro;
}
protected void setMacro(String macro)
{
this.macro = macro;
}
}

View File

@ -0,0 +1,70 @@
/*
* Copyright (c) 2018 datagear.tech. All Rights Reserved.
*/
/**
*
*/
package org.datagear.analysis.support;
import java.util.List;
import java.util.Map;
import org.datagear.analysis.DataSet;
import org.datagear.analysis.DataSetException;
import org.datagear.analysis.DataSetProperty;
import org.datagear.analysis.DataSetResult;
/**
* 轮廓{@linkplain DataSet}
* <p>
* 此类仅用于描述{@linkplain DataSet}接口数据结构不包含任何其他逻辑
* </p>
*
* @author datagear@163.com
*
*/
public class ProfileDataSet extends AbstractDataSet
{
public ProfileDataSet()
{
}
public ProfileDataSet(String id, String name, List<DataSetProperty> properties)
{
super(id, name, properties);
}
public ProfileDataSet(DataSet dataSet)
{
super(dataSet.getId(), dataSet.getName(), dataSet.getProperties());
setParams(dataSet.getParams());
}
@Override
public DataSetResult getResult(Map<String, ?> paramValues) throws DataSetException
{
throw new UnsupportedOperationException();
}
/**
* 构建{@linkplain ProfileDataSet}
* <p>
* 如果{@code dataSet}{@linkplain ProfileDataSet}实例将直接返回
* </p>
*
* @param dataSet
* 允许为{@code null}
* @return
*/
public static ProfileDataSet valueOf(DataSet dataSet)
{
if (dataSet == null)
return null;
if (dataSet instanceof ProfileDataSet)
return (ProfileDataSet) dataSet;
return new ProfileDataSet(dataSet);
}
}

View File

@ -99,7 +99,7 @@ public class SqlDataSet extends AbstractResolvableDataSet implements ResolvableD
protected TemplateResolvedDataSetResult resolveResult(Map<String, ?> paramValues, List<DataSetProperty> properties)
throws DataSetException
{
String sql = resolveAsFmkTemplateIfHasParam(getSql(), paramValues);
String sql = resolveAsFmkTemplate(getSql(), paramValues);
Connection cn = null;

View File

@ -6,7 +6,7 @@
<parent>
<groupId>org.datagear</groupId>
<artifactId>datagear</artifactId>
<version>1.12.0</version>
<version>1.13.0</version>
</parent>
<artifactId>datagear-connection</artifactId>

View File

@ -7,7 +7,7 @@
<parent>
<groupId>org.datagear</groupId>
<artifactId>datagear</artifactId>
<version>1.12.0</version>
<version>1.13.0</version>
</parent>
<artifactId>datagear-dataexchange</artifactId>

View File

@ -6,7 +6,7 @@
<parent>
<groupId>org.datagear</groupId>
<artifactId>datagear</artifactId>
<version>1.12.0</version>
<version>1.13.0</version>
</parent>
<artifactId>datagear-management</artifactId>

View File

@ -0,0 +1,109 @@
/*
* Copyright 2018 datagear.tech. All Rights Reserved.
*/
package org.datagear.management.domain;
import java.util.Date;
/**
* 数据分析项目实体
*
* @author datagear@163.com
*
*/
public class AnalysisProject extends AbstractStringIdEntity
implements CreateUserEntity<String>, DataPermissionEntity<String>
{
private static final long serialVersionUID = 1L;
/** 授权资源类型 */
public static final String AUTHORIZATION_RESOURCE_TYPE = "AnalysisProject";
/** 名称 */
private String name;
/** 描述 */
private String desc = "";
/** 创建用户 */
private User createUser;
/** 创建时间 */
private Date createTime = new Date();
private int dataPermission = PERMISSION_NOT_LOADED;
public AnalysisProject()
{
super();
}
public AnalysisProject(String id, String name, User createUser)
{
super(id);
this.name = name;
this.createUser = createUser;
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public String getDesc()
{
return desc;
}
public void setDesc(String desc)
{
this.desc = desc;
}
@Override
public User getCreateUser()
{
return createUser;
}
@Override
public void setCreateUser(User createUser)
{
this.createUser = createUser;
}
public Date getCreateTime()
{
return createTime;
}
public void setCreateTime(Date createTime)
{
this.createTime = createTime;
}
@Override
public int getDataPermission()
{
return dataPermission;
}
@Override
public void setDataPermission(int dataPermission)
{
this.dataPermission = dataPermission;
}
@Override
public String toString()
{
return getClass().getSimpleName() + " [name=" + name + ", desc=" + desc + ", createUser=" + createUser
+ ", createTime=" + createTime + ", dataPermission=" + dataPermission + "]";
}
}

View File

@ -0,0 +1,27 @@
/*
* Copyright (c) 2018 datagear.tech. All Rights Reserved.
*/
/**
*
*/
package org.datagear.management.domain;
/**
* {@linkplain AnalysisProject}关联实体类
*
* @author datagear@163.com
*
*/
public interface AnalysisProjectAwareEntity<ID> extends Entity<ID>
{
/**
* {@linkplain AnalysisProject}关联实体类的级联数据权限参数资源类型
* 参考AnalysisProjectMapper.xml的queryViewIdPermissionForAnalysisProjectAwareEntity
*/
String DATA_PERMISSION_PARAM_RESOURCE_TYPE_ANALYSIS_PROJECT = "DP_RESOURCE_TYPE_ANALYSIS_PROJECT";
AnalysisProject getAnalysisProject();
void setAnalysisProject(AnalysisProject analysisProject);
}

View File

@ -10,8 +10,10 @@ package org.datagear.management.domain;
import java.io.File;
import java.util.Date;
import java.util.List;
import java.util.Map;
import org.datagear.analysis.DataSetProperty;
import org.datagear.analysis.support.AbstractCsvFileDataSet;
import org.datagear.analysis.support.CsvDirectoryFileDataSet;
/**
@ -20,37 +22,102 @@ import org.datagear.analysis.support.CsvDirectoryFileDataSet;
* @author datagear@163.com
*
*/
public class CsvFileDataSetEntity extends CsvDirectoryFileDataSet implements DirectoryFileDataSetEntity
public class CsvFileDataSetEntity extends AbstractCsvFileDataSet implements DirectoryFileDataSetEntity
{
private static final long serialVersionUID = 1L;
/** 文件源类型 */
private String fileSourceType;
/** 上传文件所在的目录 */
private File directory = null;
/** 上传文件名 */
private String fileName = "";
/** 展示名 */
private String displayName;
private String displayName = "";
/** 服务器端文件所在的目录 */
private DataSetResDirectory dataSetResDirectory = null;
/** 服务器端文件的文件名(相对于{@linkplain #getDataSetResDirectory()} */
private String dataSetResFileName = "";
/** 创建用户 */
private User createUser;
/** 创建时间 */
private Date createTime;
private Date createTime = new Date();
/** 权限 */
private int dataPermission = PERMISSION_NOT_LOADED;
private AnalysisProject analysisProject = null;
public CsvFileDataSetEntity()
{
super();
this.createTime = new Date();
}
public CsvFileDataSetEntity(String id, String name, List<DataSetProperty> properties, File directory,
String fileName, String displayName, User createUser)
{
super(id, name, properties, directory, fileName);
super(id, name, properties);
this.fileSourceType = FILE_SOURCE_TYPE_UPLOAD;
this.directory = directory;
this.fileName = fileName;
this.displayName = displayName;
this.createTime = new Date();
this.createUser = createUser;
}
public CsvFileDataSetEntity(String id, String name, List<DataSetProperty> properties,
DataSetResDirectory dataSetResDirectory, String dataSetResFileName, User createUser)
{
super(id, name, properties);
this.fileSourceType = FILE_SOURCE_TYPE_SERVER;
this.dataSetResDirectory = dataSetResDirectory;
this.dataSetResFileName = dataSetResFileName;
this.createUser = createUser;
}
@Override
public String getFileSourceType()
{
return fileSourceType;
}
@Override
public void setFileSourceType(String fileSourceType)
{
this.fileSourceType = fileSourceType;
}
@Override
public File getDirectory()
{
return directory;
}
@Override
public void setDirectory(File directory)
{
this.directory = directory;
}
@Override
public String getFileName()
{
return fileName;
}
@Override
public void setFileName(String fileName)
{
this.fileName = fileName;
}
@Override
public String getDisplayName()
{
@ -63,6 +130,30 @@ public class CsvFileDataSetEntity extends CsvDirectoryFileDataSet implements Dir
this.displayName = displayName;
}
@Override
public DataSetResDirectory getDataSetResDirectory()
{
return dataSetResDirectory;
}
@Override
public void setDataSetResDirectory(DataSetResDirectory dataSetResDirectory)
{
this.dataSetResDirectory = dataSetResDirectory;
}
@Override
public String getDataSetResFileName()
{
return dataSetResFileName;
}
@Override
public void setDataSetResFileName(String dataSetResFileName)
{
this.dataSetResFileName = dataSetResFileName;
}
@Override
public String getDataSetType()
{
@ -111,4 +202,28 @@ public class CsvFileDataSetEntity extends CsvDirectoryFileDataSet implements Dir
{
this.dataPermission = dataPermission;
}
@Override
public AnalysisProject getAnalysisProject()
{
return analysisProject;
}
@Override
public void setAnalysisProject(AnalysisProject analysisProject)
{
this.analysisProject = analysisProject;
}
@Override
public String resolveFileNameAsFmkTemplate(String fileName, Map<String, ?> paramValues)
{
return resolveAsFmkTemplate(fileName, paramValues);
}
@Override
protected File getCsvFile(Map<String, ?> paramValues) throws Throwable
{
return FILE_SUPPORT.getFile(this, paramValues);
}
}

View File

@ -32,6 +32,8 @@ public class CsvValueDataSetEntity extends CsvValueDataSet implements DataSetEnt
/** 权限 */
private int dataPermission = PERMISSION_NOT_LOADED;
private AnalysisProject analysisProject = null;
public CsvValueDataSetEntity()
{
super();
@ -94,4 +96,16 @@ public class CsvValueDataSetEntity extends CsvValueDataSet implements DataSetEnt
{
this.dataPermission = dataPermission;
}
@Override
public AnalysisProject getAnalysisProject()
{
return analysisProject;
}
@Override
public void setAnalysisProject(AnalysisProject analysisProject)
{
this.analysisProject = analysisProject;
}
}

View File

@ -4,6 +4,8 @@
package org.datagear.management.domain;
import org.datagear.management.service.DataPermissionEntityService;
/**
* 数据权限实体
*
@ -13,8 +15,8 @@ package org.datagear.management.domain;
*/
public interface DataPermissionEntity<ID> extends Entity<ID>
{
/** 权限未加载 */
int PERMISSION_NOT_LOADED = -9;
/** 参考{@linkplain DataPermissionEntityService#PERMISSION_NOT_LOADED} */
int PERMISSION_NOT_LOADED = DataPermissionEntityService.PERMISSION_NOT_LOADED;
/**
* 获取数据权限值

View File

@ -17,7 +17,8 @@ import org.datagear.analysis.DataSetProperty;
* @author datagear@163.com
*
*/
public interface DataSetEntity extends DataSet, CreateUserEntity<String>, DataPermissionEntity<String>
public interface DataSetEntity
extends DataSet, CreateUserEntity<String>, DataPermissionEntity<String>, AnalysisProjectAwareEntity<String>
{
/** 授权资源类型 */
String AUTHORIZATION_RESOURCE_TYPE = "DataSet";

View File

@ -0,0 +1,113 @@
/*
* Copyright 2018 datagear.tech. All Rights Reserved.
*/
package org.datagear.management.domain;
import java.util.Date;
/**
* 数据集资源目录实体
* <p>
* 文件类数据集允许选择服务器端文件需要限定用户可访问的服务端目录此类即用于定义访问目录
* </p>
*
* @author datagear@163.com
*
*/
public class DataSetResDirectory extends AbstractStringIdEntity
implements CreateUserEntity<String>, DataPermissionEntity<String>
{
private static final long serialVersionUID = 1L;
/** 授权资源类型 */
public static final String AUTHORIZATION_RESOURCE_TYPE = "DataSetDirectory";
/** 目录 */
private String directory;
/** 描述 */
private String desc = "";
/** 此模式的创建用户 */
private User createUser;
/** 此模式的创建时间 */
private Date createTime = new Date();
/** 权限 */
private int dataPermission = PERMISSION_NOT_LOADED;
public DataSetResDirectory()
{
super();
}
public DataSetResDirectory(String id, String directory, User createuUser)
{
super(id);
this.directory = directory;
this.createUser = createuUser;
}
public String getDirectory()
{
return directory;
}
public void setDirectory(String directory)
{
this.directory = directory;
}
public String getDesc()
{
return desc;
}
public void setDesc(String desc)
{
this.desc = desc;
}
@Override
public User getCreateUser()
{
return createUser;
}
@Override
public void setCreateUser(User createUser)
{
this.createUser = createUser;
}
public Date getCreateTime()
{
return createTime;
}
public void setCreateTime(Date createTime)
{
this.createTime = createTime;
}
@Override
public int getDataPermission()
{
return dataPermission;
}
@Override
public void setDataPermission(int dataPermission)
{
this.dataPermission = dataPermission;
}
@Override
public String toString()
{
return getClass().getSimpleName() + " [directory=" + directory + ", desc=" + desc + ", createUser=" + createUser
+ ", createTime=" + createTime + ", dataPermission=" + dataPermission + "]";
}
}

View File

@ -5,54 +5,148 @@
package org.datagear.management.domain;
import java.io.File;
import java.util.Map;
import org.datagear.analysis.support.AbstractDataSet;
import org.datagear.util.FileUtil;
/**
* 目录内文件数据集实体
* <p>
* 文件有两种类型
* 用户上传的文件保存至{@linkplain #getDirectory()}内的{@linkplain #getFileName()}文件
* 服务器端文件本来就存储在服务器磁盘指定目录内的文件
* </p>
*
* @author datagear@163.com
*
*/
public interface DirectoryFileDataSetEntity extends DataSetEntity
{
/** 文件类型:用户上传文件 */
String FILE_SOURCE_TYPE_UPLOAD = "UPLOAD";
/** 文件类型:服务器端文件 */
String FILE_SOURCE_TYPE_SERVER = "SERVER";
/**
* 获取目录
* 获取文件源类型
*
* @return
*/
String getFileSourceType();
/**
* 设置文件类型{@linkplain #FILE_SOURCE_TYPE_UPLOAD}{@linkplain #FILE_SOURCE_TYPE_SERVER}
*
* @param fileSourceType
*/
void setFileSourceType(String fileSourceType);
/**
* 获取用户上传文件的存储目录
*
* @return
*/
File getDirectory();
/**
* 设置目录
* 设置用户上传文件的存储目录
*
* @param directory
*/
void setDirectory(File directory);
/**
* 获取文件名
* 获取用户上传文件的文件名
*
* @return
*/
String getFileName();
/**
* 设置文件名
* 设置用户上传文件的存储文件名
*
* @param fileName
*/
void setFileName(String fileName);
/**
* 获取文件展示名
* 获取用户上传文件展示名
*
* @return
*/
String getDisplayName();
/**
* 设置文件展示名
* 设置用户上传文件的文件展示名
*
* @param displayName
*/
void setDisplayName(String displayName);
/**
* 获取服务器端文件所在的目录
*
* @return
*/
DataSetResDirectory getDataSetResDirectory();
/**
* 设置服务器端文件所在的目录
*
* @param dataSetResDirectory
*/
void setDataSetResDirectory(DataSetResDirectory dataSetResDirectory);
/**
* 获取服务器端文件的文件名相对于{@linkplain #getDataSetResDirectory()}
*
* @return
*/
String getDataSetResFileName();
/**
* 设置服务器端文件的文件名相对于{@linkplain #getDataSetResDirectory()}
*
* @param fileName
*/
void setDataSetResFileName(String fileName);
/**
* 将文件名作为<code>Freemarker</code>模板解析
* <p>
* 实现规则应与{@linkplain AbstractDataSet#resolveAsFmkTemplate(String, Map)}一致
* </p>
*
* @param fileName
* @param paramValues
* @return
*/
String resolveFileNameAsFmkTemplate(String fileName, Map<String, ?> paramValues);
FileSupport FILE_SUPPORT = new FileSupport();
class FileSupport
{
public File getFile(DirectoryFileDataSetEntity entity, Map<String, ?> paramValues) throws Throwable
{
File file = null;
if (FILE_SOURCE_TYPE_UPLOAD.equals(entity.getFileSourceType()))
file = FileUtil.getFile(entity.getDirectory(), entity.getFileName());
else if (FILE_SOURCE_TYPE_SERVER.equals(entity.getFileSourceType()))
{
// 服务器端文件名允许参数化
String fileName = entity.resolveFileNameAsFmkTemplate(entity.getDataSetResFileName(), paramValues);
File directory = FileUtil.getDirectory(entity.getDataSetResDirectory().getDirectory(), false);
file = FileUtil.getFile(directory, fileName, false);
}
else
throw new IllegalStateException("Unknown file source type :" + entity.getFileSourceType());
return file;
}
}
}

View File

@ -10,8 +10,10 @@ package org.datagear.management.domain;
import java.io.File;
import java.util.Date;
import java.util.List;
import java.util.Map;
import org.datagear.analysis.DataSetProperty;
import org.datagear.analysis.support.AbstractExcelDataSet;
import org.datagear.analysis.support.ExcelDirectoryFileDataSet;
/**
@ -20,37 +22,101 @@ import org.datagear.analysis.support.ExcelDirectoryFileDataSet;
* @author datagear@163.com
*
*/
public class ExcelDataSetEntity extends ExcelDirectoryFileDataSet implements DirectoryFileDataSetEntity
public class ExcelDataSetEntity extends AbstractExcelDataSet implements DirectoryFileDataSetEntity
{
private static final long serialVersionUID = 1L;
/** 文件源类型 */
private String fileSourceType;
/** 上传文件所在的目录 */
private File directory = null;
/** 上传文件名 */
private String fileName = "";
/** 展示名 */
private String displayName;
private String displayName = "";
/** 服务器端文件所在的目录 */
private DataSetResDirectory dataSetResDirectory = null;
/** 服务器端文件的文件名(相对于{@linkplain #getDataSetResDirectory()} */
private String dataSetResFileName = "";
/** 创建用户 */
private User createUser;
/** 创建时间 */
private Date createTime;
private Date createTime = new Date();
/** 权限 */
private int dataPermission = PERMISSION_NOT_LOADED;
private AnalysisProject analysisProject = null;
public ExcelDataSetEntity()
{
super();
this.createTime = new Date();
}
public ExcelDataSetEntity(String id, String name, List<DataSetProperty> properties, File directory, String fileName,
String displayName, User createUser)
{
super(id, name, properties, directory, fileName);
super(id, name, properties);
this.fileSourceType = FILE_SOURCE_TYPE_UPLOAD;
this.directory = directory;
this.fileName = fileName;
this.displayName = displayName;
this.createTime = new Date();
this.createUser = createUser;
}
public ExcelDataSetEntity(String id, String name, List<DataSetProperty> properties,
DataSetResDirectory dataSetResDirectory, String dataSetResFileName, User createUser)
{
super(id, name, properties);
this.fileSourceType = FILE_SOURCE_TYPE_SERVER;
this.dataSetResDirectory = dataSetResDirectory;
this.dataSetResFileName = dataSetResFileName;
this.createUser = createUser;
}
@Override
public String getFileSourceType()
{
return fileSourceType;
}
@Override
public void setFileSourceType(String fileSourceType)
{
this.fileSourceType = fileSourceType;
}
@Override
public File getDirectory()
{
return directory;
}
@Override
public void setDirectory(File directory)
{
this.directory = directory;
}
@Override
public String getFileName()
{
return fileName;
}
@Override
public void setFileName(String fileName)
{
this.fileName = fileName;
}
@Override
public String getDisplayName()
{
@ -63,6 +129,30 @@ public class ExcelDataSetEntity extends ExcelDirectoryFileDataSet implements Dir
this.displayName = displayName;
}
@Override
public DataSetResDirectory getDataSetResDirectory()
{
return dataSetResDirectory;
}
@Override
public void setDataSetResDirectory(DataSetResDirectory dataSetResDirectory)
{
this.dataSetResDirectory = dataSetResDirectory;
}
@Override
public String getDataSetResFileName()
{
return dataSetResFileName;
}
@Override
public void setDataSetResFileName(String dataSetResFileName)
{
this.dataSetResFileName = dataSetResFileName;
}
@Override
public String getDataSetType()
{
@ -111,4 +201,28 @@ public class ExcelDataSetEntity extends ExcelDirectoryFileDataSet implements Dir
{
this.dataPermission = dataPermission;
}
@Override
public AnalysisProject getAnalysisProject()
{
return analysisProject;
}
@Override
public void setAnalysisProject(AnalysisProject analysisProject)
{
this.analysisProject = analysisProject;
}
@Override
public String resolveFileNameAsFmkTemplate(String fileName, Map<String, ?> paramValues)
{
return resolveAsFmkTemplate(fileName, paramValues);
}
@Override
protected File getExcelFile(Map<String, ?> paramValues) throws Throwable
{
return FILE_SUPPORT.getFile(this, paramValues);
}
}

View File

@ -26,7 +26,7 @@ import com.fasterxml.jackson.annotation.JsonIgnore;
*
*/
public class HtmlChartWidgetEntity extends HtmlChartWidget
implements CreateUserEntity<String>, DataPermissionEntity<String>
implements CreateUserEntity<String>, DataPermissionEntity<String>, AnalysisProjectAwareEntity<String>
{
private static final long serialVersionUID = 1L;
@ -44,6 +44,8 @@ public class HtmlChartWidgetEntity extends HtmlChartWidget
/** 权限 */
private int dataPermission = PERMISSION_NOT_LOADED;
private AnalysisProject analysisProject = null;
/** 插件名称,展示用 */
private String chartPluginName = "";
@ -117,6 +119,18 @@ public class HtmlChartWidgetEntity extends HtmlChartWidget
this.dataPermission = dataPermission;
}
@Override
public AnalysisProject getAnalysisProject()
{
return analysisProject;
}
@Override
public void setAnalysisProject(AnalysisProject analysisProject)
{
this.analysisProject = analysisProject;
}
public String getChartPluginName()
{
return chartPluginName;

View File

@ -22,7 +22,7 @@ import org.datagear.util.StringUtil;
*
*/
public class HtmlTplDashboardWidgetEntity extends HtmlTplDashboardWidget
implements CreateUserEntity<String>, DataPermissionEntity<String>
implements CreateUserEntity<String>, DataPermissionEntity<String>, AnalysisProjectAwareEntity<String>
{
private static final long serialVersionUID = 1L;
@ -45,6 +45,8 @@ public class HtmlTplDashboardWidgetEntity extends HtmlTplDashboardWidget
/** 权限 */
private int dataPermission = PERMISSION_NOT_LOADED;
private AnalysisProject analysisProject = null;
public HtmlTplDashboardWidgetEntity()
{
super();
@ -104,6 +106,18 @@ public class HtmlTplDashboardWidgetEntity extends HtmlTplDashboardWidget
this.dataPermission = dataPermission;
}
@Override
public AnalysisProject getAnalysisProject()
{
return analysisProject;
}
@Override
public void setAnalysisProject(AnalysisProject analysisProject)
{
this.analysisProject = analysisProject;
}
/**
* 返回{@linkplain #getTemplates()}的JSON
*

View File

@ -33,6 +33,8 @@ public class HttpDataSetEntity extends HttpDataSet implements DataSetEntity
/** 权限 */
private int dataPermission = PERMISSION_NOT_LOADED;
private AnalysisProject analysisProject = null;
public HttpDataSetEntity()
{
super();
@ -102,4 +104,16 @@ public class HttpDataSetEntity extends HttpDataSet implements DataSetEntity
{
this.dataPermission = dataPermission;
}
@Override
public AnalysisProject getAnalysisProject()
{
return analysisProject;
}
@Override
public void setAnalysisProject(AnalysisProject analysisProject)
{
this.analysisProject = analysisProject;
}
}

View File

@ -10,8 +10,10 @@ package org.datagear.management.domain;
import java.io.File;
import java.util.Date;
import java.util.List;
import java.util.Map;
import org.datagear.analysis.DataSetProperty;
import org.datagear.analysis.support.AbstractJsonFileDataSet;
import org.datagear.analysis.support.JsonDirectoryFileDataSet;
/**
@ -20,22 +22,39 @@ import org.datagear.analysis.support.JsonDirectoryFileDataSet;
* @author datagear@163.com
*
*/
public class JsonFileDataSetEntity extends JsonDirectoryFileDataSet implements DirectoryFileDataSetEntity
public class JsonFileDataSetEntity extends AbstractJsonFileDataSet implements DirectoryFileDataSetEntity
{
private static final long serialVersionUID = 1L;
/** 文件源类型 */
private String fileSourceType;
/** 上传文件所在的目录 */
private File directory = null;
/** 上传文件名 */
private String fileName = "";
/** 展示名 */
private String displayName;
private String displayName = "";
/** 服务器端文件所在的目录 */
private DataSetResDirectory dataSetResDirectory = null;
/** 服务器端文件的文件名(相对于{@linkplain #getDataSetResDirectory()} */
private String dataSetResFileName = "";
/** 创建用户 */
private User createUser;
/** 创建时间 */
private Date createTime;
private Date createTime = new Date();
/** 权限 */
private int dataPermission = PERMISSION_NOT_LOADED;
private AnalysisProject analysisProject = null;
public JsonFileDataSetEntity()
{
super();
@ -45,12 +64,61 @@ public class JsonFileDataSetEntity extends JsonDirectoryFileDataSet implements D
public JsonFileDataSetEntity(String id, String name, List<DataSetProperty> properties, File directory,
String fileName, String displayName, User createUser)
{
super(id, name, properties, directory, fileName);
super(id, name, properties);
this.fileSourceType = FILE_SOURCE_TYPE_UPLOAD;
this.directory = directory;
this.fileName = fileName;
this.displayName = displayName;
this.createUser = createUser;
}
public JsonFileDataSetEntity(String id, String name, List<DataSetProperty> properties,
DataSetResDirectory dataSetResDirectory, String dataSetResFileName, User createUser)
{
super(id, name, properties);
this.fileSourceType = FILE_SOURCE_TYPE_SERVER;
this.dataSetResDirectory = dataSetResDirectory;
this.dataSetResFileName = dataSetResFileName;
this.createTime = new Date();
this.createUser = createUser;
}
@Override
public String getFileSourceType()
{
return fileSourceType;
}
@Override
public void setFileSourceType(String fileSourceType)
{
this.fileSourceType = fileSourceType;
}
@Override
public File getDirectory()
{
return directory;
}
@Override
public void setDirectory(File directory)
{
this.directory = directory;
}
@Override
public String getFileName()
{
return fileName;
}
@Override
public void setFileName(String fileName)
{
this.fileName = fileName;
}
@Override
public String getDisplayName()
{
@ -63,6 +131,30 @@ public class JsonFileDataSetEntity extends JsonDirectoryFileDataSet implements D
this.displayName = displayName;
}
@Override
public DataSetResDirectory getDataSetResDirectory()
{
return dataSetResDirectory;
}
@Override
public void setDataSetResDirectory(DataSetResDirectory dataSetResDirectory)
{
this.dataSetResDirectory = dataSetResDirectory;
}
@Override
public String getDataSetResFileName()
{
return dataSetResFileName;
}
@Override
public void setDataSetResFileName(String dataSetResFileName)
{
this.dataSetResFileName = dataSetResFileName;
}
@Override
public String getDataSetType()
{
@ -111,4 +203,28 @@ public class JsonFileDataSetEntity extends JsonDirectoryFileDataSet implements D
{
this.dataPermission = dataPermission;
}
@Override
public AnalysisProject getAnalysisProject()
{
return analysisProject;
}
@Override
public void setAnalysisProject(AnalysisProject analysisProject)
{
this.analysisProject = analysisProject;
}
@Override
public String resolveFileNameAsFmkTemplate(String fileName, Map<String, ?> paramValues)
{
return resolveAsFmkTemplate(fileName, paramValues);
}
@Override
protected File getJsonFile(Map<String, ?> paramValues) throws Throwable
{
return FILE_SUPPORT.getFile(this, paramValues);
}
}

View File

@ -32,6 +32,8 @@ public class JsonValueDataSetEntity extends JsonValueDataSet implements DataSetE
/** 权限 */
private int dataPermission = PERMISSION_NOT_LOADED;
private AnalysisProject analysisProject = null;
public JsonValueDataSetEntity()
{
super();
@ -94,4 +96,16 @@ public class JsonValueDataSetEntity extends JsonValueDataSet implements DataSetE
{
this.dataPermission = dataPermission;
}
@Override
public AnalysisProject getAnalysisProject()
{
return analysisProject;
}
@Override
public void setAnalysisProject(AnalysisProject analysisProject)
{
this.analysisProject = analysisProject;
}
}

View File

@ -33,6 +33,8 @@ public class SqlDataSetEntity extends SqlDataSet implements DataSetEntity
/** 权限 */
private int dataPermission = PERMISSION_NOT_LOADED;
private AnalysisProject analysisProject = null;
public SqlDataSetEntity()
{
super();
@ -120,4 +122,16 @@ public class SqlDataSetEntity extends SqlDataSet implements DataSetEntity
{
this.dataPermission = dataPermission;
}
@Override
public AnalysisProject getAnalysisProject()
{
return analysisProject;
}
@Override
public void setAnalysisProject(AnalysisProject analysisProject)
{
this.analysisProject = analysisProject;
}
}

View File

@ -37,6 +37,8 @@ public class SummaryDataSetEntity extends AbstractDataSet implements DataSetEnti
private int dataPermission = PERMISSION_NOT_LOADED;
private AnalysisProject analysisProject = null;
public SummaryDataSetEntity()
{
super();
@ -100,6 +102,18 @@ public class SummaryDataSetEntity extends AbstractDataSet implements DataSetEnti
this.dataPermission = dataPermission;
}
@Override
public AnalysisProject getAnalysisProject()
{
return analysisProject;
}
@Override
public void setAnalysisProject(AnalysisProject analysisProject)
{
this.analysisProject = analysisProject;
}
@Override
public DataSetResult getResult(Map<String, ?> paramValues) throws DataSetException
{

View File

@ -0,0 +1,37 @@
/*
* Copyright (c) 2018 datagear.tech. All Rights Reserved.
*/
/**
*
*/
package org.datagear.management.service;
import org.datagear.management.domain.AnalysisProjectAwareEntity;
import org.datagear.management.domain.User;
import org.datagear.persistence.PagingData;
import org.datagear.persistence.PagingQuery;
/**
* {@linkplain AnalysisProjectAwareEntity}业务服务接口
*
* @author datagear@163.com
*
*/
public interface AnalysisProjectAwareEntityService<T>
{
String QUERY_PARAM_ANALYSIS_PROJECT_ID = "_analysisProjectId";
/**
* 授权分页查询
*
* @param user
* 操作用户
* @param pagingQuery
* @param dataFilter
* @param analysisProjectId
* 允许为{@code null}
* @return
*/
PagingData<T> pagingQuery(User user, PagingQuery pagingQuery, String dataFilter, String analysisProjectId);
}

View File

@ -0,0 +1,19 @@
/*
* Copyright 2018 datagear.tech. All Rights Reserved.
*/
package org.datagear.management.service;
import org.datagear.management.domain.AnalysisProject;
/**
* {@linkplain AnalysisProject}业务服务接口
*
* @author datagear@163.com
*
*/
public interface AnalysisProjectService
extends DataPermissionEntityService<String, AnalysisProject>, CreateUserEntityService
{
}

View File

@ -53,6 +53,16 @@ public interface DataPermissionEntityService<ID, T extends DataPermissionEntity<
/** 查询过滤值:全部 */
String DATA_FILTER_VALUE_ALL = "all";
/**
* {@linkplain DataPermissionEntity#getDataPermission()}的权限值标识表明未加载实际权限值
*/
int PERMISSION_NOT_LOADED = -9;
/**
* {@linkplain #getPermission(User, Object)}{@linkplain #getPermissions(User, Object[])}的返回权限值标识表明指定ID的记录未找到
*/
int PERMISSION_NOT_FOUND = -11;
/**
* 获取数据权限资源类型
*
@ -68,7 +78,7 @@ public interface DataPermissionEntityService<ID, T extends DataPermissionEntity<
*
* @param user
* @param id
* @return
* @return 可能返回{@linkplain #PERMISSION_NOT_FOUND}
*/
int getPermission(User user, ID id);
@ -80,7 +90,7 @@ public interface DataPermissionEntityService<ID, T extends DataPermissionEntity<
*
* @param user
* @param ids
* @return
* @return 返回元素可能{@linkplain #PERMISSION_NOT_FOUND}
*/
int[] getPermissions(User user, ID[] ids);
@ -180,7 +190,8 @@ public interface DataPermissionEntityService<ID, T extends DataPermissionEntity<
/**
* 授权分页查询
*
* @param user 操作用户
* @param user
* 操作用户
* @param pagingQuery
* @param dataFilter
* @return

View File

@ -11,7 +11,9 @@ import java.io.File;
import org.apache.hc.client5.http.classic.HttpClient;
import org.datagear.analysis.DataSet;
import org.datagear.analysis.support.ProfileDataSet;
import org.datagear.management.domain.DataSetEntity;
import org.datagear.management.domain.User;
/**
* {@linkplain DataSetEntity}业务服务接口
@ -19,8 +21,8 @@ import org.datagear.management.domain.DataSetEntity;
* @author datagear@163.com
*
*/
public interface DataSetEntityService
extends DataPermissionEntityService<String, DataSetEntity>, CreateUserEntityService
public interface DataSetEntityService extends DataPermissionEntityService<String, DataSetEntity>,
CreateUserEntityService, AnalysisProjectAwareEntityService<DataSetEntity>
{
/**
* 获取可用于执行分析的{@linkplain DataSet}
@ -30,6 +32,15 @@ public interface DataSetEntityService
*/
DataSet getDataSet(String id);
/**
* 获取指定ID的{@linkplain ProfileDataSet}
*
* @param user
* @param id
* @return
*/
ProfileDataSet getProfileDataSet(User user, String id);
/**
* 获取指定ID的文件存储目录
*

View File

@ -0,0 +1,19 @@
/*
* Copyright 2018 datagear.tech. All Rights Reserved.
*/
package org.datagear.management.service;
import org.datagear.management.domain.DataSetResDirectory;
/**
* {@linkplain DataSetResDirectory}业务服务接口
*
* @author datagear@163.com
*
*/
public interface DataSetResDirectoryService
extends DataPermissionEntityService<String, DataSetResDirectory>, CreateUserEntityService
{
}

View File

@ -17,8 +17,8 @@ import org.datagear.management.domain.User;
* @author datagear@163.com
*
*/
public interface HtmlChartWidgetEntityService
extends DataPermissionEntityService<String, HtmlChartWidgetEntity>, ChartWidgetSource, CreateUserEntityService
public interface HtmlChartWidgetEntityService extends DataPermissionEntityService<String, HtmlChartWidgetEntity>,
ChartWidgetSource, CreateUserEntityService, AnalysisProjectAwareEntityService<HtmlChartWidgetEntity>
{
/**
* {@linkplain ChartWidgetSource}上下文

View File

@ -19,7 +19,8 @@ import org.datagear.management.domain.User;
*
*/
public interface HtmlTplDashboardWidgetEntityService
extends DataPermissionEntityService<String, HtmlTplDashboardWidgetEntity>, CreateUserEntityService
extends DataPermissionEntityService<String, HtmlTplDashboardWidgetEntity>, CreateUserEntityService,
AnalysisProjectAwareEntityService<HtmlTplDashboardWidgetEntity>
{
/**
* 获取渲染器

View File

@ -14,6 +14,7 @@ import org.datagear.management.domain.Authorization;
import org.datagear.management.domain.DataIdPermission;
import org.datagear.management.domain.DataPermissionEntity;
import org.datagear.management.domain.User;
import org.datagear.management.service.AnalysisProjectAwareEntityService;
import org.datagear.management.service.DataPermissionEntityService;
import org.datagear.management.service.PermissionDeniedException;
import org.datagear.persistence.PagingData;
@ -49,10 +50,10 @@ public abstract class AbstractMybatisDataPermissionEntityService<ID, T extends D
@Override
public int getPermission(User user, ID id)
{
List<ID> ids = new ArrayList<ID>(1);
List<ID> ids = new ArrayList<>(1);
ids.add(id);
List<Integer> permissions = getPermissions(user, ids, Authorization.PERMISSION_NONE_START);
List<Integer> permissions = getPermissions(user, ids, PERMISSION_NOT_FOUND);
return permissions.get(0);
}
@ -62,7 +63,7 @@ public abstract class AbstractMybatisDataPermissionEntityService<ID, T extends D
{
List<ID> idList = Arrays.asList(ids);
List<Integer> permissions = getPermissions(user, idList, Authorization.PERMISSION_NONE_START);
List<Integer> permissions = getPermissions(user, idList, PERMISSION_NOT_FOUND);
int[] re = new int[permissions.size()];
@ -132,6 +133,11 @@ public abstract class AbstractMybatisDataPermissionEntityService<ID, T extends D
@Override
public T getById(User user, ID id) throws PermissionDeniedException
{
return getById(user, id, true);
}
protected T getById(User user, ID id, boolean postProcessSelect) throws PermissionDeniedException
{
int permission = getPermission(user, id);
@ -141,7 +147,7 @@ public abstract class AbstractMybatisDataPermissionEntityService<ID, T extends D
Map<String, Object> params = buildParamMap();
addDataPermissionParameters(params, user);
return getById(id, params);
return getById(id, params, postProcessSelect);
}
@Override
@ -178,9 +184,26 @@ public abstract class AbstractMybatisDataPermissionEntityService<ID, T extends D
{
Map<String, Object> params = buildParamMap();
addDataPermissionParameters(params, user);
setDataFilterParam(params, dataFilter);
return pagingQuery(pagingQuery, params);
}
protected void setDataFilterParam(Map<String, Object> params, String dataFilter)
{
if (!StringUtil.isEmpty(dataFilter))
params.put("_dataFilter", dataFilter);
}
protected PagingData<T> pagingQueryForAnalysisProjectId(User user, PagingQuery pagingQuery, String dataFilter,
String analysisProjectId)
{
Map<String, Object> params = buildParamMap();
addDataPermissionParameters(params, user);
setDataFilterParam(params, dataFilter);
if (!StringUtil.isEmpty(analysisProjectId))
params.put(AnalysisProjectAwareEntityService.QUERY_PARAM_ANALYSIS_PROJECT_ID, analysisProjectId);
return pagingQuery(pagingQuery, params);
}
@ -201,7 +224,7 @@ public abstract class AbstractMybatisDataPermissionEntityService<ID, T extends D
List<DataIdPermission> dataPermissions = selectListMybatis("getDataIdPermissions", params);
List<Integer> re = new ArrayList<Integer>(ids.size());
List<Integer> re = new ArrayList<>(ids.size());
for (int i = 0, len = ids.size(); i < len; i++)
{

View File

@ -91,18 +91,37 @@ public abstract class AbstractMybatisEntityService<ID, T extends Entity<ID>> ext
/**
* 获取
* <p>
* 此方法内部会执行{@linkplain #postProcessSelect(Object)}
* </p>
*
* @param id
* @param params
* @return
*/
protected T getById(ID id, Map<String, Object> params)
{
return getById(id, params, true);
}
/**
* 获取
*
* @param id
* @param params
* @param postProcessSelect
* 是否内部执行{@linkplain #postProcessSelect(Object)}
* @return
*/
protected T getById(ID id, Map<String, Object> params, boolean postProcessSelect)
{
addIdentifierQuoteParameter(params);
params.put("id", id);
T entity = selectOneMybatis("getById", params);
entity = postProcessSelect(entity);
if (postProcessSelect)
entity = postProcessSelect(entity);
return entity;
}

View File

@ -0,0 +1,90 @@
/*
* Copyright 2018 datagear.tech. All Rights Reserved.
*/
package org.datagear.management.service.impl;
import java.util.Map;
import org.apache.ibatis.session.SqlSessionFactory;
import org.datagear.management.domain.AnalysisProject;
import org.datagear.management.domain.User;
import org.datagear.management.service.AnalysisProjectService;
import org.datagear.management.service.PermissionDeniedException;
import org.mybatis.spring.SqlSessionTemplate;
/**
* {@linkplain AnalysisProjectService}实现类
*
* @author datagear@163.com
*
*/
public class AnalysisProjectServiceImpl extends AbstractMybatisDataPermissionEntityService<String, AnalysisProject>
implements AnalysisProjectService
{
protected static final String SQL_NAMESPACE = AnalysisProject.class.getName();
public AnalysisProjectServiceImpl()
{
super();
}
public AnalysisProjectServiceImpl(SqlSessionFactory sqlSessionFactory)
{
super(sqlSessionFactory);
}
public AnalysisProjectServiceImpl(SqlSessionTemplate sqlSessionTemplate)
{
super(sqlSessionTemplate);
}
@Override
public String getResourceType()
{
return AnalysisProject.AUTHORIZATION_RESOURCE_TYPE;
}
@Override
public AnalysisProject getByStringId(User user, String id) throws PermissionDeniedException
{
return getById(user, id);
}
@Override
public int updateCreateUserId(String oldUserId, String newUserId)
{
Map<String, Object> params = buildParamMap();
addIdentifierQuoteParameter(params);
params.put("oldUserId", oldUserId);
params.put("newUserId", newUserId);
return updateMybatis("updateCreateUserId", params);
}
@Override
protected void checkAddInput(AnalysisProject entity)
{
if (isBlank(entity.getId()) || isBlank(entity.getName()) || isEmpty(entity.getCreateUser()))
throw new IllegalArgumentException();
}
@Override
protected void checkUpdateInput(AnalysisProject entity)
{
if (isBlank(entity.getId()) || isBlank(entity.getName()))
throw new IllegalArgumentException();
}
@Override
protected void addDataPermissionParameters(Map<String, Object> params, User user)
{
addDataPermissionParameters(params, user, getResourceType(), false, true);
}
@Override
protected String getSqlNamespace()
{
return SQL_NAMESPACE;
}
}

View File

@ -17,7 +17,10 @@ import org.apache.ibatis.session.SqlSessionFactory;
import org.datagear.analysis.DataSet;
import org.datagear.analysis.DataSetParam;
import org.datagear.analysis.DataSetProperty;
import org.datagear.analysis.support.ProfileDataSet;
import org.datagear.connection.ConnectionSource;
import org.datagear.management.domain.AnalysisProject;
import org.datagear.management.domain.AnalysisProjectAwareEntity;
import org.datagear.management.domain.CsvFileDataSetEntity;
import org.datagear.management.domain.CsvValueDataSetEntity;
import org.datagear.management.domain.DataSetEntity;
@ -33,6 +36,8 @@ import org.datagear.management.service.AuthorizationService;
import org.datagear.management.service.DataSetEntityService;
import org.datagear.management.service.PermissionDeniedException;
import org.datagear.management.service.SchemaService;
import org.datagear.persistence.PagingData;
import org.datagear.persistence.PagingQuery;
import org.datagear.util.FileUtil;
import org.mybatis.spring.SqlSessionTemplate;
@ -162,6 +167,19 @@ public class DataSetEntityServiceImpl extends AbstractMybatisDataPermissionEntit
return entity;
}
@Override
public ProfileDataSet getProfileDataSet(User user, String id)
{
ProfileDataSet profileDataSet = null;
DataSetEntity entity = getById(user, id, false);
inflateParamsAndProperties(entity);
profileDataSet = ProfileDataSet.valueOf(entity);
return profileDataSet;
}
@Override
public int updateCreateUserId(String oldUserId, String newUserId)
{
@ -173,6 +191,13 @@ public class DataSetEntityServiceImpl extends AbstractMybatisDataPermissionEntit
return updateMybatis("updateCreateUserId", params);
}
@Override
public PagingData<DataSetEntity> pagingQuery(User user, PagingQuery pagingQuery, String dataFilter,
String analysisProjectId)
{
return pagingQueryForAnalysisProjectId(user, pagingQuery, dataFilter, analysisProjectId);
}
@Override
protected boolean add(DataSetEntity entity, Map<String, Object> params)
{
@ -387,6 +412,8 @@ public class DataSetEntityServiceImpl extends AbstractMybatisDataPermissionEntit
if (obj == null)
return null;
DataSetEntity initObj = obj;
if (DataSetEntity.DATA_SET_TYPE_SQL.equals(obj.getDataSetType()))
obj = getSqlDataSetEntityById(obj.getId());
else if (DataSetEntity.DATA_SET_TYPE_JsonValue.equals(obj.getDataSetType()))
@ -405,18 +432,29 @@ public class DataSetEntityServiceImpl extends AbstractMybatisDataPermissionEntit
if (obj == null)
return null;
// 这里必须设置全限值为了效率上述子类的底层查询并未返回全限值
obj.setDataPermission(initObj.getDataPermission());
inflateParamsAndProperties(obj);
return obj;
}
protected void inflateParamsAndProperties(DataSetEntity dataSetEntity)
{
if (dataSetEntity == null)
return;
Map<String, Object> params = buildParamMapWithIdentifierQuoteParameter();
params.put("dataSetId", obj.getId());
params.put("dataSetId", dataSetEntity.getId());
List<DataSetPropertyPO> propertyPOs = selectListMybatis("getPropertyPOs", params);
List<DataSetProperty> dataSetProperties = DataSetPropertyPO.to(propertyPOs);
obj.setProperties(dataSetProperties);
dataSetEntity.setProperties(dataSetProperties);
List<DataSetParamPO> paramPOs = selectListMybatis("getParamPOs", params);
List<DataSetParam> dataSetParams = DataSetParamPO.to(paramPOs);
obj.setParams(dataSetParams);
return obj;
dataSetEntity.setParams(dataSetParams);
}
protected SqlDataSetEntity getSqlDataSetEntityById(String id)
@ -504,6 +542,8 @@ public class DataSetEntityServiceImpl extends AbstractMybatisDataPermissionEntit
@Override
protected void addDataPermissionParameters(Map<String, Object> params, User user)
{
params.put(AnalysisProjectAwareEntity.DATA_PERMISSION_PARAM_RESOURCE_TYPE_ANALYSIS_PROJECT,
AnalysisProject.AUTHORIZATION_RESOURCE_TYPE);
addDataPermissionParameters(params, user, getResourceType(), false, true);
}

View File

@ -0,0 +1,91 @@
/*
* Copyright 2018 datagear.tech. All Rights Reserved.
*/
package org.datagear.management.service.impl;
import java.util.Map;
import org.apache.ibatis.session.SqlSessionFactory;
import org.datagear.management.domain.DataSetResDirectory;
import org.datagear.management.domain.User;
import org.datagear.management.service.DataSetResDirectoryService;
import org.datagear.management.service.PermissionDeniedException;
import org.mybatis.spring.SqlSessionTemplate;
/**
* {@linkplain DataSetResDirectoryService}实现类
*
* @author datagear@163.com
*
*/
public class DataSetResDirectoryServiceImpl
extends AbstractMybatisDataPermissionEntityService<String, DataSetResDirectory>
implements DataSetResDirectoryService
{
protected static final String SQL_NAMESPACE = DataSetResDirectory.class.getName();
public DataSetResDirectoryServiceImpl()
{
super();
}
public DataSetResDirectoryServiceImpl(SqlSessionFactory sqlSessionFactory)
{
super(sqlSessionFactory);
}
public DataSetResDirectoryServiceImpl(SqlSessionTemplate sqlSessionTemplate)
{
super(sqlSessionTemplate);
}
@Override
public String getResourceType()
{
return DataSetResDirectory.AUTHORIZATION_RESOURCE_TYPE;
}
@Override
public DataSetResDirectory getByStringId(User user, String id) throws PermissionDeniedException
{
return getById(user, id);
}
@Override
public int updateCreateUserId(String oldUserId, String newUserId)
{
Map<String, Object> params = buildParamMap();
addIdentifierQuoteParameter(params);
params.put("oldUserId", oldUserId);
params.put("newUserId", newUserId);
return updateMybatis("updateCreateUserId", params);
}
@Override
protected void checkAddInput(DataSetResDirectory entity)
{
if (isBlank(entity.getId()) || isBlank(entity.getDirectory()) || isEmpty(entity.getCreateUser()))
throw new IllegalArgumentException();
}
@Override
protected void checkUpdateInput(DataSetResDirectory entity)
{
if (isBlank(entity.getId()) || isBlank(entity.getDirectory()))
throw new IllegalArgumentException();
}
@Override
protected void addDataPermissionParameters(Map<String, Object> params, User user)
{
addDataPermissionParameters(params, user, getResourceType(), false, true);
}
@Override
protected String getSqlNamespace()
{
return SQL_NAMESPACE;
}
}

View File

@ -23,6 +23,8 @@ import org.datagear.analysis.DataSet;
import org.datagear.analysis.support.ChartWidget;
import org.datagear.analysis.support.JsonSupport;
import org.datagear.analysis.support.html.HtmlChartPlugin;
import org.datagear.management.domain.AnalysisProject;
import org.datagear.management.domain.AnalysisProjectAwareEntity;
import org.datagear.management.domain.ChartDataSetVO;
import org.datagear.management.domain.HtmlChartWidgetEntity;
import org.datagear.management.domain.User;
@ -30,6 +32,8 @@ import org.datagear.management.service.AuthorizationService;
import org.datagear.management.service.DataSetEntityService;
import org.datagear.management.service.HtmlChartWidgetEntityService;
import org.datagear.management.service.PermissionDeniedException;
import org.datagear.persistence.PagingData;
import org.datagear.persistence.PagingQuery;
import org.datagear.util.StringUtil;
import org.mybatis.spring.SqlSessionTemplate;
@ -149,6 +153,13 @@ public class HtmlChartWidgetEntityServiceImpl
return updateMybatis("updateCreateUserId", params);
}
@Override
public PagingData<HtmlChartWidgetEntity> pagingQuery(User user, PagingQuery pagingQuery, String dataFilter,
String analysisProjectId)
{
return pagingQueryForAnalysisProjectId(user, pagingQuery, dataFilter, analysisProjectId);
}
@Override
protected boolean add(HtmlChartWidgetEntity entity, Map<String, Object> params)
{
@ -221,6 +232,8 @@ public class HtmlChartWidgetEntityServiceImpl
@Override
protected void addDataPermissionParameters(Map<String, Object> params, User user)
{
params.put(AnalysisProjectAwareEntity.DATA_PERMISSION_PARAM_RESOURCE_TYPE_ANALYSIS_PROJECT,
AnalysisProject.AUTHORIZATION_RESOURCE_TYPE);
addDataPermissionParameters(params, user, getResourceType(), false, true);
}

View File

@ -12,11 +12,15 @@ import java.util.Map;
import org.apache.ibatis.session.SqlSessionFactory;
import org.datagear.analysis.support.html.HtmlTplDashboardWidgetRenderer;
import org.datagear.management.domain.AnalysisProject;
import org.datagear.management.domain.AnalysisProjectAwareEntity;
import org.datagear.management.domain.HtmlTplDashboardWidgetEntity;
import org.datagear.management.domain.User;
import org.datagear.management.service.AuthorizationService;
import org.datagear.management.service.HtmlTplDashboardWidgetEntityService;
import org.datagear.management.service.PermissionDeniedException;
import org.datagear.persistence.PagingData;
import org.datagear.persistence.PagingQuery;
import org.mybatis.spring.SqlSessionTemplate;
/**
@ -111,6 +115,13 @@ public class HtmlTplDashboardWidgetEntityServiceImpl
return updateMybatis("updateCreateUserId", params);
}
@Override
public PagingData<HtmlTplDashboardWidgetEntity> pagingQuery(User user, PagingQuery pagingQuery, String dataFilter,
String analysisProjectId)
{
return pagingQueryForAnalysisProjectId(user, pagingQuery, dataFilter, analysisProjectId);
}
@Override
protected boolean add(HtmlTplDashboardWidgetEntity entity, Map<String, Object> params)
{
@ -158,6 +169,8 @@ public class HtmlTplDashboardWidgetEntityServiceImpl
@Override
protected void addDataPermissionParameters(Map<String, Object> params, User user)
{
params.put(AnalysisProjectAwareEntity.DATA_PERMISSION_PARAM_RESOURCE_TYPE_ANALYSIS_PROJECT,
AnalysisProject.AUTHORIZATION_RESOURCE_TYPE);
addDataPermissionParameters(params, user, getResourceType(), false, true);
}

View File

@ -579,3 +579,96 @@ CREATE TABLE DATAGEAR_DATA_SET_HTTP
);
ALTER TABLE DATAGEAR_DATA_SET_HTTP ADD FOREIGN KEY (DS_ID) REFERENCES DATAGEAR_DATA_SET (DS_ID) ON DELETE CASCADE;
-----------------------------------------
--version[1.13.0], DO NOT EDIT THIS LINE!
-----------------------------------------
--2020-09-22
--
CREATE TABLE DATAGEAR_ANALYSIS_PROJECT
(
AP_ID VARCHAR(50) NOT NULL,
AP_NAME VARCHAR(100) NOT NULL,
AP_DESC VARCHAR(500),
AP_CREATE_USER_ID VARCHAR(50),
AP_CREATE_TIME TIMESTAMP,
PRIMARY KEY (AP_ID)
);
ALTER TABLE DATAGEAR_DATA_SET ADD COLUMN DS_AP_ID VARCHAR(50);
ALTER TABLE DATAGEAR_HTML_CHART_WIDGET ADD COLUMN HCW_AP_ID VARCHAR(50);
ALTER TABLE DATAGEAR_HTML_DASHBOARD ADD COLUMN HD_AP_ID VARCHAR(50);
--2020-09-25
--
ALTER TABLE DATAGEAR_DATA_SET ADD FOREIGN KEY (DS_AP_ID) REFERENCES DATAGEAR_ANALYSIS_PROJECT (AP_ID);
ALTER TABLE DATAGEAR_HTML_CHART_WIDGET ADD FOREIGN KEY (HCW_AP_ID) REFERENCES DATAGEAR_ANALYSIS_PROJECT (AP_ID);
ALTER TABLE DATAGEAR_HTML_DASHBOARD ADD FOREIGN KEY (HD_AP_ID) REFERENCES DATAGEAR_ANALYSIS_PROJECT (AP_ID);
--2020-09-25
--
CREATE INDEX DATAGEAR_DATA_SET_CREATE_USER_ID ON DATAGEAR_DATA_SET(DS_CREATE_USER_ID);
CREATE INDEX DATAGEAR_HTML_CHART_WIDGET_CREATE_USER_ID ON DATAGEAR_HTML_CHART_WIDGET(HCW_CREATE_USER_ID);
CREATE INDEX DATAGEAR_HTML_DASHBOARD_CREATE_USER_ID ON DATAGEAR_HTML_DASHBOARD(HD_CREATE_USER_ID);
--2020-09-26
--
CREATE TABLE DATAGEAR_DSR_DIRECTORY
(
DD_ID VARCHAR(50) NOT NULL,
DD_DIRECTORY VARCHAR(250) NOT NULL,
DD_DESC VARCHAR(500),
DD_CREATE_USER_ID VARCHAR(50),
DD_CREATE_TIME TIMESTAMP,
PRIMARY KEY (DD_ID)
);
--2020-09-26
--
ALTER TABLE DATAGEAR_DATA_SET_JSON_FILE ADD COLUMN DS_FILE_SOURCE_TYPE VARCHAR(50);
ALTER TABLE DATAGEAR_DATA_SET_JSON_FILE ADD COLUMN DS_DSRD_ID VARCHAR(50);
ALTER TABLE DATAGEAR_DATA_SET_JSON_FILE ADD COLUMN DS_DSRD_FILE_NAME VARCHAR(500);
ALTER TABLE DATAGEAR_DATA_SET_JSON_FILE ADD FOREIGN KEY (DS_DSRD_ID) REFERENCES DATAGEAR_DSR_DIRECTORY (DD_ID);
--UPLOAD类型
UPDATE DATAGEAR_DATA_SET_JSON_FILE SET DS_FILE_SOURCE_TYPE = 'UPLOAD';
ALTER TABLE DATAGEAR_DATA_SET_JSON_FILE ALTER COLUMN DS_FILE_SOURCE_TYPE SET NOT NULL;
ALTER TABLE DATAGEAR_DATA_SET_EXCEL ADD COLUMN DS_FILE_SOURCE_TYPE VARCHAR(50);
ALTER TABLE DATAGEAR_DATA_SET_EXCEL ADD COLUMN DS_DSRD_ID VARCHAR(50);
ALTER TABLE DATAGEAR_DATA_SET_EXCEL ADD COLUMN DS_DSRD_FILE_NAME VARCHAR(500);
ALTER TABLE DATAGEAR_DATA_SET_EXCEL ADD FOREIGN KEY (DS_DSRD_ID) REFERENCES DATAGEAR_DSR_DIRECTORY (DD_ID);
--UPLOAD类型
UPDATE DATAGEAR_DATA_SET_EXCEL SET DS_FILE_SOURCE_TYPE = 'UPLOAD';
ALTER TABLE DATAGEAR_DATA_SET_EXCEL ALTER COLUMN DS_FILE_SOURCE_TYPE SET NOT NULL;
ALTER TABLE DATAGEAR_DATA_SET_CSV_FILE ADD COLUMN DS_FILE_SOURCE_TYPE VARCHAR(50);
ALTER TABLE DATAGEAR_DATA_SET_CSV_FILE ADD COLUMN DS_DSRD_ID VARCHAR(50);
ALTER TABLE DATAGEAR_DATA_SET_CSV_FILE ADD COLUMN DS_DSRD_FILE_NAME VARCHAR(500);
ALTER TABLE DATAGEAR_DATA_SET_CSV_FILE ADD FOREIGN KEY (DS_DSRD_ID) REFERENCES DATAGEAR_DSR_DIRECTORY (DD_ID);
--UPLOAD类型
UPDATE DATAGEAR_DATA_SET_CSV_FILE SET DS_FILE_SOURCE_TYPE = 'UPLOAD';
ALTER TABLE DATAGEAR_DATA_SET_CSV_FILE ALTER COLUMN DS_FILE_SOURCE_TYPE SET NOT NULL;

View File

@ -0,0 +1,187 @@
<?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="org.datagear.management.domain.AnalysisProject">
<insert id="insert">
INSERT INTO DATAGEAR_ANALYSIS_PROJECT
(
AP_ID, AP_NAME, AP_DESC, AP_CREATE_USER_ID, AP_CREATE_TIME
)
VALUES
(
#{entity.id}, #{entity.name}, #{entity.desc}, #{entity.createUser.id}, #{entity.createTime}
)
</insert>
<update id="update">
UPDATE DATAGEAR_ANALYSIS_PROJECT SET
AP_NAME = #{entity.name},
AP_DESC = #{entity.desc}
WHERE
AP_ID = #{entity.id}
</update>
<update id="updateCreateUserId">
UPDATE DATAGEAR_ANALYSIS_PROJECT SET
AP_CREATE_USER_ID = #{newUserId}
WHERE
AP_CREATE_USER_ID = #{oldUserId}
</update>
<delete id="deleteById">
DELETE FROM DATAGEAR_ANALYSIS_PROJECT
WHERE
AP_ID = #{id}
</delete>
<select id="getById" resultType="org.datagear.management.domain.AnalysisProject">
SELECT
T.*
FROM
(<include refid="queryViewDataPermission" />) T
WHERE
T.${_iq_}id${_iq_} = #{id}
</select>
<select id="getDataIdPermissions" resultType="org.datagear.management.domain.DataIdPermission">
SELECT
T.DATA_ID as ${_iq_}dataId${_iq_},
T.DATA_PERMISSION as ${_iq_}dataPermission${_iq_}
FROM
(
<include refid="commonDataPermission.dataIdPermissionQueryViewHead" />
<include refid="queryViewDataPermissionId" />
<include refid="commonDataPermission.dataIdPermissionQueryViewFoot" />
) T
WHERE
<foreach item="item" collection="ids" separator=" OR ">T.DATA_ID = #{item}</foreach>
</select>
<select id="query" resultType="org.datagear.management.domain.AnalysisProject">
SELECT
T.*
FROM
(<include refid="queryViewDataPermission" />) T
WHERE
<include refid="queryCondition" />
<include refid="common.queryOrder" />
</select>
<select id="pagingQueryCount" resultType="int">
SELECT
COUNT(*)
FROM
(<include refid="queryViewDataPermission" />) T
WHERE
<include refid="queryCondition" />
</select>
<select id="pagingQuery" resultType="org.datagear.management.domain.AnalysisProject">
<include refid="common.pagingQueryHead" />
SELECT
T.*
FROM
(<include refid="queryViewDataPermission" />) T
WHERE
<include refid="queryCondition" />
<include refid="common.queryOrder" />
<include refid="common.pagingQueryFoot" />
</select>
<sql id="queryViewDataPermission">
<choose><when test="DP_CURRENT_USER == null">
<include refid="queryView" />
</when><otherwise>
SELECT
T0.*,
T1.DATA_PERMISSION as ${_iq_}dataPermission${_iq_}
FROM
(<include refid="queryView" />) T0
INNER JOIN
(
<include refid="commonDataPermission.dataIdPermissionQueryViewHead" />
<include refid="queryViewDataPermissionId" />
<include refid="commonDataPermission.dataIdPermissionQueryViewFoot" />
) T1
ON
T0.${_iq_}id${_iq_} = T1.DATA_ID
WHERE
T1.DATA_PERMISSION >= ${DP_MIN_READ_PERMISSION}
</otherwise></choose>
</sql>
<sql id="queryViewDataPermissionId">
SELECT
A.AP_ID AS DP_AUTH_DATA_ID,
A.AP_CREATE_USER_ID AS DP_AUTH_DATA_CREATOR_ID
FROM
DATAGEAR_ANALYSIS_PROJECT A
</sql>
<sql id="queryView">
SELECT
A.AP_ID AS ${_iq_}id${_iq_},
A.AP_NAME AS ${_iq_}name${_iq_},
A.AP_DESC AS ${_iq_}desc${_iq_},
A.AP_CREATE_TIME AS ${_iq_}createTime${_iq_},
A.AP_CREATE_USER_ID AS ${_iq_}createUser.id${_iq_},
<include refid="common.fieldsForCreateUser" />
FROM
DATAGEAR_ANALYSIS_PROJECT A
LEFT JOIN
DATAGEAR_USER USR
ON
A.AP_CREATE_USER_ID = USR.USER_ID
</sql>
<sql id="queryCondition">
1 = 1
<if test="queryKeyword != null">
AND
(
${_iq_}name${_iq_} LIKE #{queryKeyword}
OR ${_iq_}desc${_iq_} LIKE #{queryKeyword}
)
</if>
<include refid="commonDataPermission.dataFilterCondition" />
<include refid="common.queryCondition" />
</sql>
<!--
用于外部Mapper引用的公用SQL下面的include必须采用全名不然会出现死循环。
注意:
为了提高查询效率,这里仅查询必要的列
-->
<sql id="queryViewForAnalysisProjectAwareEntity">
SELECT
A.AP_ID AS ${_iq_}analysisProject.id${_iq_},
A.AP_NAME AS ${_iq_}analysisProject.name${_iq_},
A.AP_CREATE_TIME AS ${_iq_}analysisProject.createTime${_iq_},
A.AP_CREATE_USER_ID AS ${_iq_}analysisProject.createUser.id${_iq_}
FROM
DATAGEAR_ANALYSIS_PROJECT A
</sql>
<!--
用于外部AnalysisProjectAwareEntity实体处理权限级联引用的公用SQL下面的include必须采用全名不然会出现死循环。
注意:
引用方必须传递DP_RESOURCE_TYPE_ANALYSIS_PROJECT参数且值为AnalysisProject.AUTHORIZATION_RESOURCE_TYPE
因为此SQL片段通常作为第二处数据权限片段被引入会出现DP_RESOURCE_TYPE冲突而导致逻辑出错。
-->
<sql id="queryViewIdPermissionForAnalysisProjectAwareEntity">
<bind name="DP_RESOURCE_TYPE" value="DP_RESOURCE_TYPE_ANALYSIS_PROJECT"/>
SELECT
T.DATA_ID as AP_ID,
T.DATA_PERMISSION
FROM
(
<include refid="commonDataPermission.dataIdPermissionQueryViewHead" />
<include refid="org.datagear.management.domain.AnalysisProject.queryViewDataPermissionId" />
<include refid="commonDataPermission.dataIdPermissionQueryViewFoot" />
) T
WHERE
T.DATA_PERMISSION >= ${DP_MIN_READ_PERMISSION}
</sql>
</mapper>

View File

@ -6,11 +6,13 @@
<insert id="insert">
INSERT INTO DATAGEAR_DATA_SET
(
DS_ID, DS_NAME, DS_TYPE, DS_CREATE_USER_ID, DS_CREATE_TIME
DS_ID, DS_NAME, DS_TYPE, DS_CREATE_USER_ID, DS_CREATE_TIME,
DS_AP_ID
)
VALUES
(
#{entity.id}, #{entity.name}, #{entity.dataSetType}, #{entity.createUser.id}, #{entity.createTime}
#{entity.id}, #{entity.name}, #{entity.dataSetType}, #{entity.createUser.id}, #{entity.createTime},
#{entity.analysisProject.id, jdbcType=VARCHAR}
)
</insert>
@ -39,11 +41,13 @@
<insert id="insertJsonFileDataSetEntity">
INSERT INTO DATAGEAR_DATA_SET_JSON_FILE
(
DS_ID, DS_FILE_NAME, DS_FILE_ENCODING, DS_DISPLAY_NAME, DS_DATA_JSON_PATH
DS_ID, DS_FILE_NAME, DS_FILE_ENCODING, DS_DISPLAY_NAME, DS_DATA_JSON_PATH,
DS_FILE_SOURCE_TYPE, DS_DSRD_ID, DS_DSRD_FILE_NAME
)
VALUES
(
#{entity.id}, #{entity.fileName}, #{entity.encoding}, #{entity.displayName}, #{entity.dataJsonPath}
#{entity.id}, #{entity.fileName}, #{entity.encoding}, #{entity.displayName}, #{entity.dataJsonPath},
#{entity.fileSourceType}, #{entity.dataSetResDirectory.id, jdbcType=VARCHAR}, #{entity.dataSetResFileName}
)
</insert>
@ -51,12 +55,14 @@
INSERT INTO DATAGEAR_DATA_SET_EXCEL
(
DS_ID, DS_FILE_NAME, DS_DISPLAY_NAME, DS_SHEET_INDEX, DS_NAME_ROW,
DS_DATA_ROW_EXP, DS_DATA_COLUMN_EXP, DS_FORCE_XLS
DS_DATA_ROW_EXP, DS_DATA_COLUMN_EXP, DS_FORCE_XLS,
DS_FILE_SOURCE_TYPE, DS_DSRD_ID, DS_DSRD_FILE_NAME
)
VALUES
(
#{entity.id}, #{entity.fileName}, #{entity.displayName}, #{entity.sheetIndex}, #{entity.nameRow},
#{entity.dataRowExp}, #{entity.dataColumnExp}, #{entity.forceXls}
#{entity.dataRowExp}, #{entity.dataColumnExp}, #{entity.forceXls},
#{entity.fileSourceType}, #{entity.dataSetResDirectory.id, jdbcType=VARCHAR}, #{entity.dataSetResFileName}
)
</insert>
@ -74,11 +80,13 @@
<insert id="insertCsvFileDataSetEntity">
INSERT INTO DATAGEAR_DATA_SET_CSV_FILE
(
DS_ID, DS_FILE_NAME, DS_FILE_ENCODING, DS_DISPLAY_NAME, DS_NAME_ROW
DS_ID, DS_FILE_NAME, DS_FILE_ENCODING, DS_DISPLAY_NAME, DS_NAME_ROW,
DS_FILE_SOURCE_TYPE, DS_DSRD_ID, DS_DSRD_FILE_NAME
)
VALUES
(
#{entity.id}, #{entity.fileName}, #{entity.encoding}, #{entity.displayName}, #{entity.nameRow}
#{entity.id}, #{entity.fileName}, #{entity.encoding}, #{entity.displayName}, #{entity.nameRow},
#{entity.fileSourceType}, #{entity.dataSetResDirectory.id, jdbcType=VARCHAR}, #{entity.dataSetResFileName}
)
</insert>
@ -121,7 +129,8 @@
<update id="update">
UPDATE DATAGEAR_DATA_SET SET
DS_NAME = #{entity.name}
DS_NAME = #{entity.name},
DS_AP_ID = #{entity.analysisProject.id, jdbcType=VARCHAR}
WHERE
DS_ID = #{entity.id}
</update>
@ -153,7 +162,10 @@
DS_FILE_NAME = #{entity.fileName},
DS_FILE_ENCODING = #{entity.encoding},
DS_DISPLAY_NAME = #{entity.displayName},
DS_DATA_JSON_PATH = #{entity.dataJsonPath}
DS_DATA_JSON_PATH = #{entity.dataJsonPath},
DS_FILE_SOURCE_TYPE = #{entity.fileSourceType},
DS_DSRD_ID = #{entity.dataSetResDirectory.id, jdbcType=VARCHAR},
DS_DSRD_FILE_NAME = #{entity.dataSetResFileName}
WHERE
DS_ID = #{entity.id}
</update>
@ -166,7 +178,10 @@
DS_NAME_ROW = #{entity.nameRow},
DS_DATA_ROW_EXP = #{entity.dataRowExp},
DS_DATA_COLUMN_EXP = #{entity.dataColumnExp},
DS_FORCE_XLS = #{entity.forceXls}
DS_FORCE_XLS = #{entity.forceXls},
DS_FILE_SOURCE_TYPE = #{entity.fileSourceType},
DS_DSRD_ID = #{entity.dataSetResDirectory.id, jdbcType=VARCHAR},
DS_DSRD_FILE_NAME = #{entity.dataSetResFileName}
WHERE
DS_ID = #{entity.id}
</update>
@ -184,7 +199,10 @@
DS_FILE_NAME = #{entity.fileName},
DS_FILE_ENCODING = #{entity.encoding},
DS_DISPLAY_NAME = #{entity.displayName},
DS_NAME_ROW = #{entity.nameRow}
DS_NAME_ROW = #{entity.nameRow},
DS_FILE_SOURCE_TYPE = #{entity.fileSourceType},
DS_DSRD_ID = #{entity.dataSetResDirectory.id, jdbcType=VARCHAR},
DS_DSRD_FILE_NAME = #{entity.dataSetResFileName}
WHERE
DS_ID = #{entity.id}
</update>
@ -266,13 +284,21 @@
T2.DS_FILE_NAME AS ${_iq_}fileName${_iq_},
T2.DS_FILE_ENCODING AS ${_iq_}encoding${_iq_},
T2.DS_DISPLAY_NAME AS ${_iq_}displayName${_iq_},
T2.DS_DATA_JSON_PATH AS ${_iq_}dataJsonPath${_iq_}
T2.DS_DATA_JSON_PATH AS ${_iq_}dataJsonPath${_iq_},
T2.DS_FILE_SOURCE_TYPE AS ${_iq_}fileSourceType${_iq_},
T2.DS_DSRD_ID AS ${_iq_}dataSetResDirectory.id${_iq_},
T2.DS_DSRD_FILE_NAME AS ${_iq_}dataSetResFileName${_iq_},
DSRD.DD_DIRECTORY AS ${_iq_}dataSetResDirectory.directory${_iq_}
FROM
(SELECT * FROM (<include refid="queryView" />) T0 WHERE T0.${_iq_}id${_iq_} = #{id}) T1
INNER JOIN
DATAGEAR_DATA_SET_JSON_FILE T2
ON
T1.${_iq_}id${_iq_} = T2.DS_ID
LEFT JOIN
DATAGEAR_DSR_DIRECTORY DSRD
ON
T2.DS_DSRD_ID = DSRD.DD_ID
</select>
<select id="getExcelDataSetEntityById" resultType="org.datagear.management.domain.ExcelDataSetEntity">
@ -280,18 +306,25 @@
T1.*,
T2.DS_FILE_NAME AS ${_iq_}fileName${_iq_},
T2.DS_DISPLAY_NAME AS ${_iq_}displayName${_iq_},
T2.DS_SHEET_INDEX AS ${_iq_}sheetIndex${_iq_},
T2.DS_NAME_ROW AS ${_iq_}nameRow${_iq_},
T2.DS_DATA_ROW_EXP AS ${_iq_}dataRowExp${_iq_},
T2.DS_DATA_COLUMN_EXP AS ${_iq_}dataColumnExp${_iq_},
T2.DS_FORCE_XLS AS ${_iq_}forceXls${_iq_}
T2.DS_FORCE_XLS AS ${_iq_}forceXls${_iq_},
T2.DS_FILE_SOURCE_TYPE AS ${_iq_}fileSourceType${_iq_},
T2.DS_DSRD_ID AS ${_iq_}dataSetResDirectory.id${_iq_},
T2.DS_DSRD_FILE_NAME AS ${_iq_}dataSetResFileName${_iq_},
DSRD.DD_DIRECTORY AS ${_iq_}dataSetResDirectory.directory${_iq_}
FROM
(SELECT * FROM (<include refid="queryView" />) T0 WHERE T0.${_iq_}id${_iq_} = #{id}) T1
INNER JOIN
DATAGEAR_DATA_SET_EXCEL T2
ON
T1.${_iq_}id${_iq_} = T2.DS_ID
LEFT JOIN
DATAGEAR_DSR_DIRECTORY DSRD
ON
T2.DS_DSRD_ID = DSRD.DD_ID
</select>
<select id="getCsvValueDataSetEntityById" resultType="org.datagear.management.domain.CsvValueDataSetEntity">
@ -313,13 +346,21 @@
T2.DS_FILE_NAME AS ${_iq_}fileName${_iq_},
T2.DS_FILE_ENCODING AS ${_iq_}encoding${_iq_},
T2.DS_DISPLAY_NAME AS ${_iq_}displayName${_iq_},
T2.DS_NAME_ROW AS ${_iq_}nameRow${_iq_}
T2.DS_NAME_ROW AS ${_iq_}nameRow${_iq_},
T2.DS_FILE_SOURCE_TYPE AS ${_iq_}fileSourceType${_iq_},
T2.DS_DSRD_ID AS ${_iq_}dataSetResDirectory.id${_iq_},
T2.DS_DSRD_FILE_NAME AS ${_iq_}dataSetResFileName${_iq_},
DSRD.DD_DIRECTORY AS ${_iq_}dataSetResDirectory.directory${_iq_}
FROM
(SELECT * FROM (<include refid="queryView" />) T0 WHERE T0.${_iq_}id${_iq_} = #{id}) T1
INNER JOIN
DATAGEAR_DATA_SET_CSV_FILE T2
ON
T1.${_iq_}id${_iq_} = T2.DS_ID
LEFT JOIN
DATAGEAR_DSR_DIRECTORY DSRD
ON
T2.DS_DSRD_ID = DSRD.DD_ID
</select>
<select id="getHttpDataSetEntityById" resultType="org.datagear.management.domain.HttpDataSetEntity">
@ -379,11 +420,7 @@
T.DATA_ID as ${_iq_}dataId${_iq_},
T.DATA_PERMISSION as ${_iq_}dataPermission${_iq_}
FROM
(
<include refid="commonDataPermission.dataIdPermissionQueryViewHead" />
<include refid="queryViewDataPermissionId" />
<include refid="commonDataPermission.dataIdPermissionQueryViewFoot" />
) T
(<include refid="queryViewDataIdPermission" />) T
WHERE
<foreach item="item" collection="ids" separator=" OR ">T.DATA_ID = #{item}</foreach>
</select>
@ -428,17 +465,41 @@
T1.DATA_PERMISSION as ${_iq_}dataPermission${_iq_}
FROM
(<include refid="queryView" />) T0
INNER JOIN
INNER JOIN
(<include refid="queryViewDataIdPermission" />) T1
ON
T0.${_iq_}id${_iq_} = T1.DATA_ID
WHERE
T1.DATA_PERMISSION IS NOT NULL AND T1.DATA_PERMISSION >= ${DP_MIN_READ_PERMISSION}
</otherwise></choose>
</sql>
<sql id="queryViewDataIdPermission">
SELECT
T0.DS_ID AS DATA_ID,
(
CASE
WHEN T2.DATA_PERMISSION IS NULL THEN T1.DATA_PERMISSION
WHEN T1.DATA_PERMISSION >= ${DP_MIN_READ_PERMISSION} THEN T1.DATA_PERMISSION
ELSE T2.DATA_PERMISSION
END
) AS DATA_PERMISSION
FROM
DATAGEAR_DATA_SET T0
LEFT JOIN
(
<include refid="commonDataPermission.dataIdPermissionQueryViewHead" />
<include refid="queryViewDataPermissionId" />
<include refid="commonDataPermission.dataIdPermissionQueryViewFoot" />
) T1
ON
T0.${_iq_}id${_iq_} = T1.DATA_ID
WHERE
T1.DATA_PERMISSION >= ${DP_MIN_READ_PERMISSION}
</otherwise></choose>
T0.DS_ID = T1.DATA_ID
LEFT JOIN
(
<include refid="org.datagear.management.domain.AnalysisProject.queryViewIdPermissionForAnalysisProjectAwareEntity" />
) T2
ON
T0.DS_AP_ID = T2.AP_ID
</sql>
<sql id="queryViewDataPermissionId">
@ -456,13 +517,18 @@
A.DS_TYPE AS ${_iq_}dataSetType${_iq_},
A.DS_CREATE_USER_ID AS ${_iq_}createUser.id${_iq_},
<include refid="common.fieldsForCreateUser" />,
A.DS_CREATE_TIME AS ${_iq_}createTime${_iq_}
A.DS_CREATE_TIME AS ${_iq_}createTime${_iq_},
AP.*
FROM
DATAGEAR_DATA_SET A
LEFT JOIN
DATAGEAR_USER USR
ON
A.DS_CREATE_USER_ID = USR.USER_ID
LEFT JOIN
(<include refid="org.datagear.management.domain.AnalysisProject.queryViewForAnalysisProjectAwareEntity" />) AP
ON
A.DS_AP_ID = AP.${_iq_}analysisProject.id${_iq_}
</sql>
<sql id="queryCondition">
@ -470,9 +536,12 @@
<if test="queryKeyword != null">
AND
(
${_iq_}name${_iq_} LIKE #{queryKeyword}
${_iq_}name${_iq_} LIKE #{queryKeyword} OR ${_iq_}analysisProject.name${_iq_} LIKE #{queryKeyword}
)
</if>
<if test="_analysisProjectId != null">
AND ${_iq_}analysisProject.id${_iq_} = #{_analysisProjectId}
</if>
<include refid="commonDataPermission.dataFilterCondition" />
<include refid="common.queryCondition" />
</sql>

View File

@ -0,0 +1,151 @@
<?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="org.datagear.management.domain.DataSetResDirectory">
<insert id="insert">
INSERT INTO DATAGEAR_DSR_DIRECTORY
(
DD_ID, DD_DIRECTORY, DD_DESC, DD_CREATE_USER_ID, DD_CREATE_TIME
)
VALUES
(
#{entity.id}, #{entity.directory}, #{entity.desc}, #{entity.createUser.id}, #{entity.createTime}
)
</insert>
<update id="update">
UPDATE DATAGEAR_DSR_DIRECTORY SET
DD_DIRECTORY = #{entity.directory},
DD_DESC = #{entity.desc}
WHERE
DD_ID = #{entity.id}
</update>
<update id="updateCreateUserId">
UPDATE DATAGEAR_DSR_DIRECTORY SET
DD_CREATE_USER_ID = #{newUserId}
WHERE
DD_CREATE_USER_ID = #{oldUserId}
</update>
<delete id="deleteById">
DELETE FROM DATAGEAR_DSR_DIRECTORY
WHERE
DD_ID = #{id}
</delete>
<select id="getById" resultType="org.datagear.management.domain.DataSetResDirectory">
SELECT
T.*
FROM
(<include refid="queryViewDataPermission" />) T
WHERE
T.${_iq_}id${_iq_} = #{id}
</select>
<select id="getDataIdPermissions" resultType="org.datagear.management.domain.DataIdPermission">
SELECT
T.DATA_ID as ${_iq_}dataId${_iq_},
T.DATA_PERMISSION as ${_iq_}dataPermission${_iq_}
FROM
(
<include refid="commonDataPermission.dataIdPermissionQueryViewHead" />
<include refid="queryViewDataPermissionId" />
<include refid="commonDataPermission.dataIdPermissionQueryViewFoot" />
) T
WHERE
<foreach item="item" collection="ids" separator=" OR ">T.DATA_ID = #{item}</foreach>
</select>
<select id="query" resultType="org.datagear.management.domain.DataSetResDirectory">
SELECT
T.*
FROM
(<include refid="queryViewDataPermission" />) T
WHERE
<include refid="queryCondition" />
<include refid="common.queryOrder" />
</select>
<select id="pagingQueryCount" resultType="int">
SELECT
COUNT(*)
FROM
(<include refid="queryViewDataPermission" />) T
WHERE
<include refid="queryCondition" />
</select>
<select id="pagingQuery" resultType="org.datagear.management.domain.DataSetResDirectory">
<include refid="common.pagingQueryHead" />
SELECT
T.*
FROM
(<include refid="queryViewDataPermission" />) T
WHERE
<include refid="queryCondition" />
<include refid="common.queryOrder" />
<include refid="common.pagingQueryFoot" />
</select>
<sql id="queryViewDataPermission">
<choose><when test="DP_CURRENT_USER == null">
<include refid="queryView" />
</when><otherwise>
SELECT
T0.*,
T1.DATA_PERMISSION as ${_iq_}dataPermission${_iq_}
FROM
(<include refid="queryView" />) T0
INNER JOIN
(
<include refid="commonDataPermission.dataIdPermissionQueryViewHead" />
<include refid="queryViewDataPermissionId" />
<include refid="commonDataPermission.dataIdPermissionQueryViewFoot" />
) T1
ON
T0.${_iq_}id${_iq_} = T1.DATA_ID
WHERE
T1.DATA_PERMISSION >= ${DP_MIN_READ_PERMISSION}
</otherwise></choose>
</sql>
<sql id="queryViewDataPermissionId">
SELECT
A.DD_ID AS DP_AUTH_DATA_ID,
A.DD_CREATE_USER_ID AS DP_AUTH_DATA_CREATOR_ID
FROM
DATAGEAR_DSR_DIRECTORY A
</sql>
<sql id="queryView">
SELECT
A.DD_ID AS ${_iq_}id${_iq_},
A.DD_DIRECTORY AS ${_iq_}directory${_iq_},
A.DD_DESC AS ${_iq_}desc${_iq_},
A.DD_CREATE_TIME AS ${_iq_}createTime${_iq_},
A.DD_CREATE_USER_ID AS ${_iq_}createUser.id${_iq_},
<include refid="common.fieldsForCreateUser" />
FROM
DATAGEAR_DSR_DIRECTORY A
LEFT JOIN
DATAGEAR_USER USR
ON
A.DD_CREATE_USER_ID = USR.USER_ID
</sql>
<sql id="queryCondition">
1 = 1
<if test="queryKeyword != null">
AND
(
${_iq_}directory${_iq_} LIKE #{queryKeyword}
OR ${_iq_}desc${_iq_} LIKE #{queryKeyword}
)
</if>
<include refid="commonDataPermission.dataFilterCondition" />
<include refid="common.queryCondition" />
</sql>
</mapper>

View File

@ -7,12 +7,12 @@
INSERT INTO DATAGEAR_HTML_CHART_WIDGET
(
HCW_ID, HCW_NAME, HCW_PLUGIN_ID, HCW_UPDATE_INTERVAL, HCW_CREATE_USER_ID,
HCW_CREATE_TIME
HCW_CREATE_TIME, HCW_AP_ID
)
VALUES
(
#{entity.id}, #{entity.name}, #{entity.htmlChartPlugin.id}, #{entity.updateInterval}, #{entity.createUser.id},
#{entity.createTime}
#{entity.createTime}, #{entity.analysisProject.id, jdbcType=VARCHAR}
)
</insert>
@ -31,7 +31,8 @@
UPDATE DATAGEAR_HTML_CHART_WIDGET SET
HCW_NAME = #{entity.name},
HCW_PLUGIN_ID = #{entity.htmlChartPlugin.id},
HCW_UPDATE_INTERVAL = #{entity.updateInterval}
HCW_UPDATE_INTERVAL = #{entity.updateInterval},
HCW_AP_ID = #{entity.analysisProject.id, jdbcType=VARCHAR}
WHERE
HCW_ID = #{entity.id}
</update>
@ -83,11 +84,7 @@
T.DATA_ID as ${_iq_}dataId${_iq_},
T.DATA_PERMISSION as ${_iq_}dataPermission${_iq_}
FROM
(
<include refid="commonDataPermission.dataIdPermissionQueryViewHead" />
<include refid="queryViewDataPermissionId" />
<include refid="commonDataPermission.dataIdPermissionQueryViewFoot" />
) T
(<include refid="queryViewDataIdPermission" />) T
WHERE
<foreach item="item" collection="ids" separator=" OR ">T.DATA_ID = #{item}</foreach>
</select>
@ -133,16 +130,40 @@
FROM
(<include refid="queryView" />) T0
INNER JOIN
(<include refid="queryViewDataIdPermission" />) T1
ON
T0.${_iq_}id${_iq_} = T1.DATA_ID
WHERE
T1.DATA_PERMISSION IS NOT NULL AND T1.DATA_PERMISSION >= ${DP_MIN_READ_PERMISSION}
</otherwise></choose>
</sql>
<sql id="queryViewDataIdPermission">
SELECT
T0.HCW_ID AS DATA_ID,
(
CASE
WHEN T2.DATA_PERMISSION IS NULL THEN T1.DATA_PERMISSION
WHEN T1.DATA_PERMISSION >= ${DP_MIN_READ_PERMISSION} THEN T1.DATA_PERMISSION
ELSE T2.DATA_PERMISSION
END
) AS DATA_PERMISSION
FROM
DATAGEAR_HTML_CHART_WIDGET T0
LEFT JOIN
(
<include refid="commonDataPermission.dataIdPermissionQueryViewHead" />
<include refid="queryViewDataPermissionId" />
<include refid="commonDataPermission.dataIdPermissionQueryViewFoot" />
) T1
ON
T0.${_iq_}id${_iq_} = T1.DATA_ID
WHERE
T1.DATA_PERMISSION >= ${DP_MIN_READ_PERMISSION}
</otherwise></choose>
T0.HCW_ID = T1.DATA_ID
LEFT JOIN
(
<include refid="org.datagear.management.domain.AnalysisProject.queryViewIdPermissionForAnalysisProjectAwareEntity" />
) T2
ON
T0.HCW_AP_ID = T2.AP_ID
</sql>
<sql id="queryViewDataPermissionId">
@ -161,13 +182,18 @@
A.HCW_UPDATE_INTERVAL AS ${_iq_}updateInterval${_iq_},
A.HCW_CREATE_USER_ID AS ${_iq_}createUser.id${_iq_},
<include refid="common.fieldsForCreateUser" />,
A.HCW_CREATE_TIME AS ${_iq_}createTime${_iq_}
A.HCW_CREATE_TIME AS ${_iq_}createTime${_iq_},
AP.*
FROM
DATAGEAR_HTML_CHART_WIDGET A
LEFT JOIN
DATAGEAR_USER USR
ON
A.HCW_CREATE_USER_ID = USR.USER_ID
LEFT JOIN
(<include refid="org.datagear.management.domain.AnalysisProject.queryViewForAnalysisProjectAwareEntity" />) AP
ON
A.HCW_AP_ID = AP.${_iq_}analysisProject.id${_iq_}
</sql>
<sql id="queryCondition">
@ -176,8 +202,12 @@
AND
(
${_iq_}id${_iq_} LIKE #{queryKeyword} OR ${_iq_}name${_iq_} LIKE #{queryKeyword}
OR ${_iq_}analysisProject.name${_iq_} LIKE #{queryKeyword}
)
</if>
<if test="_analysisProjectId != null">
AND ${_iq_}analysisProject.id${_iq_} = #{_analysisProjectId}
</if>
<include refid="commonDataPermission.dataFilterCondition" />
<include refid="common.queryCondition" />
</sql>

View File

@ -7,12 +7,23 @@
INSERT INTO DATAGEAR_HTML_DASHBOARD
(
HD_ID, HD_NAME, HD_TEMPLATE, HD_TEMPLATE_ENCODING, HD_CREATE_USER_ID,
HD_CREATE_TIME
HD_CREATE_TIME, HD_AP_ID
)
VALUES
(
#{entity.id}, #{entity.name}, #{entity.templatesJson}, #{entity.templateEncoding}, #{entity.createUser.id},
#{entity.createTime}
#{entity.createTime}, #{entity.analysisProject.id, jdbcType=VARCHAR}
)
</insert>
<insert id="insertDataSetRelation">
INSERT INTO DATAGEAR_HD_DSF
(
HD_ID, DS_ID, DS_ORDER
)
VALUES
(
#{widgetId}, #{dataSetId}, #{order}
)
</insert>
@ -20,7 +31,8 @@
UPDATE DATAGEAR_HTML_DASHBOARD SET
HD_NAME = #{entity.name},
HD_TEMPLATE = #{entity.templatesJson},
HD_TEMPLATE_ENCODING = #{entity.templateEncoding}
HD_TEMPLATE_ENCODING = #{entity.templateEncoding},
HD_AP_ID = #{entity.analysisProject.id, jdbcType=VARCHAR}
WHERE
HD_ID = #{entity.id}
</update>
@ -38,6 +50,12 @@
HD_ID = #{id}
</delete>
<delete id="deleteDataSetRelationById">
DELETE FROM DATAGEAR_HD_DSF
WHERE
HD_ID = #{id}
</delete>
<select id="getById" resultType="org.datagear.management.domain.HtmlTplDashboardWidgetEntity">
SELECT
T.*
@ -52,11 +70,7 @@
T.DATA_ID as ${_iq_}dataId${_iq_},
T.DATA_PERMISSION as ${_iq_}dataPermission${_iq_}
FROM
(
<include refid="commonDataPermission.dataIdPermissionQueryViewHead" />
<include refid="queryViewDataPermissionId" />
<include refid="commonDataPermission.dataIdPermissionQueryViewFoot" />
) T
(<include refid="queryViewDataIdPermission" />) T
WHERE
<foreach item="item" collection="ids" separator=" OR ">T.DATA_ID = #{item}</foreach>
</select>
@ -92,23 +106,6 @@
<include refid="common.pagingQueryFoot" />
</select>
<delete id="deleteDataSetRelationById">
DELETE FROM DATAGEAR_HD_DSF
WHERE
HD_ID = #{id}
</delete>
<insert id="insertDataSetRelation">
INSERT INTO DATAGEAR_HD_DSF
(
HD_ID, DS_ID, DS_ORDER
)
VALUES
(
#{widgetId}, #{dataSetId}, #{order}
)
</insert>
<sql id="queryViewDataPermission">
<choose><when test="DP_CURRENT_USER == null">
<include refid="queryView" />
@ -119,16 +116,40 @@
FROM
(<include refid="queryView" />) T0
INNER JOIN
(<include refid="queryViewDataIdPermission" />) T1
ON
T0.${_iq_}id${_iq_} = T1.DATA_ID
WHERE
T1.DATA_PERMISSION >= ${DP_MIN_READ_PERMISSION}
</otherwise></choose>
</sql>
<sql id="queryViewDataIdPermission">
SELECT
T0.HD_ID AS DATA_ID,
(
CASE
WHEN T2.DATA_PERMISSION IS NULL THEN T1.DATA_PERMISSION
WHEN T1.DATA_PERMISSION >= ${DP_MIN_READ_PERMISSION} THEN T1.DATA_PERMISSION
ELSE T2.DATA_PERMISSION
END
) AS DATA_PERMISSION
FROM
DATAGEAR_HTML_DASHBOARD T0
LEFT JOIN
(
<include refid="commonDataPermission.dataIdPermissionQueryViewHead" />
<include refid="queryViewDataPermissionId" />
<include refid="commonDataPermission.dataIdPermissionQueryViewFoot" />
) T1
ON
T0.${_iq_}id${_iq_} = T1.DATA_ID
WHERE
T1.DATA_PERMISSION >= ${DP_MIN_READ_PERMISSION}
</otherwise></choose>
T0.HD_ID = T1.DATA_ID
LEFT JOIN
(
<include refid="org.datagear.management.domain.AnalysisProject.queryViewIdPermissionForAnalysisProjectAwareEntity" />
) T2
ON
T0.HD_AP_ID = T2.AP_ID
</sql>
<sql id="queryViewDataPermissionId">
@ -147,13 +168,18 @@
A.HD_TEMPLATE_ENCODING AS ${_iq_}templateEncoding${_iq_},
A.HD_CREATE_USER_ID AS ${_iq_}createUser.id${_iq_},
<include refid="common.fieldsForCreateUser" />,
A.HD_CREATE_TIME AS ${_iq_}createTime${_iq_}
A.HD_CREATE_TIME AS ${_iq_}createTime${_iq_},
AP.*
FROM
DATAGEAR_HTML_DASHBOARD A
LEFT JOIN
DATAGEAR_USER USR
ON
A.HD_CREATE_USER_ID = USR.USER_ID
LEFT JOIN
(<include refid="org.datagear.management.domain.AnalysisProject.queryViewForAnalysisProjectAwareEntity" />) AP
ON
A.HD_AP_ID = AP.${_iq_}analysisProject.id${_iq_}
</sql>
<sql id="queryCondition">
@ -162,8 +188,12 @@
AND
(
${_iq_}id${_iq_} LIKE #{queryKeyword} OR ${_iq_}name${_iq_} LIKE #{queryKeyword}
OR ${_iq_}analysisProject.name${_iq_} LIKE #{queryKeyword}
)
</if>
<if test="_analysisProjectId != null">
AND ${_iq_}analysisProject.id${_iq_} = #{_analysisProjectId}
</if>
<include refid="commonDataPermission.dataFilterCondition" />
<include refid="common.queryCondition" />
</sql>

View File

@ -6,7 +6,7 @@
<parent>
<groupId>org.datagear</groupId>
<artifactId>datagear</artifactId>
<version>1.12.0</version>
<version>1.13.0</version>
</parent>
<artifactId>datagear-meta</artifactId>

View File

@ -7,6 +7,8 @@ package org.datagear.meta;
import java.io.Serializable;
import java.util.Arrays;
import org.datagear.util.StringUtil;
/**
* 表键
*
@ -59,6 +61,26 @@ public abstract class AbstractKey implements Serializable
this.keyName = keyName;
}
/**
* 是否包含指定列名
*
* @param columnName
* @return
*/
public boolean containsColumnName(String columnName)
{
if (this.columnNames == null)
return false;
for (String cn : this.columnNames)
{
if (StringUtil.isEquals(cn, columnName))
return true;
}
return false;
}
@Override
public String toString()
{

View File

@ -542,7 +542,7 @@ public abstract class AbstractDevotedDBMetaResolver extends JdbcSupport implemen
{
Column column = readColumn(cn, metaData, schema, tableName, mrs);
column = postProcessColumn(cn, metaData, schema, tableName, column);
addColumn(columns, column);
addValidColumn(columns, column);
if (count != null && columns.size() == count)
break;
@ -698,7 +698,7 @@ public abstract class AbstractDevotedDBMetaResolver extends JdbcSupport implemen
if (StringUtil.isEmpty(keyName))
keyName = mrs.getString("PK_NAME", "");
addName(columnNames, columnName);
addValidName(columnNames, columnName);
}
if (!columnNames.isEmpty())
@ -748,6 +748,8 @@ public abstract class AbstractDevotedDBMetaResolver extends JdbcSupport implemen
while (rs.next())
{
@JDBCCompatiblity("某些驱动程序INDEX_NAME列可能为nul但COLUMN_NAME不为null此行应是有效的"
+ "而某些驱动程序会返回INDEX_NAME和COLUMN_NAME都为null的无效行所以这里统一先把它们整理出来下面再筛选过滤")
String keyName = mrs.getString("INDEX_NAME", "");
String columnName = mrs.getString("COLUMN_NAME", null);
@ -763,12 +765,12 @@ public abstract class AbstractDevotedDBMetaResolver extends JdbcSupport implemen
else
keyColumnNames = keyColumnNamess.get(myIndex);
addName(keyColumnNames, columnName);
addValidName(keyColumnNames, columnName);
}
}
catch (SQLException e)
{
LOGGER.warn("return null primary key object for exception", e);
LOGGER.warn("return null unique key object for exception", e);
@JDBCCompatiblity("当tableName是视图时某些驱动比如Oracle可能会抛出SQLSyntaxErrorException异常")
UniqueKey[] nullUniqueKeys = null;
@ -781,14 +783,24 @@ public abstract class AbstractDevotedDBMetaResolver extends JdbcSupport implemen
if (!keyNames.isEmpty())
{
uniqueKeys = new UniqueKey[keyNames.size()];
List<UniqueKey> uks = new ArrayList<>();
for (int i = 0; i < uniqueKeys.length; i++)
for (int i = 0; i < keyNames.size(); i++)
{
List<String> keyColumnNames = keyColumnNamess.get(i);
uniqueKeys[i] = new UniqueKey(keyColumnNames.toArray(new String[keyColumnNames.size()]));
uniqueKeys[i].setKeyName(keyNames.get(i));
// 忽略无效的
if (keyColumnNames.isEmpty())
continue;
UniqueKey uk = new UniqueKey(keyColumnNames.toArray(new String[keyColumnNames.size()]));
uk.setKeyName(keyNames.get(i));
uks.add(uk);
}
if (!uks.isEmpty())
uniqueKeys = uks.toArray(new UniqueKey[uks.size()]);
}
return uniqueKeys;
@ -839,8 +851,8 @@ public abstract class AbstractDevotedDBMetaResolver extends JdbcSupport implemen
primaryColumnNames = primaryColumnNamess.get(myIndex);
}
addName(columnNames, columnName);
addName(primaryColumnNames, primaryColumnName);
addValidName(columnNames, columnName);
addValidName(primaryColumnNames, primaryColumnName);
}
}
catch (SQLException e)
@ -879,8 +891,15 @@ public abstract class AbstractDevotedDBMetaResolver extends JdbcSupport implemen
return importKeys;
}
/**
* 添加非空且不重名的名称元素
*
* @param names
* @param name
* @return
*/
@JDBCCompatiblity("避免某些驱动程序的结果集出现非法或者重复项")
protected boolean addName(List<String> names, String name)
protected boolean addValidName(List<String> names, String name)
{
if (StringUtil.isEmpty(name) || names.indexOf(name) > -1)
return false;
@ -889,8 +908,15 @@ public abstract class AbstractDevotedDBMetaResolver extends JdbcSupport implemen
return true;
}
/**
* 添加非空且不重名的列元素
*
* @param columns
* @param column
* @return
*/
@JDBCCompatiblity("避免某些驱动程序的结果集出现非法或者重复项")
protected boolean addColumn(List<Column> columns, Column column)
protected boolean addValidColumn(List<Column> columns, Column column)
{
if (column == null || containsColumn(columns, column.getName()))
return false;

View File

@ -6,7 +6,7 @@
<parent>
<groupId>org.datagear</groupId>
<artifactId>datagear</artifactId>
<version>1.12.0</version>
<version>1.13.0</version>
</parent>
<artifactId>datagear-persistence</artifactId>

View File

@ -31,6 +31,7 @@ public interface SqlParamValueMapper
* @param table
* @param column
* @param value
* 允许为{@code null}
* @return
* @throws SqlParamValueMapperException
*/

View File

@ -15,6 +15,7 @@ import java.util.regex.Pattern;
import org.datagear.connection.ConnectionOption;
import org.datagear.meta.Column;
import org.datagear.meta.PrimaryKey;
import org.datagear.meta.Table;
import org.datagear.persistence.Dialect;
import org.datagear.persistence.DialectSource;
@ -28,6 +29,7 @@ import org.datagear.persistence.Query;
import org.datagear.persistence.Row;
import org.datagear.persistence.RowMapper;
import org.datagear.persistence.SqlParamValueMapper;
import org.datagear.util.JDBCCompatiblity;
import org.datagear.util.Sql;
import org.datagear.util.SqlParamValue;
import org.datagear.util.StringUtil;
@ -108,8 +110,13 @@ public class DefaultPersistenceManager extends PersistenceSupport implements Per
// 如果是自动生成列且没有初值才返回自动生成值因为即使自动生成列也是允许手动赋值的
if (column.isAutoincrement() && StringUtil.isEmpty(value))
{
autoGeneratedColumns.add(column);
// 忽略留给数据库自动生成
continue;
}
// 忽略不插入的列
if (!row.containsKey(name))
continue;
@ -170,9 +177,12 @@ public class DefaultPersistenceManager extends PersistenceSupport implements Per
Sql sql = Sql.valueOf().sql("UPDATE ").sql(quote(dialect, table.getName())).sql(" SET ").delimit(",");
Column[] columns = table.getColumns();
PrimaryKey primaryKey = table.getPrimaryKey();
try
{
int updateColumnCount = 0;
for (int i = 0; i < columns.length; i++)
{
Column column = columns[i];
@ -190,16 +200,34 @@ public class DefaultPersistenceManager extends PersistenceSupport implements Per
SqlParamValue sqlParamValue = mapToSqlParamValue(cn, table, column, value, mapper, releasableRegistry);
@JDBCCompatiblity("某些数据库存在不允许更新自增长列或者主键列的情况比如SQL Server的自增列因此如果这些列值没有改变则不应更新")
boolean checkIgnoreIfEquals = (column.isAutoincrement()
|| (primaryKey != null && primaryKey.containsColumnName(name)));
if (checkIgnoreIfEquals && StringUtil.isEquals(sqlParamValue.getValue(), origin.get(name)))
continue;
if (sqlParamValue instanceof LiteralSqlParamValue)
sql.sqld(quote(dialect, name) + "="
+ addBracketIfSelectSql(((LiteralSqlParamValue) sqlParamValue).getValue()));
else
sql.sqld(quote(dialect, name) + "=?").param(sqlParamValue);
updateColumnCount++;
}
// 即使updateColumnCount=0也执行下面这行SQL拼接操作确保必要的buildUniqueRecordCondition里面必要的校验逻辑执行到
sql.sql(" WHERE ").sql(buildUniqueRecordCondition(cn, dialect, table, origin, mapper, releasableRegistry));
return executeUpdateWrap(cn, sql);
if (updateColumnCount > 0)
{
return executeUpdateWrap(cn, sql);
}
else
{
// 没有需要更新的列时仍然返回1确保返回逻辑正确
return 1;
}
}
finally
{
@ -572,6 +600,7 @@ public class DefaultPersistenceManager extends PersistenceSupport implements Per
* @param table
* @param column
* @param value
* 允许为{@code null}
* @param mapper
* 允许为{@code null}
* @param releasableRegistry

View File

@ -7,7 +7,7 @@
<parent>
<groupId>org.datagear</groupId>
<artifactId>datagear</artifactId>
<version>1.12.0</version>
<version>1.13.0</version>
</parent>
<artifactId>datagear-util</artifactId>

View File

@ -21,7 +21,7 @@ public final class Global
}
/** 当前版本号 */
public static final String VERSION = "1.12.0";
public static final String VERSION = "1.13.0";
/** 中文产品名称 */
public static final String PRODUCT_NAME_ZH = "数据齿轮";

View File

@ -97,6 +97,23 @@ public class StringUtil
return false;
}
/**
* 判断两个对象是否相等
*
* @param a
* 允许为{@code null}
* @param b
* 允许为{@code null}
* @return
*/
public static boolean isEquals(Object a, Object b)
{
if (a == null)
return (b == null);
else
return a.equals(b);
}
/**
* 拆分字符串
*

View File

@ -6,7 +6,7 @@
<parent>
<groupId>org.datagear</groupId>
<artifactId>datagear</artifactId>
<version>1.12.0</version>
<version>1.13.0</version>
</parent>
<artifactId>datagear-web</artifactId>

View File

@ -19,6 +19,7 @@ import javax.servlet.Filter;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.HttpClients;
import org.apache.ibatis.session.SqlSessionFactory;
import org.cometd.bayeux.server.BayeuxServer;
import org.cometd.bayeux.server.BayeuxServer.Extension;
import org.cometd.server.ext.AcknowledgedMessagesExtension;
@ -47,9 +48,11 @@ import org.datagear.dataexchange.support.JsonDataImportService;
import org.datagear.dataexchange.support.SqlDataExportService;
import org.datagear.dataexchange.support.SqlDataImportService;
import org.datagear.management.dbversion.DbVersionManager;
import org.datagear.management.service.AnalysisProjectService;
import org.datagear.management.service.AuthorizationService;
import org.datagear.management.service.DataPermissionEntityService;
import org.datagear.management.service.DataSetEntityService;
import org.datagear.management.service.DataSetResDirectoryService;
import org.datagear.management.service.HtmlChartWidgetEntityService;
import org.datagear.management.service.HtmlTplDashboardWidgetEntityService;
import org.datagear.management.service.RoleService;
@ -57,8 +60,10 @@ import org.datagear.management.service.RoleUserService;
import org.datagear.management.service.SchemaService;
import org.datagear.management.service.SqlHistoryService;
import org.datagear.management.service.UserService;
import org.datagear.management.service.impl.AnalysisProjectServiceImpl;
import org.datagear.management.service.impl.AuthorizationServiceImpl;
import org.datagear.management.service.impl.DataSetEntityServiceImpl;
import org.datagear.management.service.impl.DataSetResDirectoryServiceImpl;
import org.datagear.management.service.impl.HtmlChartWidgetEntityServiceImpl;
import org.datagear.management.service.impl.HtmlTplDashboardWidgetEntityServiceImpl;
import org.datagear.management.service.impl.RoleServiceImpl;
@ -102,6 +107,7 @@ import org.datagear.web.util.WebContextPath;
import org.datagear.web.util.WebContextPathFilter;
import org.datagear.web.util.XmlDriverEntityManagerInitializer;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.springframework.beans.factory.BeanInitializationException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
@ -202,37 +208,37 @@ public class CoreConfiguration implements InitializingBean
}
@Bean
public File driverEntityManagerRootDirectory() throws IOException
public File driverEntityManagerRootDirectory()
{
return createDirectory(environment.getProperty("directory.driver"), true);
}
@Bean
public File tempDirectory() throws IOException
public File tempDirectory()
{
return createDirectory(environment.getProperty("directory.temp"), true);
}
@Bean
public File chartPluginRootDirectory() throws IOException
public File chartPluginRootDirectory()
{
return createDirectory(environment.getProperty("directory.chartPlugin"), true);
}
@Bean
public File dashboardRootDirectory() throws IOException
public File dashboardRootDirectory()
{
return createDirectory(environment.getProperty("directory.dashboard"), true);
}
@Bean
public File resetPasswordCheckFileDirectory() throws IOException
public File resetPasswordCheckFileDirectory()
{
return createDirectory(environment.getProperty("directory.resetPasswordCheckFile"), true);
}
@Bean
public File dataSetRootDirectory() throws IOException
public File dataSetRootDirectory()
{
return createDirectory(environment.getProperty("directory.dataSet"), true);
}
@ -243,12 +249,20 @@ public class CoreConfiguration implements InitializingBean
return HttpClients.createDefault();
}
protected File createDirectory(String directoryName, boolean createIfInexistence) throws IOException
protected File createDirectory(String directoryName, boolean createIfInexistence)
{
DirectoryFactory bean = new DirectoryFactory();
bean.setDirectoryName(directoryName);
bean.setCreateIfInexistence(createIfInexistence);
bean.init();
try
{
bean.init();
}
catch(IOException e)
{
throw new BeanInitializationException("Init directory [" + directoryName + "] failed", e);
}
return bean.getDirectory();
}
@ -268,14 +282,21 @@ public class CoreConfiguration implements InitializingBean
}
@Bean
public SqlSessionFactoryBean sqlSessionFactory()
public SqlSessionFactory sqlSessionFactory()
{
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(this.dataSourceConfiguration.dataSource());
bean.setMapperLocations(
new Resource[] { new ClassPathResource("classpath*:org/datagear/management/mapper/*.xml") });
return bean;
try
{
return bean.getObject();
}
catch(Exception e)
{
throw new BeanInitializationException("Init " + SqlSessionFactory.class + " failed", e);
}
}
@Bean
@ -286,14 +307,14 @@ public class CoreConfiguration implements InitializingBean
}
@Bean(destroyMethod = "releaseAll")
public XmlDriverEntityManager driverEntityManager() throws IOException
public XmlDriverEntityManager driverEntityManager()
{
XmlDriverEntityManager bean = new XmlDriverEntityManager(driverEntityManagerRootDirectory());
return bean;
}
@Bean(initMethod = "init")
public XmlDriverEntityManagerInitializer xmlDriverEntityManagerInitializer() throws IOException
public XmlDriverEntityManagerInitializer xmlDriverEntityManagerInitializer()
{
XmlDriverEntityManagerInitializer bean = new XmlDriverEntityManagerInitializer(this.driverEntityManager());
@ -301,7 +322,7 @@ public class CoreConfiguration implements InitializingBean
}
@Bean(destroyMethod = "close")
public ConnectionSource connectionSource() throws IOException
public ConnectionSource connectionSource()
{
DefaultConnectionSource bean = new DefaultConnectionSource(this.driverEntityManager());
bean.setDriverChecker(new SqlDriverChecker(this.dbMetaResolver()));
@ -357,56 +378,56 @@ public class CoreConfiguration implements InitializingBean
}
@Bean
public AuthorizationService authorizationService() throws Exception
public AuthorizationService authorizationService()
{
AuthorizationServiceImpl bean = new AuthorizationServiceImpl(this.sqlSessionFactory().getObject(),
AuthorizationServiceImpl bean = new AuthorizationServiceImpl(this.sqlSessionFactory(),
this.authorizationResourceServices());
return bean;
}
@Bean
public SchemaService schemaService() throws Exception
public SchemaService schemaService()
{
SchemaServiceImpl bean = new SchemaServiceImpl(this.sqlSessionFactory().getObject(), this.driverEntityManager(),
SchemaServiceImpl bean = new SchemaServiceImpl(this.sqlSessionFactory(), this.driverEntityManager(),
this.authorizationService());
return bean;
}
@Bean
public UserService userService() throws Exception
public UserService userService()
{
UserServiceImpl bean = new UserServiceImpl(this.sqlSessionFactory().getObject());
UserServiceImpl bean = new UserServiceImpl(this.sqlSessionFactory());
bean.setUserPasswordEncoder(this.userPasswordEncoder());
return bean;
}
@Bean
public RoleService roleService() throws Exception
public RoleService roleService()
{
RoleServiceImpl bean = new RoleServiceImpl(this.sqlSessionFactory().getObject());
RoleServiceImpl bean = new RoleServiceImpl(this.sqlSessionFactory());
return bean;
}
@Bean
public RoleUserService roleUserService() throws Exception
public RoleUserService roleUserService()
{
RoleUserServiceImpl bean = new RoleUserServiceImpl(this.sqlSessionFactory().getObject());
RoleUserServiceImpl bean = new RoleUserServiceImpl(this.sqlSessionFactory());
return bean;
}
@Bean
public DataSetEntityService dataSetEntityService() throws Exception
public DataSetEntityService dataSetEntityService()
{
DataSetEntityServiceImpl bean = new DataSetEntityServiceImpl(this.sqlSessionFactory().getObject(),
DataSetEntityServiceImpl bean = new DataSetEntityServiceImpl(this.sqlSessionFactory(),
this.connectionSource(), this.schemaService(), this.authorizationService(), this.dataSetRootDirectory(),
this.httpClient());
return bean;
}
@Bean
public FileTemplateDashboardWidgetResManager templateDashboardWidgetResManager() throws IOException
public FileTemplateDashboardWidgetResManager templateDashboardWidgetResManager()
{
FileTemplateDashboardWidgetResManager bean = new FileTemplateDashboardWidgetResManager(
this.dashboardRootDirectory());
@ -414,14 +435,14 @@ public class CoreConfiguration implements InitializingBean
}
@Bean
public DirectoryHtmlChartPluginManager directoryHtmlChartPluginManager() throws IOException
public DirectoryHtmlChartPluginManager directoryHtmlChartPluginManager()
{
DirectoryHtmlChartPluginManager bean = new DirectoryHtmlChartPluginManager(this.chartPluginRootDirectory());
return bean;
}
@Bean(initMethod = "init")
public DirectoryHtmlChartPluginManagerInitializer directoryHtmlChartPluginManagerInitializer() throws IOException
public DirectoryHtmlChartPluginManagerInitializer directoryHtmlChartPluginManagerInitializer()
{
DirectoryHtmlChartPluginManagerInitializer bean = new DirectoryHtmlChartPluginManagerInitializer(
this.directoryHtmlChartPluginManager());
@ -429,17 +450,17 @@ public class CoreConfiguration implements InitializingBean
}
@Bean
public HtmlChartWidgetEntityService htmlChartWidgetEntityService() throws Exception
public HtmlChartWidgetEntityService htmlChartWidgetEntityService()
{
HtmlChartWidgetEntityServiceImpl bean = new HtmlChartWidgetEntityServiceImpl(
this.sqlSessionFactory().getObject(), this.directoryHtmlChartPluginManager(),
this.sqlSessionFactory(), this.directoryHtmlChartPluginManager(),
this.dataSetEntityService(), this.authorizationService());
return bean;
}
@Bean(NAME_CHART_SHOW_HtmlTplDashboardWidgetHtmlRenderer)
public HtmlTplDashboardWidgetHtmlRenderer chartShowHtmlTplDashboardWidgetHtmlRenderer() throws Exception
public HtmlTplDashboardWidgetHtmlRenderer chartShowHtmlTplDashboardWidgetHtmlRenderer()
{
FileTemplateDashboardWidgetResManager resManager = new FileTemplateDashboardWidgetResManager(
this.dashboardRootDirectory());
@ -456,7 +477,7 @@ public class CoreConfiguration implements InitializingBean
}
@Bean(NAME_DASHBOARD_SHOW_HtmlTplDashboardWidgetHtmlRenderer)
public HtmlTplDashboardWidgetHtmlRenderer htmlTplDashboardWidgetRenderer() throws Exception
public HtmlTplDashboardWidgetHtmlRenderer htmlTplDashboardWidgetRenderer()
{
HtmlTplDashboardWidgetHtmlRenderer bean = new HtmlTplDashboardWidgetHtmlRenderer(
this.templateDashboardWidgetResManager(), this.htmlChartWidgetEntityService());
@ -544,19 +565,33 @@ public class CoreConfiguration implements InitializingBean
}
@Bean
public HtmlTplDashboardWidgetEntityService htmlTplDashboardWidgetEntityService() throws Exception
public HtmlTplDashboardWidgetEntityService htmlTplDashboardWidgetEntityService()
{
HtmlTplDashboardWidgetEntityServiceImpl bean = new HtmlTplDashboardWidgetEntityServiceImpl(
this.sqlSessionFactory().getObject(), this.htmlTplDashboardWidgetRenderer(),
this.sqlSessionFactory(), this.htmlTplDashboardWidgetRenderer(),
this.authorizationService());
return bean;
}
@Bean
public SqlHistoryService sqlHistoryService() throws Exception
public AnalysisProjectService analysisProjectService()
{
SqlHistoryServiceImpl bean = new SqlHistoryServiceImpl(this.sqlSessionFactory().getObject());
AnalysisProjectService bean = new AnalysisProjectServiceImpl(this.sqlSessionFactory());
return bean;
}
@Bean
public DataSetResDirectoryService dataSetResDirectoryService()
{
DataSetResDirectoryService bean = new DataSetResDirectoryServiceImpl(this.sqlSessionFactory());
return bean;
}
@Bean
public SqlHistoryService sqlHistoryService()
{
SqlHistoryServiceImpl bean = new SqlHistoryServiceImpl(this.sqlSessionFactory());
return bean;
}
@ -700,7 +735,7 @@ public class CoreConfiguration implements InitializingBean
}
@Bean
public SqlpadExecutionService sqlpadExecutionService() throws Exception
public SqlpadExecutionService sqlpadExecutionService()
{
SqlpadExecutionService bean = new SqlpadExecutionService(this.connectionSource(), this.messageSource(),
this.sqlpadCometdService(), this.sqlHistoryService(), this.sqlSelectManager());
@ -747,7 +782,7 @@ public class CoreConfiguration implements InitializingBean
}
@Bean
public SchedulerFactoryBean deleteTempFileScheduler() throws IOException
public SchedulerFactoryBean deleteTempFileScheduler()
{
DeleteExpiredFileJob job = new DeleteExpiredFileJob(this.tempDirectory(), 1440);
@ -776,6 +811,7 @@ public class CoreConfiguration implements InitializingBean
resourceServices.add(this.dataSetEntityService());
resourceServices.add(this.htmlChartWidgetEntityService());
resourceServices.add(this.htmlTplDashboardWidgetEntityService());
resourceServices.add(this.analysisProjectService());
}
// 处理循环依赖

View File

@ -0,0 +1,236 @@
/*
* Copyright (c) 2018 datagear.tech. All Rights Reserved.
*/
/**
*
*/
package org.datagear.web.config;
import java.util.Arrays;
import java.util.List;
import org.datagear.management.service.CreateUserEntityService;
import org.datagear.web.security.AuthUser;
import org.datagear.web.security.AuthenticationSuccessHandlerImpl;
import org.datagear.web.security.UserDetailsServiceImpl;
import org.datagear.web.util.WebContextPath;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
/**
* 安全配置
* <p>
* 依赖配置{@linkplain PropertiesConfiguration}{@linkplain CoreConfiguration}
* </p>
* <p>
* 依赖配置需要手动加载
* </p>
*
* @author datagear@163.com
*/
@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter
{
protected static final String[] ROLES_ANONYMOUS_AND_USER = { AuthUser.ROLE_ANONYMOUS, AuthUser.ROLE_USER };
protected static final String[] ROLES_USER = { AuthUser.ROLE_USER };
@Autowired
private CoreConfiguration coreConfiguration;
@Autowired
private Environment environment;
public SecurityConfiguration()
{
}
public SecurityConfiguration(CoreConfiguration coreConfiguration, Environment environment)
{
super();
this.coreConfiguration = coreConfiguration;
this.environment = environment;
}
public CoreConfiguration getCoreConfiguration()
{
return coreConfiguration;
}
public void setCoreConfiguration(CoreConfiguration coreConfiguration)
{
this.coreConfiguration = coreConfiguration;
}
public Environment getEnvironment()
{
return environment;
}
public void setEnvironment(Environment environment)
{
this.environment = environment;
}
/**
* 是否禁用匿名用户使用系统
*
* @return
*/
protected boolean isDisableAnonymous()
{
String disableStr = this.environment.getProperty("disableAnonymous");
return (disableStr == null ? false : Boolean.TRUE.toString().equals(disableStr));
}
/**
* 获取子应用上下文路径参考{@linkplain WebContextPath}
*
* @return
*/
protected String getSubContextPath()
{
String subContextPath = this.environment.getProperty("subContextPath");
return WebContextPath.trimSubContextPath(subContextPath);
}
protected String concatPath(String subContextPath, String path)
{
return subContextPath + path;
}
protected AuthenticationSuccessHandler getAuthenticationSuccessHandler()
{
AuthenticationSuccessHandlerImpl bean = new AuthenticationSuccessHandlerImpl();
List<CreateUserEntityService> createUserEntityServices = Arrays.asList(this.coreConfiguration.schemaService(),
this.coreConfiguration.dataSetEntityService(), this.coreConfiguration.htmlChartWidgetEntityService(),
this.coreConfiguration.htmlTplDashboardWidgetEntityService(),
this.coreConfiguration.analysisProjectService());
bean.setCreateUserEntityServices(createUserEntityServices);
return bean;
}
@Override
protected void configure(HttpSecurity http) throws Exception
{
String subContextPath = getSubContextPath();
boolean disableAnonymous = isDisableAnonymous();
http.authorizeRequests()
// 静态资源
.antMatchers(concatPath(subContextPath, "/static/**"))
.permitAll()
// 图表看板展示功能始终允许匿名用户访问用于支持外部系统iframe嵌套场景
.antMatchers(
concatPath(subContextPath, "/analysis/chartPlugin/icon/*"),
concatPath(subContextPath, "/analysis/chartPlugin/chartPluginManager.js"),
concatPath(subContextPath, "/analysis/chart/show/**"),
concatPath(subContextPath, "/analysis/chart/showData"),
concatPath(subContextPath, "/analysis/dashboard/show/**"),
concatPath(subContextPath, "/analysis/dashboard/showData"),
concatPath(subContextPath, "/analysis/dashboard/loadChart"),
concatPath(subContextPath, "/analysis/dashboard/heartbeat"))
.permitAll()
// 切换主题
.antMatchers(concatPath(subContextPath, "/changeThemeData/**"))
.permitAll()
// cometd
.antMatchers(concatPath(subContextPath, "/cometd/**"))
.hasAnyAuthority(disableAnonymous ? ROLES_USER : ROLES_ANONYMOUS_AND_USER)
// 驱动程序管理
.antMatchers(concatPath(subContextPath, "/driverEntity/add"),
concatPath(subContextPath, "/driverEntity/saveAdd"),
concatPath(subContextPath, "/driverEntity/import"),
concatPath(subContextPath, "/driverEntity/uploadImportFile"),
concatPath(subContextPath, "/driverEntity/saveImport"),
concatPath(subContextPath, "/driverEntity/edit"),
concatPath(subContextPath, "/driverEntity/saveEdit"),
concatPath(subContextPath, "/driverEntity/delete"),
concatPath(subContextPath, "/driverEntity/query"),
concatPath(subContextPath, "/driverEntity/uploadDriverFile"),
concatPath(subContextPath, "/driverEntity/deleteDriverFile"))
.hasAuthority(AuthUser.ROLE_ADMIN)
// 用户管理
.antMatchers(concatPath(subContextPath, "/user/personalSet"),
concatPath(subContextPath, "/user/savePersonalSet"),
concatPath(subContextPath, "/user/select"), concatPath(subContextPath, "/user/queryData"))
.hasAuthority(AuthUser.ROLE_USER)
.antMatchers(concatPath(subContextPath, "/user/**")).hasAuthority(AuthUser.ROLE_ADMIN)
// 角色管理
.antMatchers(concatPath(subContextPath, "/role/select"), concatPath(subContextPath, "/role/queryData"))
.hasAuthority(AuthUser.ROLE_USER)
.antMatchers(concatPath(subContextPath, "/role/**")).hasAuthority(AuthUser.ROLE_ADMIN)
// 权限管理
.antMatchers(concatPath(subContextPath, "/authorization/**")).hasAuthority(AuthUser.ROLE_USER)
// 设置数据库URL构建器脚本
.antMatchers(concatPath(subContextPath, "/schemaUrlBuilder/editScriptCode"),
concatPath(subContextPath, "/schemaUrlBuilder/saveScriptCode"),
concatPath(subContextPath, "/schemaUrlBuilder/previewScriptCode"))
.hasAuthority(AuthUser.ROLE_ADMIN)
// 图表插件管理
.antMatchers(concatPath(subContextPath, "/analysis/chartPlugin/select"),
concatPath(subContextPath, "/analysis/chartPlugin/selectData"))
.hasAnyAuthority(disableAnonymous ? ROLES_USER : ROLES_ANONYMOUS_AND_USER)
.antMatchers(concatPath(subContextPath, "/analysis/chartPlugin/**")).hasAuthority(AuthUser.ROLE_ADMIN)
// 数据集资源目录管理
.antMatchers(concatPath(subContextPath, "/dataSetResDirectory/view"),
concatPath(subContextPath, "/dataSetResDirectory/select"),
concatPath(subContextPath, "/dataSetResDirectory/pagingQueryData"),
concatPath(subContextPath, "/dataSetResDirectory/listFiles"))
.hasAnyAuthority(disableAnonymous ? ROLES_USER : ROLES_ANONYMOUS_AND_USER)
.antMatchers(concatPath(subContextPath, "/dataSetResDirectory/**")).hasAuthority(AuthUser.ROLE_ADMIN)
//
.antMatchers(
concatPath(subContextPath, "/login/**"),
concatPath(subContextPath, "/register/**"),
concatPath(subContextPath, "/resetPassword/**"))
.hasAuthority(AuthUser.ROLE_ANONYMOUS)
//
.antMatchers(concatPath(subContextPath, "/**"))
.hasAnyAuthority(disableAnonymous ? ROLES_USER : ROLES_ANONYMOUS_AND_USER)
.and()
.formLogin().loginPage(concatPath(subContextPath, "/login"))
.loginProcessingUrl(concatPath(subContextPath, "/login/doLogin")).usernameParameter("name")
.passwordParameter("password")
.successHandler(getAuthenticationSuccessHandler())
.and().logout().logoutUrl(concatPath(subContextPath, "/logout")).invalidateHttpSession(true)
.logoutSuccessUrl(concatPath(subContextPath, "/"))
.and()
.rememberMe().key("REMEMBER_ME_KEY").tokenValiditySeconds(60 * 60 * 24 * 365)
// TODO 配置"remember-me-parameter""autoLogin"
;
}
@Override
protected UserDetailsService userDetailsService()
{
UserDetailsService bean = new UserDetailsServiceImpl(this.coreConfiguration.userService());
return bean;
}
}

View File

@ -1,29 +0,0 @@
/*
* Copyright (c) 2018 datagear.tech. All Rights Reserved.
*/
/**
*
*/
package org.datagear.web.config;
import org.springframework.context.annotation.Configuration;
/**
* 安全配置
* <p>
* 依赖配置{@linkplain PropertiesConfiguration}{@linkplain CoreConfiguration}
* </p>
* <p>
* 依赖配置需要手动加载
* </p>
*
* @author datagear@163.com
*/
@Configuration
public class SercurityConfiguration
{
public SercurityConfiguration()
{
}
}

View File

@ -11,7 +11,6 @@ import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
@ -20,17 +19,15 @@ import org.datagear.analysis.Chart;
import org.datagear.analysis.ChartDataSet;
import org.datagear.analysis.ChartDefinition;
import org.datagear.analysis.DashboardTheme;
import org.datagear.analysis.DataSet;
import org.datagear.analysis.DataSetException;
import org.datagear.analysis.DataSetResult;
import org.datagear.analysis.DataSign;
import org.datagear.analysis.Icon;
import org.datagear.analysis.RenderContext;
import org.datagear.analysis.RenderException;
import org.datagear.analysis.support.AbstractChartPlugin;
import org.datagear.analysis.support.AbstractDataSet;
import org.datagear.analysis.support.CategorizationResolver;
import org.datagear.analysis.support.CategorizationResolver.Categorization;
import org.datagear.analysis.support.ProfileDataSet;
import org.datagear.analysis.support.html.DirectoryHtmlChartPluginManager;
import org.datagear.analysis.support.html.HtmlChartPlugin;
import org.datagear.util.i18n.Label;
@ -286,35 +283,6 @@ public class AbstractChartPluginAwareController extends AbstractDataAnalysisCont
}
}
/**
* {@linkplain DataSet}视图对象
*
* @author datagear@163.com
*
*/
public static class DataSetViewObj extends AbstractDataSet
{
public DataSetViewObj()
{
super();
}
public DataSetViewObj(DataSet dataSet)
{
super();
setId(dataSet.getId());
setName(dataSet.getName());
setProperties(dataSet.getProperties());
setParams(dataSet.getParams());
}
@Override
public DataSetResult getResult(Map<String, ?> paramValues) throws DataSetException
{
throw new UnsupportedOperationException();
}
}
/**
* {@linkplain ChartDataSet}视图对象
*
@ -331,7 +299,7 @@ public class AbstractChartPluginAwareController extends AbstractDataAnalysisCont
public ChartDataSetViewObj(ChartDataSet chartDataSet)
{
super();
setDataSet(new DataSetViewObj(chartDataSet.getDataSet()));
setDataSet(ProfileDataSet.valueOf(chartDataSet.getDataSet()));
setPropertySigns(chartDataSet.getPropertySigns());
setAlias(chartDataSet.getAlias());
setParamValues(chartDataSet.getParamValues());

View File

@ -4,6 +4,7 @@
package org.datagear.web.controller;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
@ -15,15 +16,23 @@ import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.datagear.management.domain.AnalysisProject;
import org.datagear.management.domain.AnalysisProjectAwareEntity;
import org.datagear.management.domain.DirectoryFileDataSetEntity;
import org.datagear.management.domain.User;
import org.datagear.management.service.AnalysisProjectService;
import org.datagear.management.service.DataPermissionEntityService;
import org.datagear.persistence.PagingQuery;
import org.datagear.util.IOUtil;
import org.datagear.util.JDBCCompatiblity;
import org.datagear.util.StringUtil;
import org.datagear.web.OperationMessage;
import org.datagear.web.convert.StringToJsonConverter;
import org.datagear.web.freemarker.WriteJsonTemplateDirectiveModel;
import org.datagear.web.util.DeliverContentTypeExceptionHandlerExceptionResolver;
import org.datagear.web.util.WebContextPath;
import org.datagear.web.util.WebUtils;
import org.datagear.web.vo.APIDDataFilterPagingQuery;
import org.datagear.web.vo.DataFilterPagingQuery;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
@ -64,6 +73,8 @@ public abstract class AbstractController
public static final String DATA_FILTER_COOKIE = "DATA_FILTER_SEARCH";
public static final String KEY_ANALYSIS_PROJECT_ID = "ANALYSIS_PROJECT_ID";
public static final String ERROR_PAGE_URL = "/error";
@Autowired
@ -109,11 +120,101 @@ public abstract class AbstractController
this.stringToJsonConverter = stringToJsonConverter;
}
protected boolean setCookieAnalysisProjectIfValid(HttpServletRequest request, HttpServletResponse response,
AnalysisProjectService analysisProjectService, AnalysisProjectAwareEntity<?> entity)
{
User user = WebUtils.getUser(request, response);
String analysisId = WebUtils.getCookieValue(request, KEY_ANALYSIS_PROJECT_ID);
if (!isEmpty(analysisId))
{
try
{
AnalysisProject analysisProject = analysisProjectService.getById(user, analysisId);
if (analysisProject != null)
{
entity.setAnalysisProject(analysisProject);
return true;
}
}
catch (Throwable t)
{
}
}
return false;
}
/**
* 整理保存时的{@linkplain AnalysisProjectAwareEntity}
* 如果analysisProject.id为空字符串则应将其改为null因为存储时相关外键不允许空字符串
*
* @param entity
*/
protected void trimAnalysisProjectAwareEntityForSave(AnalysisProjectAwareEntity<?> entity)
{
if (entity == null)
return;
if (entity.getAnalysisProject() == null)
return;
if (isEmpty(entity.getAnalysisProject().getId()))
entity.setAnalysisProject(null);
}
/**
* 整理保存时的{@linkplain DirectoryFileDataSetEntity}
* 如果dataSetResDirectory.id为空字符串则应将其改为null因为存储时相关外键不允许空字符串
*
* @param entity
*/
protected void trimDirectoryFileDataSetEntityForSave(DirectoryFileDataSetEntity entity)
{
if (entity == null)
return;
if (entity.getDataSetResDirectory() == null)
return;
if (isEmpty(entity.getDataSetResDirectory().getId()))
entity.setDataSetResDirectory(null);
}
/**
* 检查并补充{@linkplain APIDDataFilterPagingQuery}
*
* @param request
* @param pagingQuery
* 允许为{@code null}
* @return 不会为{@code null}
*/
protected APIDDataFilterPagingQuery inflateAPIDDataFilterPagingQuery(HttpServletRequest request,
APIDDataFilterPagingQuery pagingQuery)
{
DataFilterPagingQuery pq = inflateDataFilterPagingQuery(request, pagingQuery);
if (pagingQuery == null)
{
pagingQuery = new APIDDataFilterPagingQuery(pq.getPage(), pq.getPageSize(), pq.getKeyword(),
pq.getCondition());
pagingQuery.setNotLike(pq.isNotLike());
pagingQuery.setDataFilter(pq.getDataFilter());
pagingQuery.setAnalysisProjectId(WebUtils.getCookieValue(request, KEY_ANALYSIS_PROJECT_ID));
}
return pagingQuery;
}
/**
* 检查并补充{@linkplain DataFilterPagingQuery#getDataFilter()}
*
* @param request
* @param pagingQuery 允许为{@code null}
* @param pagingQuery
* 允许为{@code null}
* @return 不会为{@code null}
*/
protected DataFilterPagingQuery inflateDataFilterPagingQuery(HttpServletRequest request,
@ -126,7 +227,8 @@ public abstract class AbstractController
* 检查并补充{@linkplain DataFilterPagingQuery#getDataFilter()}
*
* @param request
* @param pagingQuery 允许为{@code null}
* @param pagingQuery
* 允许为{@code null}
* @param cookiePaginationSize
* @return 不会为{@code null}
*/
@ -193,7 +295,8 @@ public abstract class AbstractController
* 检查并补充{@linkplain PagingQuery}
*
* @param request
* @param pagingQuery 允许为{@code null}
* @param pagingQuery
* 允许为{@code null}
* @return 不会为{@code null}
*/
protected PagingQuery inflatePagingQuery(HttpServletRequest request, PagingQuery pagingQuery)
@ -205,27 +308,31 @@ public abstract class AbstractController
* 检查并补充{@linkplain PagingQuery}
*
* @param request
* @param pagingQuery 允许为{@code null}
* @param cookiePaginationSize 允许为{@code null}
* @param pagingQuery
* 允许为{@code null}
* @param cookiePaginationSize
* 允许为{@code null}
* @return 不会为{@code null}
*/
protected PagingQuery inflatePagingQuery(HttpServletRequest request, PagingQuery pagingQuery,
String cookiePaginationSize)
{
if (pagingQuery == null)
{
pagingQuery = new PagingQuery();
if (!isEmpty(cookiePaginationSize))
{
try
if (!isEmpty(cookiePaginationSize))
{
String pss = WebUtils.getCookieValue(request, cookiePaginationSize);
try
{
String pss = WebUtils.getCookieValue(request, cookiePaginationSize);
if (!isEmpty(pss))
pagingQuery.setPageSize(Integer.parseInt(pss));
}
catch (Exception e)
{
if (!isEmpty(pss))
pagingQuery.setPageSize(Integer.parseInt(pss));
}
catch (Exception e)
{
}
}
}
@ -253,6 +360,46 @@ public abstract class AbstractController
WebUtils.setOperationMessage(request, operationMessage);
}
/**
* 获取错误信息视图
*
* @param request
* @param response
* @return
*/
protected String getErrorView(HttpServletRequest request, HttpServletResponse response)
{
setAttributeIfIsJsonResponse(request, response);
return ERROR_PAGE_URL;
}
/**
* 设置JSON响应的错误页面属性
*
* @param request
* @param response
*/
protected void setAttributeIfIsJsonResponse(HttpServletRequest request, HttpServletResponse response)
{
String expectedContentType = DeliverContentTypeExceptionHandlerExceptionResolver.getHandlerContentType(request);
if (expectedContentType != null && !expectedContentType.isEmpty())
response.setContentType(expectedContentType);
boolean isJsonResponse = WebUtils.isJsonResponse(response);
request.setAttribute("isJsonResponse", isJsonResponse);
if (isJsonResponse)
{
OperationMessage operationMessage = getOperationMessageForHttpError(request, response);
request.setAttribute(WebUtils.KEY_OPERATION_MESSAGE,
WriteJsonTemplateDirectiveModel.toWriteJsonTemplateModel(operationMessage));
response.setContentType(CONTENT_TYPE_JSON);
}
}
/**
* 构建操作成功消息无消息内容对应的{@linkplain ResponseEntity}
* <p>
@ -617,6 +764,24 @@ public abstract class AbstractController
return pathInfo.substring(index + pathPrefix.length());
}
/**
* 将文件名转换为作为响应下载文件名
* <p>
* 此方法会对处理中文乱码问题
* </p>
*
* @param request
* @param response
* @param fileName
* @return
* @throws IOException
*/
protected String toResponseAttachmentFileName(HttpServletRequest request, HttpServletResponse response,
String fileName) throws IOException
{
return new String(fileName.getBytes(RESPONSE_ENCODING), IOUtil.CHARSET_ISO_8859_1);
}
/**
* 判断对象字符串数组集合Map是否为空
*

View File

@ -119,6 +119,23 @@ public abstract class AbstractSchemaConnController extends AbstractController
return schema;
}
/**
* 获取{@linkplain Schema}
*
* @param schemaId
* @return
* @throws SchemaNotFoundException
*/
protected Schema getSchemaNotNull(String schemaId) throws SchemaNotFoundException
{
Schema schema = this.schemaService.getById(schemaId);
if (schema == null)
throw new SchemaNotFoundException(schemaId);
return schema;
}
/**
* 获取指定{@linkplain Schema}{@linkplain Connection}
*

View File

@ -0,0 +1,216 @@
/*
* Copyright 2018 datagear.tech. All Rights Reserved.
*/
package org.datagear.web.controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.datagear.management.domain.AnalysisProject;
import org.datagear.management.domain.User;
import org.datagear.management.service.AnalysisProjectService;
import org.datagear.persistence.PagingData;
import org.datagear.util.IDUtil;
import org.datagear.web.OperationMessage;
import org.datagear.web.util.WebUtils;
import org.datagear.web.vo.DataFilterPagingQuery;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
/**
* 数据分析项目控制器
*
* @author datagear@163.com
*
*/
@Controller
@RequestMapping("/analysis/project")
public class AnalysisProjectController extends AbstractController
{
static
{
AuthorizationResourceMetas.registerForShare(AnalysisProject.AUTHORIZATION_RESOURCE_TYPE, "analysisProject");
}
@Autowired
private AnalysisProjectService analysisProjectService;
public AnalysisProjectController()
{
super();
}
public AnalysisProjectService getAnalysisProjectService()
{
return analysisProjectService;
}
public void setAnalysisProjectService(AnalysisProjectService analysisProjectService)
{
this.analysisProjectService = analysisProjectService;
}
@RequestMapping("/add")
public String add(HttpServletRequest request, org.springframework.ui.Model model)
{
AnalysisProject analysisProject = new AnalysisProject();
model.addAttribute("analysisProject", analysisProject);
model.addAttribute(KEY_TITLE_MESSAGE_KEY, "analysisProject.addAnalysisProject");
model.addAttribute(KEY_FORM_ACTION, "saveAdd");
return "/analysis/analysisProject/analysisProject_form";
}
@RequestMapping(value = "/saveAdd", produces = CONTENT_TYPE_JSON)
@ResponseBody
public ResponseEntity<OperationMessage> saveAdd(HttpServletRequest request, HttpServletResponse response,
@RequestBody AnalysisProject analysisProject)
{
checkSaveEntity(analysisProject);
User user = WebUtils.getUser(request, response);
analysisProject.setId(IDUtil.randomIdOnTime20());
analysisProject.setCreateUser(user);
this.analysisProjectService.add(analysisProject);
return buildOperationMessageSaveSuccessResponseEntity(request, analysisProject);
}
@RequestMapping("/edit")
public String edit(HttpServletRequest request, HttpServletResponse response, org.springframework.ui.Model model,
@RequestParam("id") String id)
{
User user = WebUtils.getUser(request, response);
AnalysisProject analysisProject = this.analysisProjectService.getByIdForEdit(user, id);
if (analysisProject == null)
throw new RecordNotFoundException();
model.addAttribute("analysisProject", analysisProject);
model.addAttribute(KEY_TITLE_MESSAGE_KEY, "analysisProject.editAnalysisProject");
model.addAttribute(KEY_FORM_ACTION, "saveEdit");
return "/analysis/analysisProject/analysisProject_form";
}
@RequestMapping(value = "/saveEdit", produces = CONTENT_TYPE_JSON)
@ResponseBody
public ResponseEntity<OperationMessage> save(HttpServletRequest request, HttpServletResponse response,
@RequestBody AnalysisProject analysisProject)
{
checkSaveEntity(analysisProject);
User user = WebUtils.getUser(request, response);
this.analysisProjectService.update(user, analysisProject);
return buildOperationMessageSaveSuccessResponseEntity(request, analysisProject);
}
@RequestMapping("/view")
public String view(HttpServletRequest request, HttpServletResponse response, org.springframework.ui.Model model,
@RequestParam("id") String id)
{
User user = WebUtils.getUser(request, response);
AnalysisProject analysisProject = this.analysisProjectService.getById(user, id);
if (analysisProject == null)
throw new RecordNotFoundException();
model.addAttribute("analysisProject", analysisProject);
model.addAttribute(KEY_TITLE_MESSAGE_KEY, "analysisProject.viewAnalysisProject");
model.addAttribute(KEY_READONLY, true);
return "/analysis/analysisProject/analysisProject_form";
}
@RequestMapping(value = "/getByIdSilently", produces = CONTENT_TYPE_JSON)
@ResponseBody
public AnalysisProject getByIdSilently(HttpServletRequest request, HttpServletResponse response,
org.springframework.ui.Model model, @RequestParam("id") String id)
{
User user = WebUtils.getUser(request, response);
AnalysisProject analysisProject = null;
try
{
analysisProject = this.analysisProjectService.getById(user, id);
}
catch (Throwable t)
{
}
return analysisProject;
}
@RequestMapping(value = "/delete", produces = CONTENT_TYPE_JSON)
@ResponseBody
public ResponseEntity<OperationMessage> delete(HttpServletRequest request, HttpServletResponse response,
@RequestBody String[] ids)
{
User user = WebUtils.getUser(request, response);
for (int i = 0; i < ids.length; i++)
{
String id = ids[i];
this.analysisProjectService.deleteById(user, id);
}
return buildOperationMessageDeleteSuccessResponseEntity(request);
}
@RequestMapping("/pagingQuery")
public String pagingQuery(HttpServletRequest request, HttpServletResponse response,
org.springframework.ui.Model model)
{
User user = WebUtils.getUser(request, response);
model.addAttribute("currentUser", user);
model.addAttribute(KEY_TITLE_MESSAGE_KEY, "analysisProject.manageAnalysisProject");
return "/analysis/analysisProject/analysisProject_grid";
}
@RequestMapping(value = "/select")
public String select(HttpServletRequest request, HttpServletResponse response, org.springframework.ui.Model model)
{
model.addAttribute(KEY_TITLE_MESSAGE_KEY, "analysisProject.selectAnalysisProject");
model.addAttribute(KEY_SELECT_OPERATION, true);
setIsMultipleSelectAttribute(request, model);
return "/analysis/analysisProject/analysisProject_grid";
}
@RequestMapping(value = "/pagingQueryData", produces = CONTENT_TYPE_JSON)
@ResponseBody
public PagingData<AnalysisProject> pagingQueryData(HttpServletRequest request, HttpServletResponse response,
final org.springframework.ui.Model springModel,
@RequestBody(required = false) DataFilterPagingQuery pagingQueryParam) throws Exception
{
User user = WebUtils.getUser(request, response);
final DataFilterPagingQuery pagingQuery = inflateDataFilterPagingQuery(request, pagingQueryParam);
PagingData<AnalysisProject> pagingData = this.analysisProjectService.pagingQuery(user, pagingQuery,
pagingQuery.getDataFilter());
return pagingData;
}
protected void checkSaveEntity(AnalysisProject analysisProject)
{
if (isBlank(analysisProject.getName()))
throw new IllegalInputException();
}
}

View File

@ -31,13 +31,15 @@ import org.datagear.analysis.support.html.HtmlTplDashboardWidgetRenderer.AddPref
import org.datagear.management.domain.ChartDataSetVO;
import org.datagear.management.domain.HtmlChartWidgetEntity;
import org.datagear.management.domain.User;
import org.datagear.management.service.AnalysisProjectService;
import org.datagear.management.service.HtmlChartWidgetEntityService;
import org.datagear.management.service.HtmlChartWidgetEntityService.ChartWidgetSourceContext;
import org.datagear.persistence.PagingData;
import org.datagear.util.IDUtil;
import org.datagear.util.IOUtil;
import org.datagear.web.OperationMessage;
import org.datagear.web.util.WebUtils;
import org.datagear.web.vo.DataFilterPagingQuery;
import org.datagear.web.vo.APIDDataFilterPagingQuery;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.http.ResponseEntity;
@ -68,6 +70,9 @@ public class ChartController extends AbstractChartPluginAwareController implemen
@Autowired
private HtmlChartWidgetEntityService htmlChartWidgetEntityService;
@Autowired
private AnalysisProjectService analysisProjectService;
@Autowired
private ChartPluginManager chartPluginManager;
@ -92,6 +97,16 @@ public class ChartController extends AbstractChartPluginAwareController implemen
this.htmlChartWidgetEntityService = htmlChartWidgetEntityService;
}
public AnalysisProjectService getAnalysisProjectService()
{
return analysisProjectService;
}
public void setAnalysisProjectService(AnalysisProjectService analysisProjectService)
{
this.analysisProjectService = analysisProjectService;
}
public ChartPluginManager getChartPluginManager()
{
return chartPluginManager;
@ -125,9 +140,10 @@ public class ChartController extends AbstractChartPluginAwareController implemen
}
@RequestMapping("/add")
public String add(HttpServletRequest request, org.springframework.ui.Model model)
public String add(HttpServletRequest request, HttpServletResponse response, org.springframework.ui.Model model)
{
HtmlChartWidgetEntity chart = new HtmlChartWidgetEntity();
setCookieAnalysisProject(request, response, chart);
model.addAttribute("chart", chart);
model.addAttribute("chartPluginVO", toWriteJsonTemplateModel(null));
@ -168,6 +184,8 @@ public class ChartController extends AbstractChartPluginAwareController implemen
{
User user = WebUtils.getUser(request, response);
trimAnalysisProjectAwareEntityForSave(entity);
HtmlChartPlugin paramPlugin = entity.getHtmlChartPlugin();
if (isEmpty(entity.getId()))
@ -258,13 +276,13 @@ public class ChartController extends AbstractChartPluginAwareController implemen
@ResponseBody
public PagingData<HtmlChartWidgetEntity> pagingQueryData(HttpServletRequest request, HttpServletResponse response,
final org.springframework.ui.Model springModel,
@RequestBody(required = false) DataFilterPagingQuery pagingQueryParam) throws Exception
@RequestBody(required = false) APIDDataFilterPagingQuery pagingQueryParam) throws Exception
{
User user = WebUtils.getUser(request, response);
final DataFilterPagingQuery pagingQuery = inflateDataFilterPagingQuery(request, pagingQueryParam);
final APIDDataFilterPagingQuery pagingQuery = inflateAPIDDataFilterPagingQuery(request, pagingQueryParam);
PagingData<HtmlChartWidgetEntity> pagingData = this.htmlChartWidgetEntityService.pagingQuery(user, pagingQuery,
pagingQuery.getDataFilter());
pagingQuery.getDataFilter(), pagingQuery.getAnalysisProjectId());
setChartPluginNames(request, pagingData.getItems());
return pagingData;
@ -370,6 +388,8 @@ public class ChartController extends AbstractChartPluginAwareController implemen
if (chart == null)
throw new RecordNotFoundException();
ChartWidgetSourceContext.set(new ChartWidgetSourceContext(user));
String id = chart.getId();
String htmlTitle = chart.getName();
@ -450,6 +470,12 @@ public class ChartController extends AbstractChartPluginAwareController implemen
}
}
protected void setCookieAnalysisProject(HttpServletRequest request, HttpServletResponse response,
HtmlChartWidgetEntity entity)
{
setCookieAnalysisProjectIfValid(request, response, this.analysisProjectService, entity);
}
protected void checkSaveEntity(HtmlChartWidgetEntity chart)
{
if (isBlank(chart.getName()))

View File

@ -183,7 +183,8 @@ public class ChartPluginController extends AbstractChartPluginAwareController
public void download(HttpServletRequest request, HttpServletResponse response, org.springframework.ui.Model model,
@RequestParam("id") String[] ids) throws Exception
{
response.addHeader("Content-Disposition", "attachment;filename=chartPlugins.zip");
response.addHeader("Content-Disposition",
"attachment;filename=" + toResponseAttachmentFileName(request, response, "chartPlugins.zip"));
response.setContentType("application/octet-stream");
ZipOutputStream zout = IOUtil.getZipOutputStream(response.getOutputStream());

View File

@ -38,13 +38,10 @@ import org.datagear.persistence.support.NoColumnDefinedException;
import org.datagear.persistence.support.SqlParamValueSqlExpressionException;
import org.datagear.persistence.support.SqlParamValueVariableExpressionException;
import org.datagear.persistence.support.UnsupportedDialectException;
import org.datagear.web.OperationMessage;
import org.datagear.web.freemarker.WriteJsonTemplateDirectiveModel;
import org.datagear.web.util.DeliverContentTypeExceptionHandlerExceptionResolver;
import org.datagear.web.util.WebUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.convert.ConversionException;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindException;
@ -515,6 +512,17 @@ public class ControllerAdvice extends AbstractController
return getErrorView(request, response);
}
@ExceptionHandler(DataIntegrityViolationException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public String handleDataIntegrityViolationException(HttpServletRequest request, HttpServletResponse response,
DataIntegrityViolationException exception)
{
setOperationMessageForThrowable(request, buildMessageCode(DataIntegrityViolationException.class), exception,
true);
return getErrorView(request, response);
}
@ExceptionHandler(Throwable.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public String handleThrowable(HttpServletRequest request, HttpServletResponse response, Throwable t)
@ -531,46 +539,6 @@ public class ControllerAdvice extends AbstractController
LOGGER.error("", t);
}
/**
* 获取错误信息视图
*
* @param request
* @param response
* @return
*/
protected String getErrorView(HttpServletRequest request, HttpServletResponse response)
{
setAttributeIfIsJsonResponse(request, response);
return ERROR_PAGE_URL;
}
/**
* 设置JSON响应的错误页面属性
*
* @param request
* @param response
*/
protected void setAttributeIfIsJsonResponse(HttpServletRequest request, HttpServletResponse response)
{
String expectedContentType = DeliverContentTypeExceptionHandlerExceptionResolver.getHandlerContentType(request);
if (expectedContentType != null && !expectedContentType.isEmpty())
response.setContentType(expectedContentType);
boolean isJsonResponse = WebUtils.isJsonResponse(response);
request.setAttribute("isJsonResponse", isJsonResponse);
if (isJsonResponse)
{
OperationMessage operationMessage = getOperationMessageForHttpError(request, response);
request.setAttribute(WebUtils.KEY_OPERATION_MESSAGE,
WriteJsonTemplateDirectiveModel.toWriteJsonTemplateModel(operationMessage));
response.setContentType(CONTENT_TYPE_JSON);
}
}
protected String buildMessageCode(Class<? extends Throwable> clazz)
{
return buildMessageCode(clazz.getSimpleName());

View File

@ -16,6 +16,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
@ -37,8 +38,10 @@ import org.datagear.analysis.support.html.HtmlTplDashboardRenderAttr.WebContext;
import org.datagear.analysis.support.html.HtmlTplDashboardWidget;
import org.datagear.analysis.support.html.HtmlTplDashboardWidgetRenderer;
import org.datagear.analysis.support.html.HtmlTplDashboardWidgetRenderer.AddPrefixHtmlTitleHandler;
import org.datagear.management.domain.AnalysisProject;
import org.datagear.management.domain.HtmlTplDashboardWidgetEntity;
import org.datagear.management.domain.User;
import org.datagear.management.service.AnalysisProjectService;
import org.datagear.management.service.HtmlChartWidgetEntityService.ChartWidgetSourceContext;
import org.datagear.management.service.HtmlTplDashboardWidgetEntityService;
import org.datagear.persistence.PagingData;
@ -48,7 +51,7 @@ import org.datagear.util.IOUtil;
import org.datagear.util.StringUtil;
import org.datagear.web.OperationMessage;
import org.datagear.web.util.WebUtils;
import org.datagear.web.vo.DataFilterPagingQuery;
import org.datagear.web.vo.APIDDataFilterPagingQuery;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
@ -90,6 +93,9 @@ public class DashboardController extends AbstractDataAnalysisController implemen
@Autowired
private HtmlTplDashboardWidgetEntityService htmlTplDashboardWidgetEntityService;
@Autowired
private AnalysisProjectService analysisProjectService;
@Autowired
private File tempDirectory;
@ -111,6 +117,16 @@ public class DashboardController extends AbstractDataAnalysisController implemen
this.htmlTplDashboardWidgetEntityService = htmlTplDashboardWidgetEntityService;
}
public AnalysisProjectService getAnalysisProjectService()
{
return analysisProjectService;
}
public void setAnalysisProjectService(AnalysisProjectService analysisProjectService)
{
this.analysisProjectService = analysisProjectService;
}
public File getTempDirectory()
{
return tempDirectory;
@ -133,9 +149,10 @@ public class DashboardController extends AbstractDataAnalysisController implemen
}
@RequestMapping("/add")
public String add(HttpServletRequest request, org.springframework.ui.Model model)
public String add(HttpServletRequest request, HttpServletResponse response, org.springframework.ui.Model model)
{
HtmlTplDashboardWidgetEntity dashboard = new HtmlTplDashboardWidgetEntity();
setCookieAnalysisProject(request, response, dashboard);
dashboard.setTemplates(HtmlTplDashboardWidgetEntity.DEFAULT_TEMPLATES);
dashboard.setTemplateEncoding(HtmlTplDashboardWidget.DEFAULT_TEMPLATE_ENCODING);
@ -186,6 +203,8 @@ public class DashboardController extends AbstractDataAnalysisController implemen
User user = WebUtils.getUser(request, response);
trimAnalysisProjectAwareEntityForSave(dashboard);
if (!dashboard.isTemplate(templateName))
{
List<String> templates = new ArrayList<>();
@ -400,8 +419,13 @@ public class DashboardController extends AbstractDataAnalysisController implemen
}
@RequestMapping("/import")
public String impt(HttpServletRequest request, org.springframework.ui.Model model)
public String impt(HttpServletRequest request, HttpServletResponse response, org.springframework.ui.Model model)
{
HtmlTplDashboardWidgetEntity dashboard = new HtmlTplDashboardWidgetEntity();
setCookieAnalysisProject(request, response, dashboard);
model.addAttribute("dashboard", dashboard);
return "/analysis/dashboard/dashboard_import";
}
@ -485,7 +509,9 @@ public class DashboardController extends AbstractDataAnalysisController implemen
@ResponseBody
public ResponseEntity<OperationMessage> saveImport(HttpServletRequest request, HttpServletResponse response,
@RequestParam("name") String name, @RequestParam("template") String template,
@RequestParam("dashboardFileName") String dashboardFileName) throws Exception
@RequestParam("dashboardFileName") String dashboardFileName,
@RequestParam(name = "analysisProject.id", required = false) String analysisProjectId,
@RequestParam(name = "analysisProject.name", required = false) String analysisProjectName) throws Exception
{
File uploadDirectory = FileUtil.getDirectory(this.tempDirectory, dashboardFileName, false);
@ -515,11 +541,21 @@ public class DashboardController extends AbstractDataAnalysisController implemen
dashboard.setTemplateEncoding(templateEncoding);
dashboard.setName(name);
if (!isEmpty(analysisProjectId))
{
AnalysisProject analysisProject = new AnalysisProject();
analysisProject.setId(analysisProjectId);
analysisProject.setName(analysisProjectName);
dashboard.setAnalysisProject(analysisProject);
}
checkSaveEntity(dashboard);
dashboard.setId(IDUtil.randomIdOnTime20());
dashboard.setCreateUser(user);
trimAnalysisProjectAwareEntityForSave(dashboard);
this.htmlTplDashboardWidgetEntityService.add(user, dashboard);
TemplateDashboardWidgetResManager dashboardWidgetResManager = this.htmlTplDashboardWidgetEntityService
@ -551,6 +587,40 @@ public class DashboardController extends AbstractDataAnalysisController implemen
return "/analysis/dashboard/dashboard_form";
}
@RequestMapping("/export")
public void export(HttpServletRequest request, HttpServletResponse response, org.springframework.ui.Model model,
@RequestParam("id") String id) throws Exception
{
User user = WebUtils.getUser(request, response);
HtmlTplDashboardWidgetEntity dashboard = this.htmlTplDashboardWidgetEntityService.getById(user, id);
if (dashboard == null)
throw new RecordNotFoundException();
TemplateDashboardWidgetResManager dashboardWidgetResManager = this.htmlTplDashboardWidgetEntityService
.getHtmlTplDashboardWidgetRenderer().getTemplateDashboardWidgetResManager();
File tmpDirectory = FileUtil.generateUniqueDirectory(this.tempDirectory);
dashboardWidgetResManager.copyTo(dashboard.getId(), tmpDirectory);
response.addHeader("Content-Disposition",
"attachment;filename=" + toResponseAttachmentFileName(request, response, dashboard.getName() + ".zip"));
response.setContentType("application/octet-stream");
ZipOutputStream zout = IOUtil.getZipOutputStream(response.getOutputStream());
try
{
IOUtil.writeFileToZipOutputStream(zout, tmpDirectory, "");
}
finally
{
zout.flush();
zout.close();
}
}
@RequestMapping(value = "/delete", produces = CONTENT_TYPE_JSON)
@ResponseBody
public ResponseEntity<OperationMessage> delete(HttpServletRequest request, HttpServletResponse response,
@ -592,13 +662,13 @@ public class DashboardController extends AbstractDataAnalysisController implemen
@ResponseBody
public PagingData<HtmlTplDashboardWidgetEntity> pagingQueryData(HttpServletRequest request,
HttpServletResponse response, final org.springframework.ui.Model springModel,
@RequestBody(required = false) DataFilterPagingQuery pagingQueryParam) throws Exception
@RequestBody(required = false) APIDDataFilterPagingQuery pagingQueryParam) throws Exception
{
User user = WebUtils.getUser(request, response);
final DataFilterPagingQuery pagingQuery = inflateDataFilterPagingQuery(request, pagingQueryParam);
final APIDDataFilterPagingQuery pagingQuery = inflateAPIDDataFilterPagingQuery(request, pagingQueryParam);
PagingData<HtmlTplDashboardWidgetEntity> pagingData = this.htmlTplDashboardWidgetEntityService.pagingQuery(user,
pagingQuery, pagingQuery.getDataFilter());
pagingQuery, pagingQuery.getDataFilter(), pagingQuery.getAnalysisProjectId());
return pagingData;
}
@ -956,4 +1026,10 @@ public class DashboardController extends AbstractDataAnalysisController implemen
return resourceName;
}
protected void setCookieAnalysisProject(HttpServletRequest request, HttpServletResponse response,
HtmlTplDashboardWidgetEntity entity)
{
setCookieAnalysisProjectIfValid(request, response, this.analysisProjectService, entity);
}
}

View File

@ -686,8 +686,9 @@ public class DataController extends AbstractSchemaConnTableController
}
}.execute();
response.setCharacterEncoding("utf-8");
response.setHeader("Content-Disposition", "attachment; filename=" + columnName + "");
response.setCharacterEncoding(IOUtil.CHARSET_UTF_8);
response.setHeader("Content-Disposition",
"attachment; filename=" + toResponseAttachmentFileName(request, response, columnName));
InputStream in = null;
OutputStream out = null;
@ -735,7 +736,8 @@ public class DataController extends AbstractSchemaConnTableController
@RequestParam("file") String fileName) throws Throwable
{
response.setCharacterEncoding(RESPONSE_ENCODING);
response.setHeader("Content-Disposition", "attachment; filename=" + fileName + "");
response.setHeader("Content-Disposition",
"attachment; filename=" + toResponseAttachmentFileName(request, response, fileName));
OutputStream out = null;

View File

@ -1319,7 +1319,7 @@ public class DataExchangeController extends AbstractSchemaConnController
{
response.setCharacterEncoding(RESPONSE_ENCODING);
response.setHeader("Content-Disposition",
"attachment; filename=" + new String(fileName.getBytes(RESPONSE_ENCODING), "iso-8859-1") + "");
"attachment; filename=" + toResponseAttachmentFileName(request, response, fileName));
File directory = getTempDataExchangeDirectory(dataExchangeId, true);
File file = FileUtil.getFile(directory, fileName);
@ -1345,7 +1345,7 @@ public class DataExchangeController extends AbstractSchemaConnController
{
response.setCharacterEncoding(RESPONSE_ENCODING);
response.setHeader("Content-Disposition",
"attachment; filename=" + new String(fileName.getBytes(RESPONSE_ENCODING), "iso-8859-1"));
"attachment; filename=" + toResponseAttachmentFileName(request, response, fileName));
File directory = getTempDataExchangeDirectory(dataExchangeId, true);

View File

@ -26,9 +26,11 @@ import org.datagear.analysis.support.CsvValueDataSet;
import org.datagear.analysis.support.DataSetFmkTemplateResolver;
import org.datagear.analysis.support.DataSetParamValueConverter;
import org.datagear.analysis.support.JsonValueDataSet;
import org.datagear.analysis.support.ProfileDataSet;
import org.datagear.analysis.support.SqlDataSet;
import org.datagear.analysis.support.TemplateContext;
import org.datagear.analysis.support.TemplateResolvedDataSetResult;
import org.datagear.management.domain.Authorization;
import org.datagear.management.domain.CsvFileDataSetEntity;
import org.datagear.management.domain.CsvValueDataSetEntity;
import org.datagear.management.domain.DataSetEntity;
@ -41,14 +43,17 @@ import org.datagear.management.domain.Schema;
import org.datagear.management.domain.SchemaConnectionFactory;
import org.datagear.management.domain.SqlDataSetEntity;
import org.datagear.management.domain.User;
import org.datagear.management.service.AnalysisProjectService;
import org.datagear.management.service.DataPermissionEntityService;
import org.datagear.management.service.DataSetEntityService;
import org.datagear.management.service.PermissionDeniedException;
import org.datagear.persistence.PagingData;
import org.datagear.util.FileUtil;
import org.datagear.util.IDUtil;
import org.datagear.util.IOUtil;
import org.datagear.web.OperationMessage;
import org.datagear.web.util.WebUtils;
import org.datagear.web.vo.DataFilterPagingQuery;
import org.datagear.web.vo.APIDDataFilterPagingQuery;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
@ -76,6 +81,9 @@ public class DataSetController extends AbstractSchemaConnController
@Autowired
private DataSetEntityService dataSetEntityService;
@Autowired
private AnalysisProjectService analysisProjectService;
@Autowired
private File tempDirectory;
@ -96,6 +104,16 @@ public class DataSetController extends AbstractSchemaConnController
this.dataSetEntityService = dataSetEntityService;
}
public AnalysisProjectService getAnalysisProjectService()
{
return analysisProjectService;
}
public void setAnalysisProjectService(AnalysisProjectService analysisProjectService)
{
this.analysisProjectService = analysisProjectService;
}
public File getTempDirectory()
{
return tempDirectory;
@ -117,9 +135,11 @@ public class DataSetController extends AbstractSchemaConnController
}
@RequestMapping("/addForSql")
public String addForSql(HttpServletRequest request, org.springframework.ui.Model model)
public String addForSql(HttpServletRequest request, HttpServletResponse response,
org.springframework.ui.Model model)
{
SqlDataSetEntity dataSet = new SqlDataSetEntity();
setCookieAnalysisProject(request, response, dataSet);
model.addAttribute("dataSet", dataSet);
model.addAttribute(KEY_TITLE_MESSAGE_KEY, "dataSet.addDataSet");
@ -140,15 +160,19 @@ public class DataSetController extends AbstractSchemaConnController
checkSaveSqlDataSetEntity(dataSet);
trimAnalysisProjectAwareEntityForSave(dataSet);
this.dataSetEntityService.add(user, dataSet);
return buildOperationMessageSaveSuccessResponseEntity(request, dataSet);
}
@RequestMapping("/addForJsonValue")
public String addForJsonValue(HttpServletRequest request, org.springframework.ui.Model model)
public String addForJsonValue(HttpServletRequest request, HttpServletResponse response,
org.springframework.ui.Model model)
{
JsonValueDataSetEntity dataSet = new JsonValueDataSetEntity();
setCookieAnalysisProject(request, response, dataSet);
model.addAttribute("dataSet", dataSet);
model.addAttribute(KEY_TITLE_MESSAGE_KEY, "dataSet.addDataSet");
@ -169,15 +193,19 @@ public class DataSetController extends AbstractSchemaConnController
checkSaveJsonValueDataSetEntity(dataSet);
trimAnalysisProjectAwareEntityForSave(dataSet);
this.dataSetEntityService.add(user, dataSet);
return buildOperationMessageSaveSuccessResponseEntity(request, dataSet);
}
@RequestMapping("/addForJsonFile")
public String addForJsonFile(HttpServletRequest request, org.springframework.ui.Model model)
public String addForJsonFile(HttpServletRequest request, HttpServletResponse response,
org.springframework.ui.Model model)
{
JsonFileDataSetEntity dataSet = new JsonFileDataSetEntity();
setCookieAnalysisProject(request, response, dataSet);
model.addAttribute("dataSet", dataSet);
model.addAttribute("availableCharsetNames", getAvailableCharsetNames());
@ -199,6 +227,9 @@ public class DataSetController extends AbstractSchemaConnController
checkSaveJsonFileDataSetEntity(dataSet);
trimAnalysisProjectAwareEntityForSave(dataSet);
trimDirectoryFileDataSetEntityForSave(dataSet);
this.dataSetEntityService.add(user, dataSet);
copyToDirectoryFileDataSetEntityDirectoryIf(dataSet, "");
@ -206,10 +237,12 @@ public class DataSetController extends AbstractSchemaConnController
}
@RequestMapping("/addForExcel")
public String addForExcel(HttpServletRequest request, org.springframework.ui.Model model)
public String addForExcel(HttpServletRequest request, HttpServletResponse response,
org.springframework.ui.Model model)
{
ExcelDataSetEntity dataSet = new ExcelDataSetEntity();
dataSet.setNameRow(1);
setCookieAnalysisProject(request, response, dataSet);
model.addAttribute("dataSet", dataSet);
model.addAttribute(KEY_TITLE_MESSAGE_KEY, "dataSet.addDataSet");
@ -230,6 +263,9 @@ public class DataSetController extends AbstractSchemaConnController
checkSaveExcelDataSetEntity(dataSet);
trimAnalysisProjectAwareEntityForSave(dataSet);
trimDirectoryFileDataSetEntityForSave(dataSet);
this.dataSetEntityService.add(user, dataSet);
copyToDirectoryFileDataSetEntityDirectoryIf(dataSet, "");
@ -237,10 +273,12 @@ public class DataSetController extends AbstractSchemaConnController
}
@RequestMapping("/addForCsvValue")
public String addForCsvValue(HttpServletRequest request, org.springframework.ui.Model model)
public String addForCsvValue(HttpServletRequest request, HttpServletResponse response,
org.springframework.ui.Model model)
{
CsvValueDataSetEntity dataSet = new CsvValueDataSetEntity();
dataSet.setNameRow(1);
setCookieAnalysisProject(request, response, dataSet);
model.addAttribute("dataSet", dataSet);
model.addAttribute(KEY_TITLE_MESSAGE_KEY, "dataSet.addDataSet");
@ -261,16 +299,20 @@ public class DataSetController extends AbstractSchemaConnController
checkSaveCsvValueDataSetEntity(dataSet);
trimAnalysisProjectAwareEntityForSave(dataSet);
this.dataSetEntityService.add(user, dataSet);
return buildOperationMessageSaveSuccessResponseEntity(request, dataSet);
}
@RequestMapping("/addForCsvFile")
public String addForCsvFile(HttpServletRequest request, org.springframework.ui.Model model)
public String addForCsvFile(HttpServletRequest request, HttpServletResponse response,
org.springframework.ui.Model model)
{
CsvFileDataSetEntity dataSet = new CsvFileDataSetEntity();
dataSet.setNameRow(1);
setCookieAnalysisProject(request, response, dataSet);
model.addAttribute("dataSet", dataSet);
model.addAttribute("availableCharsetNames", getAvailableCharsetNames());
@ -292,6 +334,9 @@ public class DataSetController extends AbstractSchemaConnController
checkSaveCsvFileDataSetEntity(dataSet);
trimAnalysisProjectAwareEntityForSave(dataSet);
trimDirectoryFileDataSetEntityForSave(dataSet);
this.dataSetEntityService.add(user, dataSet);
copyToDirectoryFileDataSetEntityDirectoryIf(dataSet, "");
@ -299,9 +344,11 @@ public class DataSetController extends AbstractSchemaConnController
}
@RequestMapping("/addForHttp")
public String addForHttp(HttpServletRequest request, org.springframework.ui.Model model)
public String addForHttp(HttpServletRequest request, HttpServletResponse response,
org.springframework.ui.Model model)
{
HttpDataSetEntity dataSet = new HttpDataSetEntity();
setCookieAnalysisProject(request, response, dataSet);
model.addAttribute("dataSet", dataSet);
model.addAttribute("availableCharsetNames", getAvailableCharsetNames());
@ -323,6 +370,8 @@ public class DataSetController extends AbstractSchemaConnController
checkSaveHttpDataSetEntity(dataSet);
trimAnalysisProjectAwareEntityForSave(dataSet);
this.dataSetEntityService.add(user, dataSet);
return buildOperationMessageSaveSuccessResponseEntity(request, dataSet);
@ -362,6 +411,8 @@ public class DataSetController extends AbstractSchemaConnController
checkSaveSqlDataSetEntity(dataSet);
trimAnalysisProjectAwareEntityForSave(dataSet);
this.dataSetEntityService.update(user, dataSet);
return buildOperationMessageSaveSuccessResponseEntity(request, dataSet);
@ -376,6 +427,8 @@ public class DataSetController extends AbstractSchemaConnController
checkSaveJsonValueDataSetEntity(dataSet);
trimAnalysisProjectAwareEntityForSave(dataSet);
this.dataSetEntityService.update(user, dataSet);
return buildOperationMessageSaveSuccessResponseEntity(request, dataSet);
@ -391,6 +444,9 @@ public class DataSetController extends AbstractSchemaConnController
checkSaveJsonFileDataSetEntity(dataSet);
trimAnalysisProjectAwareEntityForSave(dataSet);
trimDirectoryFileDataSetEntityForSave(dataSet);
this.dataSetEntityService.update(user, dataSet);
copyToDirectoryFileDataSetEntityDirectoryIf(dataSet, originalFileName);
@ -407,6 +463,9 @@ public class DataSetController extends AbstractSchemaConnController
checkSaveExcelDataSetEntity(dataSet);
trimAnalysisProjectAwareEntityForSave(dataSet);
trimDirectoryFileDataSetEntityForSave(dataSet);
this.dataSetEntityService.update(user, dataSet);
copyToDirectoryFileDataSetEntityDirectoryIf(dataSet, originalFileName);
@ -422,6 +481,8 @@ public class DataSetController extends AbstractSchemaConnController
checkSaveCsvValueDataSetEntity(dataSet);
trimAnalysisProjectAwareEntityForSave(dataSet);
this.dataSetEntityService.update(user, dataSet);
return buildOperationMessageSaveSuccessResponseEntity(request, dataSet);
@ -437,6 +498,9 @@ public class DataSetController extends AbstractSchemaConnController
checkSaveCsvFileDataSetEntity(dataSet);
trimAnalysisProjectAwareEntityForSave(dataSet);
trimDirectoryFileDataSetEntityForSave(dataSet);
this.dataSetEntityService.update(user, dataSet);
copyToDirectoryFileDataSetEntityDirectoryIf(dataSet, originalFileName);
@ -452,6 +516,8 @@ public class DataSetController extends AbstractSchemaConnController
checkSaveHttpDataSetEntity(dataSet);
trimAnalysisProjectAwareEntityForSave(dataSet);
this.dataSetEntityService.update(user, dataSet);
return buildOperationMessageSaveSuccessResponseEntity(request, dataSet);
@ -501,14 +567,22 @@ public class DataSetController extends AbstractSchemaConnController
DirectoryFileDataSetEntity dataSetEntity = (DirectoryFileDataSetEntity) dataSet;
// 服务端文件允许参数化文件名因而无法再这里下载文件即便如此也可能保存着用户之前编辑的上传文件而允许下载所以不应启用下面的逻辑
// if
// (!DirectoryFileDataSetEntity.FILE_SOURCE_TYPE_UPLOAD.equals(dataSetEntity.getFileSourceType()))
// throw new IllegalInputException();
if (isEmpty(dataSetEntity.getFileName()))
throw new IllegalInputException();
File dataSetDirectory = getDataSetEntityService().getDataSetDirectory(dataSetEntity.getId());
File entityFile = FileUtil.getFile(dataSetDirectory, dataSetEntity.getFileName());
String displayName = dataSetEntity.getDisplayName();
displayName = new String(displayName.getBytes("UTF-8"), "ISO-8859-1");
response.setCharacterEncoding("UTF-8");
response.setHeader("Content-Disposition", "attachment; filename=" + displayName + "");
response.setCharacterEncoding(IOUtil.CHARSET_UTF_8);
response.setHeader("Content-Disposition",
"attachment; filename=" + toResponseAttachmentFileName(request, response, displayName));
OutputStream out = response.getOutputStream();
IOUtil.write(entityFile, out);
@ -539,27 +613,12 @@ public class DataSetController extends AbstractSchemaConnController
return buildFormView(dataSet.getDataSetType());
}
@RequestMapping(value = "/getById", produces = CONTENT_TYPE_JSON)
@RequestMapping(value = "/getProfileDataSetByIds", produces = CONTENT_TYPE_JSON)
@ResponseBody
public DataSetEntity getById(HttpServletRequest request, HttpServletResponse response,
org.springframework.ui.Model model, @RequestParam("id") String id)
{
User user = WebUtils.getUser(request, response);
DataSetEntity dataSet = this.dataSetEntityService.getById(user, id);
if (dataSet == null)
throw new RecordNotFoundException();
return dataSet;
}
@RequestMapping(value = "/getByIds", produces = CONTENT_TYPE_JSON)
@ResponseBody
public List<DataSetEntity> getByIds(HttpServletRequest request, HttpServletResponse response,
public List<ProfileDataSet> getProfileDataSetByIds(HttpServletRequest request, HttpServletResponse response,
org.springframework.ui.Model model, @RequestParam("id") String[] ids)
{
List<DataSetEntity> dataSets = new ArrayList<>();
List<ProfileDataSet> dataSets = new ArrayList<>();
if (!isEmpty(ids))
{
@ -567,7 +626,7 @@ public class DataSetController extends AbstractSchemaConnController
for (String id : ids)
{
DataSetEntity dataSet = this.dataSetEntityService.getById(user, id);
ProfileDataSet dataSet = this.dataSetEntityService.getProfileDataSet(user, id);
if (dataSet == null)
throw new RecordNotFoundException();
@ -624,13 +683,13 @@ public class DataSetController extends AbstractSchemaConnController
@ResponseBody
public PagingData<DataSetEntity> pagingQueryData(HttpServletRequest request, HttpServletResponse response,
final org.springframework.ui.Model springModel,
@RequestBody(required = false) DataFilterPagingQuery pagingQueryParam) throws Exception
@RequestBody(required = false) APIDDataFilterPagingQuery pagingQueryParam) throws Exception
{
User user = WebUtils.getUser(request, response);
final DataFilterPagingQuery pagingQuery = inflateDataFilterPagingQuery(request, pagingQueryParam);
final APIDDataFilterPagingQuery pagingQuery = inflateAPIDDataFilterPagingQuery(request, pagingQueryParam);
PagingData<DataSetEntity> pagingData = this.dataSetEntityService.pagingQuery(user, pagingQuery,
pagingQuery.getDataFilter());
pagingQuery.getDataFilter(), pagingQuery.getAnalysisProjectId());
return pagingData;
}
@ -642,29 +701,22 @@ public class DataSetController extends AbstractSchemaConnController
{
final User user = WebUtils.getUser(request, response);
final SqlDataSet dataSet = preview.getDataSet();
String schemaId = preview.getSchemaId();
TemplateResolvedDataSetResult result = new ReturnSchemaConnExecutor<TemplateResolvedDataSetResult>(request,
response, springModel, schemaId, true)
{
@Override
protected TemplateResolvedDataSetResult execute(HttpServletRequest request, HttpServletResponse response,
org.springframework.ui.Model springModel, Schema schema) throws Throwable
{
checkReadTableDataPermission(schema, user);
// 新建时操作时未创建数据集
boolean notFound = checkDataSetEntityIdReadPermission(user, dataSet.getId());
// 如果数据集已创建则使用数据集权限如果数据集未创建则需使用数据源权限
Schema schema = (notFound ? getSchemaForUserNotNull(user, schemaId) : getSchemaNotNull(schemaId));
SqlDataSet dataSet = preview.getDataSet();
SchemaConnectionFactory connectionFactory = new SchemaConnectionFactory(getConnectionSource(), schema);
dataSet.setConnectionFactory(connectionFactory);
SchemaConnectionFactory connectionFactory = new SchemaConnectionFactory(getConnectionSource(), schema);
dataSet.setConnectionFactory(connectionFactory);
Map<String, Object> convertedParamValues = getDataSetParamValueConverter()
.convert(preview.getParamValues(), dataSet.getParams());
Map<String, Object> convertedParamValues = getDataSetParamValueConverter().convert(preview.getParamValues(),
dataSet.getParams());
TemplateResolvedDataSetResult result = dataSet.resolve(convertedParamValues);
return result;
}
}.execute();
TemplateResolvedDataSetResult result = dataSet.resolve(convertedParamValues);
return result;
}
@ -683,8 +735,12 @@ public class DataSetController extends AbstractSchemaConnController
public TemplateResolvedDataSetResult previewJsonValue(HttpServletRequest request, HttpServletResponse response,
org.springframework.ui.Model springModel, @RequestBody JsonValueDataSetPreview preview) throws Throwable
{
final User user = WebUtils.getUser(request, response);
JsonValueDataSet dataSet = preview.getDataSet();
checkDataSetEntityIdReadPermission(user, dataSet.getId());
Map<String, Object> convertedParamValues = getDataSetParamValueConverter().convert(preview.getParamValues(),
dataSet.getParams());
@ -699,7 +755,12 @@ public class DataSetController extends AbstractSchemaConnController
org.springframework.ui.Model springModel, @RequestBody JsonFileDataSetEntityPreview preview)
throws Throwable
{
final User user = WebUtils.getUser(request, response);
JsonFileDataSetEntity dataSet = preview.getDataSet();
checkDataSetEntityIdReadPermission(user, dataSet.getId());
setDirectoryFileDataSetDirectory(dataSet, preview.getOriginalFileName());
Map<String, Object> convertedParamValues = getDataSetParamValueConverter().convert(preview.getParamValues(),
@ -715,7 +776,12 @@ public class DataSetController extends AbstractSchemaConnController
public ResolvedDataSetResult previewExcel(HttpServletRequest request, HttpServletResponse response,
org.springframework.ui.Model springModel, @RequestBody ExcelDataSetEntityPreview preview) throws Throwable
{
final User user = WebUtils.getUser(request, response);
ExcelDataSetEntity dataSet = preview.getDataSet();
checkDataSetEntityIdReadPermission(user, dataSet.getId());
setDirectoryFileDataSetDirectory(dataSet, preview.getOriginalFileName());
Map<String, Object> convertedParamValues = getDataSetParamValueConverter().convert(preview.getParamValues(),
@ -731,8 +797,12 @@ public class DataSetController extends AbstractSchemaConnController
public TemplateResolvedDataSetResult previewCsvValue(HttpServletRequest request, HttpServletResponse response,
org.springframework.ui.Model springModel, @RequestBody CsvValueDataSetPreview preview) throws Throwable
{
final User user = WebUtils.getUser(request, response);
CsvValueDataSet dataSet = preview.getDataSet();
checkDataSetEntityIdReadPermission(user, dataSet.getId());
Map<String, Object> convertedParamValues = getDataSetParamValueConverter().convert(preview.getParamValues(),
dataSet.getParams());
@ -746,7 +816,12 @@ public class DataSetController extends AbstractSchemaConnController
public ResolvedDataSetResult previewCsvFile(HttpServletRequest request, HttpServletResponse response,
org.springframework.ui.Model springModel, @RequestBody CsvFileDataSetEntityPreview preview) throws Throwable
{
final User user = WebUtils.getUser(request, response);
CsvFileDataSetEntity dataSet = preview.getDataSet();
checkDataSetEntityIdReadPermission(user, dataSet.getId());
setDirectoryFileDataSetDirectory(dataSet, preview.getOriginalFileName());
Map<String, Object> convertedParamValues = getDataSetParamValueConverter().convert(preview.getParamValues(),
@ -762,7 +837,12 @@ public class DataSetController extends AbstractSchemaConnController
public TemplateResolvedDataSetResult previewHttp(HttpServletRequest request, HttpServletResponse response,
org.springframework.ui.Model springModel, @RequestBody HttpDataSetEntityPreview preview) throws Throwable
{
final User user = WebUtils.getUser(request, response);
HttpDataSetEntity dataSet = preview.getDataSet();
checkDataSetEntityIdReadPermission(user, dataSet.getId());
dataSet.setHttpClient(getDataSetEntityService().getHttpClient());
Map<String, Object> convertedParamValues = getDataSetParamValueConverter().convert(preview.getParamValues(),
@ -773,6 +853,37 @@ public class DataSetController extends AbstractSchemaConnController
return result;
}
/**
* 校验指定ID的读权限
*
* @param user
* @param id
* 允许为{@code null}
* @return 返回{@code true}表明记录未找到
*/
protected boolean checkDataSetEntityIdReadPermission(User user, String id) throws PermissionDeniedException
{
boolean notFound = true;
if (!isEmpty(id))
{
int permission = this.dataSetEntityService.getPermission(user, id);
notFound = (DataPermissionEntityService.PERMISSION_NOT_FOUND == permission);
if (!notFound && !Authorization.canRead(permission))
throw new PermissionDeniedException();
}
return notFound;
}
protected void setCookieAnalysisProject(HttpServletRequest request, HttpServletResponse response,
DataSetEntity entity)
{
setCookieAnalysisProjectIfValid(request, response, this.analysisProjectService, entity);
}
protected boolean copyToDirectoryFileDataSetEntityDirectoryIf(DirectoryFileDataSetEntity entity,
String originalFileName) throws IOException
{
@ -864,10 +975,7 @@ public class DataSetController extends AbstractSchemaConnController
{
checkSaveEntity(dataSet);
if (isEmpty(dataSet.getFileName()))
throw new IllegalInputException();
if (isEmpty(dataSet.getDisplayName()))
if (isEmpty(dataSet.getFileName()) && isEmpty(dataSet.getDataSetResFileName()))
throw new IllegalInputException();
}
@ -875,10 +983,7 @@ public class DataSetController extends AbstractSchemaConnController
{
checkSaveEntity(dataSet);
if (isEmpty(dataSet.getFileName()))
throw new IllegalInputException();
if (isEmpty(dataSet.getDisplayName()))
if (isEmpty(dataSet.getFileName()) && isEmpty(dataSet.getDataSetResFileName()))
throw new IllegalInputException();
}
@ -894,10 +999,7 @@ public class DataSetController extends AbstractSchemaConnController
{
checkSaveEntity(dataSet);
if (isEmpty(dataSet.getFileName()))
throw new IllegalInputException();
if (isEmpty(dataSet.getDisplayName()))
if (isEmpty(dataSet.getFileName()) && isEmpty(dataSet.getDataSetResFileName()))
throw new IllegalInputException();
}

View File

@ -0,0 +1,276 @@
/*
* Copyright 2018 datagear.tech. All Rights Reserved.
*/
package org.datagear.web.controller;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.datagear.management.domain.DataSetResDirectory;
import org.datagear.management.domain.User;
import org.datagear.management.service.DataSetResDirectoryService;
import org.datagear.persistence.PagingData;
import org.datagear.persistence.PagingQuery;
import org.datagear.util.FileInfo;
import org.datagear.util.FileUtil;
import org.datagear.util.IDUtil;
import org.datagear.util.StringUtil;
import org.datagear.web.OperationMessage;
import org.datagear.web.util.WebUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
/**
* 数据集资源目录控制器
*
* @author datagear@163.com
*
*/
@Controller
@RequestMapping("/dataSetResDirectory")
public class DataSetResDirectoryController extends AbstractController
{
static
{
AuthorizationResourceMetas.registerForShare(DataSetResDirectory.AUTHORIZATION_RESOURCE_TYPE,
"dataSetResDirectory");
}
@Autowired
private DataSetResDirectoryService dataSetResDirectoryService;
public DataSetResDirectoryController()
{
super();
}
public DataSetResDirectoryService getDataSetResDirectoryService()
{
return dataSetResDirectoryService;
}
public void setDataSetResDirectoryService(DataSetResDirectoryService dataSetResDirectoryService)
{
this.dataSetResDirectoryService = dataSetResDirectoryService;
}
@ExceptionHandler(DataSetResDirectoryNotFoundException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public String handleDataSetResDirectoryNotFoundException(HttpServletRequest request, HttpServletResponse response,
DataSetResDirectoryNotFoundException exception)
{
setOperationMessageForThrowable(request, "dataSetResDirectory.DataSetResDirectoryNotFoundException", exception,
false, exception.getDirectory());
return getErrorView(request, response);
}
@RequestMapping("/add")
public String add(HttpServletRequest request, org.springframework.ui.Model model)
{
DataSetResDirectory dataSetResDirectory = new DataSetResDirectory();
model.addAttribute("dataSetResDirectory", dataSetResDirectory);
model.addAttribute(KEY_TITLE_MESSAGE_KEY, "dataSetResDirectory.addDataSetResDirectory");
model.addAttribute(KEY_FORM_ACTION, "saveAdd");
return "/dataSetResDirectory/dataSetResDirectory_form";
}
@RequestMapping(value = "/saveAdd", produces = CONTENT_TYPE_JSON)
@ResponseBody
public ResponseEntity<OperationMessage> saveAdd(HttpServletRequest request, HttpServletResponse response,
@RequestBody DataSetResDirectory dataSetResDirectory)
{
checkSaveEntity(dataSetResDirectory);
User user = WebUtils.getUser(request, response);
dataSetResDirectory.setId(IDUtil.randomIdOnTime20());
dataSetResDirectory.setCreateUser(user);
this.dataSetResDirectoryService.add(dataSetResDirectory);
return buildOperationMessageSaveSuccessResponseEntity(request, dataSetResDirectory);
}
@RequestMapping("/edit")
public String edit(HttpServletRequest request, HttpServletResponse response, org.springframework.ui.Model model,
@RequestParam("id") String id)
{
User user = WebUtils.getUser(request, response);
DataSetResDirectory dataSetResDirectory = this.dataSetResDirectoryService.getByIdForEdit(user, id);
if (dataSetResDirectory == null)
throw new RecordNotFoundException();
model.addAttribute("dataSetResDirectory", dataSetResDirectory);
model.addAttribute(KEY_TITLE_MESSAGE_KEY, "dataSetResDirectory.editDataSetResDirectory");
model.addAttribute(KEY_FORM_ACTION, "saveEdit");
return "/dataSetResDirectory/dataSetResDirectory_form";
}
@RequestMapping(value = "/saveEdit", produces = CONTENT_TYPE_JSON)
@ResponseBody
public ResponseEntity<OperationMessage> save(HttpServletRequest request, HttpServletResponse response,
@RequestBody DataSetResDirectory dataSetResDirectory)
{
checkSaveEntity(dataSetResDirectory);
User user = WebUtils.getUser(request, response);
this.dataSetResDirectoryService.update(user, dataSetResDirectory);
return buildOperationMessageSaveSuccessResponseEntity(request, dataSetResDirectory);
}
@RequestMapping("/view")
public String view(HttpServletRequest request, HttpServletResponse response, org.springframework.ui.Model model,
@RequestParam("id") String id)
{
User user = WebUtils.getUser(request, response);
DataSetResDirectory dataSetResDirectory = this.dataSetResDirectoryService.getById(user, id);
if (dataSetResDirectory == null)
throw new RecordNotFoundException();
model.addAttribute("dataSetResDirectory", dataSetResDirectory);
model.addAttribute(KEY_TITLE_MESSAGE_KEY, "dataSetResDirectory.viewDataSetResDirectory");
model.addAttribute(KEY_READONLY, true);
return "/dataSetResDirectory/dataSetResDirectory_form";
}
@RequestMapping(value = "/delete", produces = CONTENT_TYPE_JSON)
@ResponseBody
public ResponseEntity<OperationMessage> delete(HttpServletRequest request, HttpServletResponse response,
@RequestBody String[] ids)
{
User user = WebUtils.getUser(request, response);
for (int i = 0; i < ids.length; i++)
{
String id = ids[i];
this.dataSetResDirectoryService.deleteById(user, id);
}
return buildOperationMessageDeleteSuccessResponseEntity(request);
}
@RequestMapping("/pagingQuery")
public String pagingQuery(HttpServletRequest request, HttpServletResponse response,
org.springframework.ui.Model model)
{
User user = WebUtils.getUser(request, response);
model.addAttribute("currentUser", user);
model.addAttribute(KEY_TITLE_MESSAGE_KEY, "dataSetResDirectory.manageDataSetResDirectory");
return "/dataSetResDirectory/dataSetResDirectory_grid";
}
@RequestMapping(value = "/select")
public String select(HttpServletRequest request, HttpServletResponse response, org.springframework.ui.Model model)
{
model.addAttribute(KEY_TITLE_MESSAGE_KEY, "dataSetResDirectory.selectDataSetResDirectory");
model.addAttribute(KEY_SELECT_OPERATION, true);
setIsMultipleSelectAttribute(request, model);
return "/dataSetResDirectory/dataSetResDirectory_grid";
}
@RequestMapping(value = "/pagingQueryData", produces = CONTENT_TYPE_JSON)
@ResponseBody
public PagingData<DataSetResDirectory> pagingQueryData(HttpServletRequest request, HttpServletResponse response,
final org.springframework.ui.Model springModel, @RequestBody(required = false) PagingQuery pagingQueryParam)
throws Exception
{
User user = WebUtils.getUser(request, response);
final PagingQuery pagingQuery = inflatePagingQuery(request, pagingQueryParam);
PagingData<DataSetResDirectory> pagingData = this.dataSetResDirectoryService.pagingQuery(user, pagingQuery);
return pagingData;
}
@RequestMapping(value = "/listFiles", produces = CONTENT_TYPE_JSON)
@ResponseBody
public List<FileInfo> listFiles(HttpServletRequest request, HttpServletResponse response,
final org.springframework.ui.Model springModel, @RequestParam("id") String id) throws Exception
{
User user = WebUtils.getUser(request, response);
DataSetResDirectory dataSetResDirectory = this.dataSetResDirectoryService.getById(user, id);
if (dataSetResDirectory == null)
throw new RecordNotFoundException();
List<FileInfo> fileInfos = new ArrayList<>();
File directory = FileUtil.getDirectory(dataSetResDirectory.getDirectory(), false);
listDataSetResDirectoryFilePaths(directory, "", fileInfos);
return fileInfos;
}
protected void listDataSetResDirectoryFilePaths(File directory, String parentPath, List<FileInfo> fileInfos)
{
if (!directory.exists())
return;
if (!directory.isDirectory())
return;
File[] files = directory.listFiles();
Arrays.sort(files, FILE_NAME_ASC_COMPARATOR);
for (File file : files)
{
String myPath = (StringUtil.isEmpty(parentPath) ? file.getName()
: FileUtil.concatPath(parentPath, file.getName()));
if (file.isDirectory())
listDataSetResDirectoryFilePaths(file, myPath, fileInfos);
else
fileInfos.add(new FileInfo(myPath));
}
}
protected void checkSaveEntity(DataSetResDirectory dataSetResDirectory)
{
if (isBlank(dataSetResDirectory.getDirectory()))
throw new IllegalInputException();
File directory = FileUtil.getDirectory(dataSetResDirectory.getDirectory(), false);
if (!directory.exists())
throw new DataSetResDirectoryNotFoundException(dataSetResDirectory.getDirectory());
}
protected static final Comparator<File> FILE_NAME_ASC_COMPARATOR = new Comparator<File>()
{
@Override
public int compare(File o1, File o2)
{
return o1.getName().compareTo(o2.getName());
}
};
}

View File

@ -0,0 +1,55 @@
/*
* Copyright 2018 datagear.tech. All Rights Reserved.
*/
package org.datagear.web.controller;
import org.datagear.management.domain.DataSetResDirectory;
/**
* {@linkplain DataSetResDirectory#getDirectory()}未找到异常
*
* @author datagear@163.com
*
*/
public class DataSetResDirectoryNotFoundException extends IllegalInputException
{
private static final long serialVersionUID = 1L;
private String directory;
public DataSetResDirectoryNotFoundException(String directory)
{
super();
this.directory = directory;
}
public DataSetResDirectoryNotFoundException(String directory, String message)
{
super(message);
this.directory = directory;
}
public DataSetResDirectoryNotFoundException(String directory, Throwable cause)
{
super(cause);
this.directory = directory;
}
public DataSetResDirectoryNotFoundException(String directory, String message, Throwable cause)
{
super(message, cause);
this.directory = directory;
}
public String getDirectory()
{
return directory;
}
protected void setDirectory(String directory)
{
this.directory = directory;
}
}

View File

@ -245,7 +245,8 @@ public class DriverEntityController extends AbstractController
public void export(HttpServletRequest request, HttpServletResponse response,
@RequestParam(value = "id", required = false) String[] driverEntityIds) throws Exception
{
response.addHeader("Content-Disposition", "attachment;filename=drivers.zip");
response.addHeader("Content-Disposition",
"attachment;filename=" + toResponseAttachmentFileName(request, response, "drivers.zip"));
response.setContentType("application/octet-stream");
ZipOutputStream zout = IOUtil.getZipOutputStream(response.getOutputStream());
@ -393,8 +394,9 @@ public class DriverEntityController extends AbstractController
{
DriverEntity driverEntity = this.driverEntityManager.get(id);
response.setCharacterEncoding("UTF-8");
response.setHeader("Content-Disposition", "attachment; filename=" + fileName + "");
response.setCharacterEncoding(IOUtil.CHARSET_UTF_8);
response.setHeader("Content-Disposition",
"attachment; filename=" + toResponseAttachmentFileName(request, response, fileName));
OutputStream out = response.getOutputStream();
if (driverEntity != null)

View File

@ -285,8 +285,9 @@ public class SqlpadController extends AbstractSchemaConnController
if (!blobFile.exists())
throw new FileNotFoundException(value);
response.setCharacterEncoding("utf-8");
response.setHeader("Content-Disposition", "attachment; filename=BLOB");
response.setCharacterEncoding(IOUtil.CHARSET_UTF_8);
response.setHeader("Content-Disposition",
"attachment; filename=" + toResponseAttachmentFileName(request, response, "BLOB"));
InputStream in = null;
OutputStream out = null;

View File

@ -25,6 +25,8 @@ public class AuthUser implements UserDetails
public static final String ROLE_USER = "ROLE_USER";
public static final String ROLE_ANONYMOUS = "ROLE_ANONYMOUS";
private static final long serialVersionUID = 1L;
private final User user;
@ -37,9 +39,15 @@ public class AuthUser implements UserDetails
this.authorities = new HashSet<GrantedAuthority>();
this.authorities.add(new SimpleGrantedAuthority(ROLE_USER));
if (user.isAdmin())
this.authorities.add(new SimpleGrantedAuthority(ROLE_ADMIN));
if (user.isAnonymous())
this.authorities.add(new SimpleGrantedAuthority(ROLE_ANONYMOUS));
else
{
this.authorities.add(new SimpleGrantedAuthority(ROLE_USER));
if (user.isAdmin())
this.authorities.add(new SimpleGrantedAuthority(ROLE_ADMIN));
}
}
/**

View File

@ -36,10 +36,7 @@ public class SubContextPathRequestMappingHandlerMapping extends RequestMappingHa
public void setSubContextPath(String subContextPath)
{
if (!WebContextPath.isValidSubContextPath(subContextPath))
throw new IllegalArgumentException("[subContextPath] must be start with '/' and not end with '/'");
this.subContextPath = subContextPath;
this.subContextPath = WebContextPath.trimSubContextPath(subContextPath);
}
@Override

View File

@ -28,10 +28,7 @@ public class WebContextPath
public void setSubContextPath(String subContextPath)
{
if (!isValidSubContextPath(subContextPath))
throw new IllegalArgumentException("[subContextPath] must be start with '/' and not end with '/'");
this.subContextPath = subContextPath;
this.subContextPath = trimSubContextPath(subContextPath);
}
/**
@ -93,20 +90,31 @@ public class WebContextPath
}
/**
* 是否合法的子上下文路径
* 修剪子上下文路径
* <p>
* 子上下文路径格式规范空字符串'/'开头且不以'/'结尾
* </p>
*
* @param subContextPath
* @return
*/
public static boolean isValidSubContextPath(String subContextPath)
public static String trimSubContextPath(String subContextPath)
{
if (subContextPath == null)
return false;
return "";
subContextPath = subContextPath.trim();
if (subContextPath.isEmpty())
return true;
return subContextPath;
return subContextPath.matches("^/[^/]+(/[^/]+)*$");
if (!subContextPath.startsWith("/"))
subContextPath = "/" + subContextPath;
while (subContextPath.endsWith("/"))
subContextPath = subContextPath.substring(0, subContextPath.length() - 1);
return subContextPath;
}
/**

View File

@ -0,0 +1,61 @@
/*
* Copyright (c) 2018 datagear.tech. All Rights Reserved.
*/
/**
*
*/
package org.datagear.web.vo;
import org.datagear.management.domain.AnalysisProject;
/**
* 包含{@linkplain AnalysisProject#getId()}信息的查询
*
* @author datagear@163.com
*
*/
public class APIDDataFilterPagingQuery extends DataFilterPagingQuery
{
private static final long serialVersionUID = 1L;
public static final String PROPERTY_APID = "analysisProjectId";
/** 查询的AnalysisProject ID */
private String analysisProjectId = null;
public APIDDataFilterPagingQuery()
{
super();
}
public APIDDataFilterPagingQuery(int page)
{
super(page);
}
public APIDDataFilterPagingQuery(int page, int pageSize)
{
super(page, pageSize);
}
public APIDDataFilterPagingQuery(int page, int pageSize, String keyword)
{
super(page, pageSize, keyword);
}
public APIDDataFilterPagingQuery(int page, int pageSize, String keyword, String condition)
{
super(page, pageSize, keyword, condition);
}
public String getAnalysisProjectId()
{
return analysisProjectId;
}
public void setAnalysisProjectId(String analysisProjectId)
{
this.analysisProjectId = analysisProjectId;
}
}

View File

@ -272,3 +272,27 @@ DataGear版本更新日志
改进:数据集预览时参数化语句解析结果改为通过按钮点击后显示浮动面板,避免影响页面布局;
改进:图表、数据集页面日期类的参数输入框禁用浏览器自动补全功能,避免遮挡日期选择器;
改进:看板编辑页编辑区最大化按钮移至底部;
-----------------------------------------
--v1.13.0
-----------------------------------------
新增CSV文件、Excel、JSON文件数据集新增选择服务端文件功能
新增:表格图表组件新增轮播效果设置项,例如:"{carousel:true}"
新增:新增数据分析项目管理功能,用于分组管理数据集、图表、看板;
新增:看板新增导出功能;
新增:新增数据集资源目录管理功能(仅管理员可用),用于管理数据集可访问的服务端目录;
修复修复环形饼图无法调整环大小的BUG
修复修复分页查询设置页大小无效的BUG
修复修复系统禁用匿名访问后分享给匿名用户的图表、看板展示链接无法访问的BUG
修复修复对于分享SQL数据集如果对其所属数据源无权限在执行预览操作时会报无权操作的BUG
修复修复图表展示页面有时报无权操作的BUG
修复修复数据管理功能添加、编辑操作不支持SQL Server自增长列的BUG
修复修复数据管理功能删除操作对于某些没有主键的表数据无法删除的BUG
改进:表格图表组件设置项支持公用行样式,例如:"{table:{row:{color:'red',...}}}"
改进:参数化数据集无论是否定义参数都将按照参数化内容解析;
改进:更新内置各省地图,解决某些省(比如山东省)地图不准确的问题;
改进:图表编辑页选择数据集时仅加载必要数据集信息,提高加载效率;
改进:操作出现违反数据库完整性约束异常时给出友好提示;
改进主页左上角LOGO添加官网超链接

View File

@ -149,6 +149,7 @@
<ref bean="dataSetEntityService" />
<ref bean="htmlChartWidgetEntityService" />
<ref bean="htmlTplDashboardWidgetEntityService" />
<ref bean="analysisProjectService" />
</list>
</property>
</bean>
@ -269,6 +270,14 @@
<property name="authorizationService" ref="authorizationService" />
</bean>
<bean id="analysisProjectService" class="org.datagear.management.service.impl.AnalysisProjectServiceImpl">
<property name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>
<bean id="dataSetResDirectoryService" class="org.datagear.management.service.impl.DataSetResDirectoryServiceImpl">
<property name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>
<bean id="sqlHistoryService" class="org.datagear.management.service.impl.SqlHistoryServiceImpl">
<property name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>

View File

@ -60,6 +60,21 @@
<intercept-url pattern="${subContextPath}/analysis/chartPlugin/chartPluginManager.js" access="IS_AUTHENTICATED_ANONYMOUSLY,ROLE_USER" />
<intercept-url pattern="${subContextPath}/analysis/chartPlugin/**" access="ROLE_ADMIN" />
<!-- 数据集资源目录管理 -->
<intercept-url pattern="${subContextPath}/dataSetResDirectory/view" access="#{sercurityDisableAnonymous.value ? 'ROLE_USER' : 'IS_AUTHENTICATED_ANONYMOUSLY,ROLE_USER'}" />
<intercept-url pattern="${subContextPath}/dataSetResDirectory/select" access="#{sercurityDisableAnonymous.value ? 'ROLE_USER' : 'IS_AUTHENTICATED_ANONYMOUSLY,ROLE_USER'}" />
<intercept-url pattern="${subContextPath}/dataSetResDirectory/pagingQueryData" access="#{sercurityDisableAnonymous.value ? 'ROLE_USER' : 'IS_AUTHENTICATED_ANONYMOUSLY,ROLE_USER'}" />
<intercept-url pattern="${subContextPath}/dataSetResDirectory/listFiles" access="#{sercurityDisableAnonymous.value ? 'ROLE_USER' : 'IS_AUTHENTICATED_ANONYMOUSLY,ROLE_USER'}" />
<intercept-url pattern="${subContextPath}/dataSetResDirectory/**" access="ROLE_ADMIN" />
<!-- 图表、看板展示功能始终允许匿名用户访问用于支持外部系统iframe嵌套场景 -->
<intercept-url pattern="${subContextPath}/analysis/chart/show/**" access="IS_AUTHENTICATED_ANONYMOUSLY,ROLE_USER" />
<intercept-url pattern="${subContextPath}/analysis/chart/showData" access="IS_AUTHENTICATED_ANONYMOUSLY,ROLE_USER" />
<intercept-url pattern="${subContextPath}/analysis/dashboard/show/**" access="IS_AUTHENTICATED_ANONYMOUSLY,ROLE_USER" />
<intercept-url pattern="${subContextPath}/analysis/dashboard/showData" access="IS_AUTHENTICATED_ANONYMOUSLY,ROLE_USER" />
<intercept-url pattern="${subContextPath}/analysis/dashboard/loadChart" access="IS_AUTHENTICATED_ANONYMOUSLY,ROLE_USER" />
<intercept-url pattern="${subContextPath}/analysis/dashboard/heartbeat" access="IS_AUTHENTICATED_ANONYMOUSLY,ROLE_USER" />
<intercept-url pattern="${subContextPath}/login/**" access="IS_AUTHENTICATED_ANONYMOUSLY" />
<intercept-url pattern="${subContextPath}/register/**" access="IS_AUTHENTICATED_ANONYMOUSLY" />
<intercept-url pattern="${subContextPath}/resetPassword/**" access="IS_AUTHENTICATED_ANONYMOUSLY" />
@ -97,6 +112,7 @@
<beans:ref bean="dataSetEntityService" />
<beans:ref bean="htmlChartWidgetEntityService" />
<beans:ref bean="htmlTplDashboardWidgetEntityService" />
<beans:ref bean="analysisProjectService" />
</beans:list>
</beans:property>
</beans:bean>

View File

@ -1,7 +1,7 @@
#--UTF-8 file--
#系统版本号
version=1.12.0
version=1.13.0
#构建日期
buildDate=${buildtimestamp}

View File

@ -4,6 +4,8 @@ app.name=DataGear
app.fullName=DataGear数据可视化分析平台
app.pageTitle=DataGear - 数据可视化分析平台
app.copyright=Copyright 2018 datagear.tech. All Rights Reserved.
app.license=LGPL-3.0
manage=管理
query=查询
add=添加
edit=编辑
@ -119,6 +121,7 @@ error.MissingServletRequestParameterException=输入非法
error.BindException=输入有误,请检查
error.ConversionException=输入有误,请检查
error.HttpMessageNotReadableException=输入有误,请检查
error.DataIntegrityViolationException=操作失败,违反数据库完整性约束
error.IllegalInputException=输入有误,请检查
error.IllegalArgumentException=输入有误,请检查
error.RecordNotFoundException=记录未找到,或许已被删除
@ -233,6 +236,7 @@ main.manageRole=管理用户组
main.manageSchemaAuth=数据源授权
main.manageChartPlugin=管理图表插件
main.uploadChartPlugin=上传图表插件
main.manageDataSetResDirectory=管理数据集资源目录
main.personalSet=个人设置
main.changeTheme=切换肤色
main.changeTheme.light=浅色
@ -256,6 +260,11 @@ main.tableType.view=视图
main.sqlpad=SQL工作台
main.dataimport=导入数据
main.dataexport=导出数据
main.analysisProject.currentValue=当前数据分析项目
main.analysisProject.currentValue.none=
main.analysisProject.currentValue.clear=清空当前数据分析项目
main.analysisProject.add=添加数据分析项目并设为当前项目
main.analysisProject.manage=管理数据分析项目
#register
register.register=注册
@ -362,6 +371,7 @@ about.about=关于
about.app.name=名称
about.app.version=版本
about.app.website=网站
about.license=许可
#changelog
changelog.changelog=版本更新日志
@ -713,6 +723,12 @@ dataSet.DataSetProperty.DataType.TIME=时间
dataSet.DataSetProperty.DataType.TIMESTAMP=时间戳
dataSet.DataSetProperty.DataType.UNKNOWN=未知
dataSet.noDataSetPropertyDefined=没有定义属性
dataSet.FILE_SOURCE_TYPE_UPLOAD=上传文件
dataSet.FILE_SOURCE_TYPE_SERVER=服务器端文件
dataSet.serverDirectory=服务器端目录
dataSet.serverDirectory.desc=仅可选择管理员授权的目录
dataSet.fileInDirectory=目录内文件名
dataSet.dataSetResFileName.desc=支持参数化语法
#Chart
chart.manageChart=管理图表
@ -753,7 +769,7 @@ dashboard.editDashboard=编辑看板
dashboard.viewDashboard=查看看板
dashboard.selectDashboard=选择看板
dashboard.importDashboard=导入看板
dashboard.name=名称
dashboard.name=看板名称
dashboard.template=模板内容
dashboard.templateEncoding=HTML模板编码
dashboard.templateName=模板文件名
@ -762,7 +778,7 @@ dashboard.createTime=创建时间
dashboard.show=展示
dashboard.import.selectFile=选择文件
dashboard.import.desc=文件格式应为:*.html、*.htm、*.zip
dashboard.import.template.desc=多个模板以英文逗号(,)分隔
dashboard.import.templateName.desc=导入文件中作为看板模板的文件名,应是*.html、*.htm文件多个模板以英文逗号(,)分隔
dashboard.import.validation.importDashboardFileRequired=请选择看板文件
dashboard.import.templateFileNotExists=导入看板文件中没有找到[{0}]模板文件
dashboard.typeChartIdHere=在此输入图表ID
@ -811,4 +827,30 @@ chartPlugin.upload.desc=文件格式应为:*.zip
chartPlugin.upload.review=上传预览
chartPlugin.upload.validation.uploadChartPluginFileRequired=请选择合法的插件文件
chartPlugin.upload.finish=上传完成,成功载入 {0} 个图表插件
chartPlugin.uncategorized=其它
chartPlugin.uncategorized=其它
#数据分析项目
analysisProject.manageAnalysisProject=管理数据分析项目
analysisProject.addAnalysisProject=添加数据分析项目
analysisProject.editAnalysisProject=编辑数据分析项目
analysisProject.viewAnalysisProject=查看数据分析项目
analysisProject.selectAnalysisProject=选择数据分析项目
analysisProject.ownerAnalysisProject=所属项目
analysisProject.auth.resouceTypeLabel=数据分析项目
analysisProject.name=名称
analysisProject.desc=描述
analysisProject.createUser=创建用户
analysisProject.createTime=创建时间
#数据集资源目录
dataSetResDirectory.manageDataSetResDirectory=管理数据集资源目录
dataSetResDirectory.addDataSetResDirectory=添加数据集资源目录
dataSetResDirectory.editDataSetResDirectory=编辑数据集资源目录
dataSetResDirectory.viewDataSetResDirectory=查看数据集资源目录
dataSetResDirectory.selectDataSetResDirectory=选择数据集资源目录
dataSetResDirectory.auth.resouceTypeLabel=数据集资源目录
dataSetResDirectory.directory=目录
dataSetResDirectory.desc=描述
dataSetResDirectory.createUser=创建用户
dataSetResDirectory.createTime=创建时间
dataSetResDirectory.DataSetResDirectoryNotFoundException=目录[{0}]不存在

View File

@ -46,6 +46,10 @@
.dg-chart-table .dg-chart-table-content table.dataTable td.dataTables_empty{
display: none;/*隐藏初始未加载数据时的空行,避免影响样式*/
}
/*轮播表格隐藏竖向滚动条*/
.dg-chart-table.dg-chart-table-carousel .dataTables_scrollBody{
overflow-y: hidden !important;
}
/*标签图表*/
.dg-chart-label{

View File

@ -100,7 +100,8 @@ form .form-content .form-item .form-item-label label{
form .form-content .form-item .form-item-label label[title]{
position: relative;
}
form .form-content .form-item .form-item-label label[title]::after{
form .form-content .form-item .form-item-label label[title]::after,
form .form-content .tip-label::after{
content: "?";
position: absolute;
margin-left: 0.2em;
@ -112,14 +113,16 @@ form .form-content .form-item .form-item-label label[title]::after{
form .form-content .form-item .form-item-value{
display: inline-block;
width: 80%;
margin-left: -0.5em;
margin-left: -0.71em;/*利用左侧外边距、内边距解决元素空隙问题*/
padding-left: 0.71em;
box-sizing: border-box;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
vertical-align: middle;
}
form .form-content .form-item .form-item-value.margin-left-none{
form .form-content .form-item .form-item-value .form-item-value{
margin-left: 0;
padding-left: 0;
}
form .form-content .form-item .form-item-value.text-value{}
form .form-content .form-item .form-item-value.textarea-value{}
@ -136,8 +139,12 @@ form .form-content .form-item .form-item-value .input{
vertical-align: middle;
}
form .form-content .form-item .form-item-value input[type=text],
form .form-content .form-item .form-item-value input[type=password]{
height: 1.5em;
form .form-content .form-item .form-item-value input[type=password],
form .form-content .form-item .form-item-value textarea{
padding: 0.3em 0.41em;
box-sizing: border-box;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
}
form .form-content .form-item .form-item-value textarea{
width: 60%;
@ -148,6 +155,20 @@ form .form-content .form-item .form-item-value .binary-label-input{/*二进制
form .form-content .form-item label.error{
color: red;
padding-left: 0.2em;
white-space: nowrap;
}
form .form-content .form-item .form-item-value.error-newline{/*验证提示信息在新行*/
position: relative;
padding-bottom: 1.4em;
}
form .form-content .form-item .form-item-value.error-newline label.error{
position: absolute;
left: 0.71em;
bottom: 0;
padding-left: 0 !important;
}
form .form-content .form-item .form-item-value .form-item-value.error-newline label.error{
left: 0;
}
form .form-content .form-item .form-item-value input[type=text].error,
form .form-content .form-item .form-item-value input[type=password].error,
@ -281,8 +302,8 @@ form .form-foot .ui-button{
.ui-controlgroup .ui-button-icon-only{
width: 1em;/*减小图标宽度*/
}
.ui-controlgroup .ui-button-icon-only .ui-icon{
top: 30%;/*图标按钮,上下居中*/
.ui-controlgroup .ui-selectmenu-button.ui-button-icon-only .ui-icon{
top: 30%;/*下拉选择组件的图标按钮,上下居中*/
}
.ui-tabs .ui-tabs-panel{
padding: 0.5em 0.7em;
@ -897,81 +918,105 @@ table.dataTable tbody tr td select{
}
.main-page-content .schema-panel .schema-panel-head{
display: inline-block;
width: 100%;
width: 100%;
min-width: 15em;
height: 2.2em;
box-sizing: border-box;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
padding-top: 0.3em;
height: 2.2em;
box-sizing: border-box;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
position: relative;
}
.main-page-content .schema-panel .schema-panel-head .schema-panel-operation{
display: inline-block;
width: 100%;
box-sizing: border-box;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
position: relative;
text-align: right;
padding-right: 1.55em;
}
.main-page-content .schema-panel .schema-panel-head .schema-panel-operation .search{
.main-page-content .schema-panel .schema-panel-head .schema-panel-form{
position: absolute;
left: 0px;
right: 4.5em;
max-width: 14em;
left: 0;
right: 4.15em;
top: 0.3em;
bottom: 0;
max-width: 20em;
box-sizing: border-box;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
}
.main-page-content .schema-panel .schema-panel-head .schema-panel-operation .search form{
position: relative;
.main-page-content .schema-panel .schema-panel-head .schema-panel-form form{
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
box-sizing: border-box;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
}
.main-page-content .schema-panel .schema-panel-head .schema-panel-operation .search .schema-search-switch{
display: inline-block;
float: left;
opacity: 0.4;
filter: Alpha(Opacity=40);
.main-page-content .schema-panel .schema-panel-head .schema-panel-form .schema-search-switch{
position: absolute;
left: 0;
top: 0;
bottom: 0;
width: 16px;
opacity: 0.5;
filter: Alpha(Opacity=50);
cursor: pointer;
}
.main-page-content .schema-panel .schema-panel-head .schema-panel-operation .search .keyword-input-parent{
.main-page-content .schema-panel .schema-panel-head .schema-panel-form .keyword-input-parent{
position: absolute;
left: 16px;
right: 1.4em;
right: 1.5em;
top: 0;
bottom: 0;
font-size: small;
font-size: 0.9em;
}
.main-page-content .schema-panel .schema-panel-head .schema-panel-operation .search .keyword-input-parent .keyword-input{
.main-page-content .schema-panel .schema-panel-head .schema-panel-form .keyword-input-parent .keyword-input{
width: 100%;
height: 100%;
border: 0;
padding: 0 0;
}
.main-page-content .schema-panel .schema-panel-head .schema-panel-operation .search .search-button.ui-button{
.main-page-content .schema-panel .schema-panel-head .schema-panel-form .search-button.ui-button{
border: 0px;
width: 1.4em;
height: 1.4em;
margin: 0 0;
margin-top: -0.2em;
padding-left: 0;
padding-right: 0;
width: 1.4em;
margin: 0 0;
padding-left: 0;
padding-right: 0;
position: absolute;
right: 0;
height: 100%;
}
.main-page-content .schema-panel .schema-panel-head .schema-panel-operation .search .search-button .ui-icon{
opacity: 0.6;
filter: Alpha(Opacity=60);
.main-page-content .schema-panel .schema-panel-head .schema-panel-form .search-button .ui-icon{
opacity: 0.7;
filter: Alpha(Opacity=70);
}
.main-page-content .schema-panel .schema-panel-head .schema-panel-operation{
position: absolute;
right: 0;
width: 3.6em;
top: 0.3em;
bottom: 0;
box-sizing: border-box;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
}
.main-page-content .schema-panel .schema-panel-head .schema-panel-operation .add-schema-button{
border: 0px;
width: 2em;
height: 1.5em;
height: 100%;
margin-right: 1px;
}
.main-page-content .schema-panel .schema-panel-head .schema-panel-operation #schemaOperationMenu{
position: fixed;
z-index: 2;
margin-top: 0.1em;
position: absolute;
z-index: 2;
width: 1.5em;
height: 100%;
}
.main-page-content .schema-panel .schema-panel-head .schema-panel-operation #schemaOperationMenu > li{
width: 100%;
height: 100%;
}
.main-page-content .schema-panel .schema-panel-head .schema-panel-operation #schemaOperationMenu > li > .ui-menu-item-wrapper{
width: 1.5em;
height: 1.5em;
width: 100%;
height: 100%;
}
.main-page-content .schema-panel .schema-panel-head .schema-panel-operation #schemaOperationMenu > li > .ui-menu{
position: fixed;
}
.main-page-content .schema-panel .schema-panel-content{
position: absolute;
@ -1002,10 +1047,102 @@ table.dataTable tbody tr td select{
font-weight: bold;
font-style: italic;
}
.main-page-content .dataAnalysis-panel .dataAnalysis-panel-head{
display: inline-block;
width: 100%;
height: 2.2em;
box-sizing: border-box;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
position: relative;
}
.main-page-content .dataAnalysis-panel .dataAnalysis-panel-head .analysis-project-current{
position: absolute;
left: 0;
right: 4.2em;
top: 0.3em;
bottom: 0;
box-sizing: border-box;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
}
.main-page-content .dataAnalysis-panel .dataAnalysis-panel-head .analysis-project-current .analysis-project-current-value{
position: absolute;
left: 0.2em;
right: 22px;
top: 0.3em;
bottom: 0;
font-size: 0.9em;
white-space: nowrap;
overflow: hidden;
cursor: pointer;
}
.main-page-content .dataAnalysis-panel .dataAnalysis-panel-head .analysis-project-current .analysis-project-current-reset{
position: absolute;
right: 1px;
top: 0;
bottom: 0;
width: 20px;
cursor: pointer;
opacity: 0.5;
filter: Alpha(Opacity=50);
}
.main-page-content .dataAnalysis-panel .dataAnalysis-panel-head .analysis-project-operation{
position: absolute;
right: 0;
width: 4em;
top: 0.3em;
bottom: 0;
box-sizing: border-box;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
text-align: right;
}
.main-page-content .dataAnalysis-panel .dataAnalysis-panel-head .analysis-project-operation .analysis-project-operation-group{
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
}
.main-page-content .dataAnalysis-panel .dataAnalysis-panel-head .analysis-project-operation .ui-button{
border: 0px;
width: 2em;
height: 100%;
}
.main-page-content .dataAnalysis-panel .dataAnalysis-panel-head .analysis-project-list-panel{
position: fixed;
width: 60%;
height: 60%;
margin-top: 2.3em;
z-index: 2;
display: none;
font-size: 0.95em;
}
.main-page-content .dataAnalysis-panel .dataAnalysis-panel-head .analysis-project-list-panel-content{
position: absolute;
left: 0.41em;
top: 0.41em;
right: 0.41em;
bottom: 0.41em;
}
.main-page-content .dataAnalysis-panel .dataAnalysis-panel-head .analysis-project-list-panel-content .dialog-content-container{
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
}
.main-page-content .dataAnalysis-panel .dataAnalysis-panel-head .analysis-project-list-panel-content .page-grid-analysisProject.page-grid .head .view-button{
display: none;
}
.main-page-content .dataAnalysis-panel .dataAnalysis-panel-head .analysis-project-list-panel-content .page-grid-analysisProject.page-grid .content{
bottom: 2.1em;
}
.main-page-content .dataAnalysis-panel .dataAnalysis-panel-content{
position: absolute;
display: block;
top: 0em;
top: 2.2em;
bottom: 0em;
left: 0em;
right: 0em;
@ -1131,7 +1268,7 @@ table.dataTable tbody tr td select{
}
.search-form .keyword-widget{
display: inline-block;
width: 70%;
width: 66%;
height: 2em;
margin-left: 0.1em;
vertical-align: middle;
@ -1155,8 +1292,11 @@ table.dataTable tbody tr td select{
width: 100%;
height: 100%;
border: 0;
padding: 0 0;
padding: 0 0.41em;
margin: 0 0;
box-sizing: border-box;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
}
.search-form .search-condition-icon-parent{
position: relative;
@ -2176,8 +2316,6 @@ table.dataTable tbody tr td select{
}
.page-form-dataSet .workspace .form-item .form-item-value{
width: 39%;
position: relative;
padding-bottom: 1.4em;
}
.page-form-dataSet .workspace .form-item .form-item-value.no-padding-bottom{
padding-bottom: 0;
@ -2188,18 +2326,49 @@ table.dataTable tbody tr td select{
.page-form-dataSet .workspace .form-item .form-item-value .input{
width: 90%;
}
.page-form-dataSet .workspace .form-item .form-item-value input.file-display-name{
width: 60%;
.page-form-dataSet .workspace .form-item .form-item-value.form-item-value-file-input{
padding-bottom: 0;
}
.page-form-dataSet .workspace .form-item .form-item-value .fileinput-wrapper{
padding-top: 0.41em;
.page-form-dataSet .ds-file-input-wrapper input[type=text]{
width: 60% !important;
}
.page-form-dataSet .workspace .form-item label.error{
.page-form-dataSet .ds-file-input-wrapper .row-wrapper{
padding-bottom: 0.41em;
}
.page-form-dataSet .ds-file-input-wrapper .form-item-value{
width: 100% !important;
margin-left: 0 !important;
}
.page-form-dataSet .ds-file-input-wrapper .form-item-value .label{
padding-bottom: 0.14em;
}
.page-form-dataSet .ds-file-input-wrapper .form-item-value-server-file{
position: relative;
}
.page-form-dataSet .ds-file-input-wrapper .form-item-value-server-file .server-file-list-panel{
position: absolute;
left: 0;
bottom: 0;
width: 80%;
height: 8em;
display: none;
}
.page-form-dataSet .ds-file-input-wrapper .form-item-value-server-file .server-file-list-panel .server-file-list-content{
position: absolute;
left: 0.41em;
top: 0.41em;
right: 0.41em;
bottom: 0.41em;
overflow: auto;
}
.page-form-dataSet .ds-file-input-wrapper .form-item-value-server-file .server-file-list-panel .server-file-item{
padding-left: 0.2em;
padding-top: 0.25em;
padding-bottom: 0.25em;
cursor: default;
white-space: nowrap;
}
.page-form-dataSet .ds-file-input-wrapper .form-item-value-server-file .server-file-list-panel .server-file-item.ui-state-active{
border-width: 0;
}
.page-form-dataSet .workspace .workspace-editor-wrapper{
height: 10em;
margin-right: 0.3em;
@ -2330,6 +2499,7 @@ table.dataTable tbody tr td select{
.page-form-chart .data-set-wrapper{
display: inline-block;
width: 60%;
height: 100%;
min-height: 10em;
padding: 0.3em 0.3em;
overflow: auto;
@ -2492,19 +2662,11 @@ table.dataTable tbody tr td select{
.page-form-chart .data-sign-select-panel .select-panel-content .data-sign-item{
margin-bottom: 0.41em;
}
.page-form-chart .form-item-value-chartDataSet{
position: relative;
}
.page-form-chart .form-item-value-chartDataSet > .error{
position: absolute;
bottom: 0;
left: 0;
}
.page-form-chart .add-data-set-button{
vertical-align: top;
position: absolute;
left: 60%;
margin-left: 0.3em;
margin-left: 1em;
}
.page-form-chart .data-set-param-value-panel{
position: absolute;
@ -2565,17 +2727,10 @@ table.dataTable tbody tr td select{
.page-form-dashboard.max-template-editor-left form .form-content .form-item .form-item-value{
width: 100%;
}
.page-form-dashboard .form-item-value-template{
position: relative;
}
.page-form-dashboard .form-item-value-template > .error{
position: absolute;
left: 0;
bottom: 0;
}
.page-form-dashboard .template-editor-wrapper{
position: relative;
width:100%;
height: 100%;
min-height:10em;
display: inline-block;
}
@ -2750,4 +2905,45 @@ table.dataTable tbody tr td select{
position: absolute;
top: 0.5em;
right: 0.5em;
}
.page-form .form-item-analysisProjectAware{
position: relative;
}
.page-form .form-item-analysisProjectAware > .form-item-value{
width: 40% !important;
}
.page-form .form-item-analysisProjectAware > .form-item-value input{
width: 60% !important;
}
.page-form .form-item-analysisProjectAware .form-item-analysisProject{
display: inline-block !important;
min-width: unset !important;
position: absolute;
right: 0;
top: -0.1em;
}
.page-form .form-item-analysisProjectAware .form-item-analysisProject .form-item-label{
width: auto !important;
margin-right: 1em;
}
.page-form .form-item-analysisProjectAware .form-item-analysisProject .form-item-label label{
width: 100%;
}
.page-form .form-item-analysisProjectAware .form-item-analysisProject .form-item-value{
display: inline-block !important;
width: 13em !important;
position: relative;
}
.page-form .form-item-analysisProjectAware .form-item-analysisProject .form-item-value input{
width: 10em !important;
}
.page-form .form-item-analysisProjectAware .form-item-analysisProject .form-item-value .analysisProjectActionSelect{
position: absolute;
right: 0.1em;
}
.page-form .form-item-analysisProjectAware .form-item-analysisProject .form-item-value .analysisProjectActionSelect .analysis-project-menu-root,
.page-form .form-item-analysisProjectAware .form-item-analysisProject .form-item-value .analysisProjectActionSelect .analysis-project-menu-root > .ui-menu-item-wrapper{
width: 1.7em;
height: 2em;
}

View File

@ -93,4 +93,11 @@
margin-left: 0px;
margin-right: 0px;
border: none;
}
/*轻量分页*/
.pagination-light .pagination .to-page,
.pagination-light .pagination .label-pss,
.pagination-light.pagination .to-page,
.pagination-light.pagination .label-pss{
display: none;
}

View File

@ -2116,20 +2116,27 @@
* 为元素设置样式集
*
* @param element HTML元素Jquery对象
* @param stylesObj 样式对象格式为{ color: "...", backgroundColor: "...", fontSize: "...", ... }
* @param stylesObj 样式对象格式为{ color: "...", backgroundColor: "...", fontSize: "...", ... }不合法的项将被忽略
* @return 旧样式集对象
*/
chartFactory.setStyles = function(element, stylesObj)
{
var olds = {};
if(element.length > 0)
element = element[0];
if(stylesObj && element.style != undefined)
{
{
for(var p in stylesObj)
{
var newStyle = stylesObj[p];
//忽略不合法的项
var newStyleType = typeof(newStyle);
if(newStyleType != "string" && newStyleType != "number")
continue;
olds[p] = element.style[p];
element.style[p] = stylesObj[p];
}

View File

@ -574,8 +574,8 @@
data: []
}]
},
chart.options(),
options);
options,
chart.options());
chartSupport.initOptions(chart, options);
@ -725,8 +725,8 @@
data: []
}]
},
chart.options(),
options);
options,
chart.options());
if(horizontal)
{
@ -880,9 +880,9 @@
}
]
},
chart.options(),
options);
options,
chart.options());
chartSupport.initOptions(chart, options);
chart.echartsInit(options);
@ -985,8 +985,8 @@
}
]
},
chart.options(),
options);
options,
chart.options());
chart.echartsInit(options);
};
@ -1098,8 +1098,8 @@
data: []
}]
},
chart.options(),
options);
options,
chart.options());
chartSupport.initOptions(chart, options);
@ -1267,8 +1267,8 @@
data: []
}]
},
chart.options(),
options);
options,
chart.options());
chartSupport.initOptions(chart, options);
@ -1457,8 +1457,8 @@
data: []
}]
},
chart.options(),
options);
options,
chart.options());
chartSupport.initOptions(chart, options);
@ -1673,8 +1673,8 @@
}
]
},
chart.options(),
options);
options,
chart.options());
chartSupport.initOptions(chart, options);
@ -1914,8 +1914,8 @@
}
]
},
chart.options(),
options);
options,
chart.options());
chartSupport.mapInitChart(chart, options);
};
@ -2061,8 +2061,8 @@
}
]
},
chart.options(),
options);
options,
chart.options());
chartSupport.mapInitChart(chart, options);
};
@ -2231,8 +2231,8 @@
label: { position: "right" }
}]
},
chart.options(),
options);
options,
chart.options());
chartSupport.mapInitChart(chart, options);
};
@ -2513,8 +2513,8 @@
data: []
}]
},
chart.options(),
options);
options,
chart.options());
chartSupport.initOptions(chart, options);
@ -2659,8 +2659,8 @@
data: []
}]
},
chart.options(),
options);
options,
chart.options());
chartSupport.initOptions(chart, options);
@ -2804,8 +2804,8 @@
expandAndCollapse: true
}]
},
chart.options(),
options);
options,
chart.options());
chartSupport.initOptions(chart, options);
@ -2882,8 +2882,8 @@
data: []
}]
},
chart.options(),
options);
options,
chart.options());
chartSupport.initOptions(chart, options);
@ -2967,8 +2967,8 @@
data: []
}]
},
chart.options(),
options);
options,
chart.options());
chartSupport.initOptions(chart, options);
@ -3163,8 +3163,8 @@
focusNodeAdjacency: 'allEdges'
}]
},
chart.options(),
options);
options,
chart.options());
//自适应条目宽度和间隔
var chartEle = chart.elementJquery();
@ -3371,8 +3371,8 @@
bottom: "12%",
}]
},
chart.options(),
options);
options,
chart.options());
chartSupport.initOptions(chart, options);
@ -3644,8 +3644,8 @@
}
]
},
chart.options(),
options);
options,
chart.options());
var chartEle = chart.elementJquery();
@ -3778,6 +3778,24 @@
var chartEle = chart.elementJquery();
chartEle.addClass("dg-chart-table");
//默认轮播配置
var carouselConfig =
{
//是否开启
enable: false,
//滚动间隔毫秒数,或者返回间隔毫秒数的函数:
//currentRow 当前可见行
//visibleHeight 当前可见行的剩余可见高度
//height 当前可见行高度
//function(currentRow, visibleHeight, height){ return ...; }
interval: 50,
//滚动跨度像素数,或者返回跨度像素数的函数:
//function(currentRow, visibleHeight, height){ return ...; }
span: 1,
//是否在鼠标悬停时暂停轮播
pauseOnHover: true
};
//表格图表样式设置项
var chartOptions = $.extend(true,
{
@ -3801,22 +3819,22 @@
//行
"row":
{
//公用样式
"color": chartTheme.color,
//偶数行样式
"odd":
{
"color": chartTheme.color,
"backgroundColor": global.chartFactory.getGradualColor(chartTheme, 0)
},
//奇数行样式
"even":
{
"color": chartTheme.color,
"backgroundColor": chartTheme.backgroundColor
},
//悬浮行样式
"hover":
{
"color": chartTheme.color,
"backgroundColor": global.chartFactory.getGradualColor(chartTheme, 0.2)
},
//选中行样式
@ -3834,10 +3852,28 @@
},
//DataTable图表配置项
"ordering": false
"ordering": false,
//轮播格式可以为true、false、轮播interval数值、轮播interval返回函数、{...}
carousel: carouselConfig
},
chart.options(),
options);
options,
chart.options());
if(chartOptions.carousel === true || chartOptions.carousel === false)
{
carouselConfig.enable = chartOptions.carousel;
chartOptions.carousel = carouselConfig;
}
else if(typeof(chartOptions.carousel) == "number" || $.isFunction(chartOptions.carousel))
{
carouselConfig.enable = true;
carouselConfig.interval = chartOptions.carousel;
chartOptions.carousel = carouselConfig;
}
if(chartOptions.carousel.enable)
chartEle.addClass("dg-chart-table-carousel");
var cps = chartSupport.tableGetColumnProperties(chart, columnSign);
var columns = [];
@ -3887,6 +3923,10 @@
{
"emptyTable": "",
"zeroRecords" : ""
},
"rowCallback": function(row, data, displayNum, displayIndex, dataIndex)
{
chartSupport.tableSetTableRowStyle(row, chartOptions);
}
});
@ -3904,14 +3944,7 @@
var dataTable = table.DataTable();
dataTable.on("draw", function()
{
var rowNodes = $(this).DataTable().rows().nodes();
$(rowNodes).each(function()
{
chartSupport.tableSetTableRowStyle(this, chartOptions);
});
})
dataTable
.on("select", function(e, dt, type, indexes )
{
if(type === 'row')
@ -3942,6 +3975,9 @@
$(dataTable.table().body()).on("mouseenter", "tr", function()
{
if(chartOptions.carousel.pauseOnHover)
chartSupport.tableStopCarousel(chart);
if(!$(this).hasClass("selected"))
global.chartFactory.setStyles(this, chartOptions.table.row.hover);
})
@ -3949,6 +3985,9 @@
{
if(!$(this).hasClass("selected"))
chartSupport.tableSetTableRowStyle(this, chartOptions);
if(chartOptions.carousel.pauseOnHover && chartOptions.carousel.enable)
chartSupport.tableStartCarousel(chart);
});
chartSupport.tableEvalDataTableBodyHeight(chartContent, dataTable);
@ -3979,7 +4018,15 @@
}
}
chartSupport.tableStopCarousel(chart);
chartSupport.tableAddDataTableData(dataTable, datas, 0, false);
if(initOptions.carousel.enable)
{
chartSupport.tablePrepareCarousel(chart);
chartSupport.tableStartCarousel(chart);
}
};
chartSupport.tableResize = function(chart)
@ -3993,8 +4040,10 @@
chartSupport.tableDestroy = function(chart)
{
var chartEle = chart.elementJquery();
chartSupport.tableStopCarousel(chart);
chartEle.removeClass("dg-chart-table");
chartEle.removeClass("dg-hide-title");
chartEle.removeClass("dg-chart-table-carousel");
$(".dg-chart-table-title", chartEle).remove();
$(".dg-chart-table-content", chartEle).remove();
};
@ -4077,6 +4126,9 @@
chartSupport.tableSetTableRowStyle = function(rowElement, chartOptions)
{
//公用样式
global.chartFactory.setStyles(rowElement, chartOptions.table.row);
if($(rowElement).hasClass("odd"))
global.chartFactory.setStyles(rowElement, chartOptions.table.row.odd);
else
@ -4124,6 +4176,187 @@
dataTable.draw();
};
/**
* 表格准备轮播
*/
chartSupport.tablePrepareCarousel = function(chart)
{
var initOptions = chartSupport.initOptions(chart);
var chartEle = chart.elementJquery();
var dataTable = chartSupport.tableGetChartDataTable(chart);
var carousel = initOptions.carousel;
var rowCount = dataTable.rows().indexes().length;
//空表格
if(rowCount == 0)
return;
var scrollBody = $(".dataTables_scrollBody", chartEle);
var scrollTable = $(".dataTable", scrollBody);
var scrollBodyHeight = scrollBody.height();
while(true)
{
//必须成倍添加数据,避免出现轮播次序混乱
//且至少添加一倍,保证滚动平滑
for(var i=0; i<rowCount; i++)
{
var addData = dataTable.row(i).data();
dataTable.row.add(addData);
}
dataTable.draw();
var scrollTableHeight = scrollTable.height();
//表格高度至少为容器高度两倍,保证滚动平滑
if(scrollTableHeight >= scrollBodyHeight*2)
break;
}
};
/**
* 表格开始轮播
*/
chartSupport.tableStartCarousel = function(chart)
{
var initOptions = chartSupport.initOptions(chart);
var chartEle = chart.elementJquery();
var dataTable = chartSupport.tableGetChartDataTable(chart);
var rowCount = dataTable.rows().indexes().length;
//空表格
if(rowCount == 0)
return;
chartSupport.tableStopCarousel(chart);
chartEle.data("tableCarouselStatus", "start");
var scrollBody = $(".dataTables_scrollBody", chartEle);
var scrollTable = $(".dataTable", scrollBody);
chartSupport.tableHandleCarousel(chart, initOptions, chartEle, dataTable, scrollBody, scrollTable);
};
/**
* 表格停止轮播
*/
chartSupport.tableStopCarousel = function(chart)
{
var chartEle = chart.elementJquery();
chartEle.data("tableCarouselStatus", "stop");
chartSupport.tableCarouselIntervalId(chart, null);
};
chartSupport.tableHandleCarousel = function(chart, initOptions, chartEle, dataTable, scrollBody, scrollTable)
{
if(chartEle.data("tableCarouselStatus") == "stop")
return;
//不采用设置滚动高度的方式scrollBody.scrollTop()),因为会出现影响整个页面滚动高度的情况
var scrollTop = scrollTable.css("margin-top");
scrollTop = (scrollTop.indexOf("px") == scrollTop.length - 2 ? scrollTop.substring(0, scrollTop.length - 2) : scrollTop);
scrollTop = (Math.abs(parseInt(scrollTop)) || 0);
var currentRow = null;
var currentRowHeight = null;
var currentRowVisibleHeight = null;
var removeRowIndexes = [];
var addRowDatas = [];
var offset = 0;
var idx = 0;
while(true)
{
var row0 = dataTable.row(idx);
var $row0 = $(row0.node());
var row0Height = $row0.outerHeight(true);
//第一行仍可见
if(scrollTop < (offset + row0Height))
{
currentRow = row0.node();
currentRowHeight = row0Height;
currentRowVisibleHeight = offset + row0Height - scrollTop;
break;
}
var row1 = dataTable.row(idx+1);
var $row1 = $(row1.node());
var row1Height = $row1.outerHeight(true);
//第二行仍可见
if(scrollTop < (offset + row0Height + row1Height))
{
currentRow = row1.node();
currentRowHeight = row1Height;
currentRowVisibleHeight = offset + row0Height + row1Height - scrollTop;
break;
}
//必须同时移除两行,不然奇偶行会变化,导致颜色交替重绘
removeRowIndexes.push(idx);
removeRowIndexes.push(idx+1);
addRowDatas.push(row0.data());
addRowDatas.push(row1.data());
offset += row0Height + row1Height;
idx += 2;
}
if(removeRowIndexes.length > 0)
{
dataTable.rows(removeRowIndexes).remove().draw();
scrollTop = scrollTop - offset;
}
var span = ($.isFunction(initOptions.carousel.span) ?
initOptions.carousel.span(currentRow, currentRowVisibleHeight, currentRowHeight) : initOptions.carousel.span);
scrollTable.css("margin-top", (0 - (scrollTop + span))+"px");
if(addRowDatas.length > 0)
dataTable.rows.add(addRowDatas).draw();
var interval = ($.isFunction(initOptions.carousel.interval) ?
initOptions.carousel.interval(currentRow, currentRowVisibleHeight, currentRowHeight) : initOptions.carousel.interval);
var intervalId = setTimeout(function()
{
chartSupport.tableHandleCarousel(chart, initOptions, chartEle, dataTable, scrollBody, scrollTable);
},
interval);
chartSupport.tableCarouselIntervalId(chart, intervalId);
};
/**
* 获取设置表格轮播定时执行ID
*
* @param chart
* @param intervalId 要设置的定时执行ID为null则清除
*/
chartSupport.tableCarouselIntervalId = function(chart, intervalId)
{
var chartEle = chart.elementJquery();
var curIntervalId = chartEle.data("tableCarouselIntervalId");
if(intervalId === undefined)
return curIntervalId;
if(curIntervalId != null)
clearInterval(curIntervalId);
chartEle.data("tableCarouselIntervalId", intervalId);
};
//标签卡
chartSupport.labelRender = function(chart, nameSign, valueSign, options)
@ -4152,8 +4385,8 @@
}
}
},
chart.options(),
options);
options,
chart.options());
chartSupport.initOptions(chart, options);
};

View File

@ -444,7 +444,11 @@
var labeldiv=$("<div class='form-item-label' />").appendTo(itemdiv);
var valuediv=$("<div class='form-item-value' />").appendTo(itemdiv);
var $label = $("<label />").html(columnName).attr("title", (column.comment || columnName)).appendTo(labeldiv);
var $label = $("<label />").html(columnName).appendTo(labeldiv);
var labelTitle = (column.comment || columnName);
//即使labelTitle与columnName一样也显示描述因为columnName可能超长而无法在label内容中完全显示
$label.attr("title", (column.comment || columnName))
if(!$.meta.supportsColumn(column))
{

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