forked from p81075629/datagear
Compare commits
30 Commits
Author | SHA1 | Date |
---|---|---|
![]() |
44928ebc64 | |
![]() |
92139f707f | |
![]() |
bc29ede09a | |
![]() |
15b33e855f | |
![]() |
63b41132b8 | |
![]() |
71e4dd8674 | |
![]() |
62797ab649 | |
![]() |
001f49acb6 | |
![]() |
4ad1838f8e | |
![]() |
8e5d2e22ce | |
![]() |
327fe29bee | |
![]() |
20a9e15f8e | |
![]() |
d334d9197b | |
![]() |
637cd54cc7 | |
![]() |
35e2f0d08b | |
![]() |
93a36b1070 | |
![]() |
ad452ee10b | |
![]() |
a8fb05bb53 | |
![]() |
93a5bc2340 | |
![]() |
cc1b9b6520 | |
![]() |
71f4ceb811 | |
![]() |
4690efeb3f | |
![]() |
62fe947e43 | |
![]() |
3934c8ae46 | |
![]() |
997895cb49 | |
![]() |
f3b83c068a | |
![]() |
1ccc40f7f4 | |
![]() |
521df3639e | |
![]() |
7e66f016be | |
![]() |
8a4b77f1f1 |
|
@ -10,14 +10,14 @@ DataGear是一款开源免费的数据可视化分析平台,可自由制作任
|
|||
|
||||
## 系统特点
|
||||
|
||||
- 支持接入多种数据源
|
||||
<br>支持接入任意提供JDBC驱动的数据库,包括MySQL、Oracle、PostgreSQL、SQL Server等关系数据库,以及Elasticsearch、ClickHouse、Hive等大数据引擎
|
||||
- 动态接入多种数据源
|
||||
<br>支持动态接入任意提供JDBC驱动的数据库,包括MySQL、Oracle、PostgreSQL、SQL Server等关系数据库,以及Elasticsearch、ClickHouse、Hive等大数据引擎
|
||||
|
||||
- 支持多种格式的数据集
|
||||
<br>支持创建SQL、CSV、Excel、HTTP接口、JSON数据集,可将数据集定义为动态参数化数据集,可添加文本框、下拉框、日期框、时间框等类型的数据集参数,为构建动态可交互图表提供支持
|
||||
|
||||
- 丰富强大的图表功能
|
||||
<br>图表可聚合多个不同格式的数据集,轻松构建同比、环比数据图表,内置折线图、柱状图、饼图、地图、雷达图、漏斗图等开箱即用的图表,并且支持自定义图表配置项,支持编写和上传自定义图表插件
|
||||
<br>图表可聚合多个不同格式的数据集,轻松构建同比、环比数据图表,内置折线图、柱状图、饼图、地图、雷达图、漏斗图、散点图、K线图、桑基图等50+开箱即用的图表,并且支持自定义图表配置项,支持编写和上传自定义图表插件
|
||||
|
||||
- 可自由编辑的数据可视化页面
|
||||
<br>可视化页面采用原生的HTML网页作为模板,可自由编辑页面内容,支持导入任意HTML网页,为元素添加扩展属性即可绑定和配置图表,页面内置丰富的API,可构建图表联动、数据钻取、异步加载、交互表单等个性化的数据可视化页面
|
||||
|
|
17
Roadmap.txt
17
Roadmap.txt
|
@ -5,14 +5,16 @@
|
|||
地图热力图
|
||||
路径图
|
||||
下拉框
|
||||
数据集预览即使执行错误也返回解析后的内容,便于用户检查错误;
|
||||
修复登录超时后打开页面内对话框未处理超时的BUG;
|
||||
改进表格图表滚动条样式,使其与图表主题匹配;
|
||||
改进表格轮播性能,解决轮播卡顿问题;
|
||||
修复静态内容类的数据集(CSV、JSON等)修改后必须刷新看板页面才能更新数据的BUG;
|
||||
移除看板展示后台缓存,将看板展示页改为无状态方式
|
||||
修复CSV数据集属性设置日期格式yyyyMMdd无效的BUG(因为值直接被解析成了数值,跳过了格式);
|
||||
升级ECharts至5.2.0版本;
|
||||
ok 修复当登录超时后点击查询页面的查询按钮无响应的BUG;
|
||||
ok 删除用户操作改为必须选择数据迁移目标用户后才能删除;
|
||||
ok 修复静态内容类的数据集(CSV、JSON等)修改后必须刷新看板页面才能更新数据的BUG;
|
||||
ok 改进表格图表滚动条样式,使其与图表主题匹配(仅支持webkit内核浏览器);
|
||||
ok 改进数据集预览功能,当参数、属性、数据格式变化时也必须重新执行预览;
|
||||
ok 修复CSV数据集属性设置日期格式yyyyMMdd无效的BUG(之前版本已修复);
|
||||
ok 标签卡图表添加flex配置项,用于丰富标签卡布局设置功能;
|
||||
ok 升级ECharts至5.2.0版本;
|
||||
ok 数据集预览即使执行出错也返回解析后的内容,便于排查拼写错误;
|
||||
|
||||
待定:
|
||||
|
||||
|
@ -32,6 +34,7 @@
|
|||
待研究:
|
||||
|
||||
提供服务API,使图表、看板可以方便整合至第三方前端代码中;
|
||||
看板多端支持;
|
||||
数据集支持更多数据库,比如:MongoDB;
|
||||
多维分析图表类型;
|
||||
数据填报;
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<groupId>org.datagear</groupId>
|
||||
<artifactId>datagear</artifactId>
|
||||
<version>2.8.0</version>
|
||||
<version>2.9.0</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>datagear-analysis</artifactId>
|
||||
|
|
|
@ -8,9 +8,7 @@
|
|||
package org.datagear.analysis;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 看板。
|
||||
|
@ -18,7 +16,7 @@ import java.util.Map;
|
|||
* @author datagear@163.com
|
||||
*
|
||||
*/
|
||||
public class Dashboard extends AbstractIdentifiable implements Serializable
|
||||
public class Dashboard extends DashboardQueryHandler implements Identifiable, Serializable
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
|
@ -27,6 +25,8 @@ public class Dashboard extends AbstractIdentifiable implements Serializable
|
|||
public static final String PROPERTY_WIDGET = "widget";
|
||||
public static final String PROPERTY_CHARTS = "charts";
|
||||
|
||||
private String id;
|
||||
|
||||
private transient RenderContext renderContext;
|
||||
|
||||
private DashboardWidget widget;
|
||||
|
@ -40,11 +40,23 @@ public class Dashboard extends AbstractIdentifiable implements Serializable
|
|||
|
||||
public Dashboard(String id, RenderContext renderContext, DashboardWidget widget)
|
||||
{
|
||||
super(id);
|
||||
super();
|
||||
this.id = id;
|
||||
this.renderContext = renderContext;
|
||||
this.widget = widget;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId()
|
||||
{
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id)
|
||||
{
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public RenderContext getRenderContext()
|
||||
{
|
||||
return renderContext;
|
||||
|
@ -88,77 +100,61 @@ public class Dashboard extends AbstractIdentifiable implements Serializable
|
|||
/**
|
||||
* 获取指定ID的{@linkplain Chart}。
|
||||
*
|
||||
* @param id
|
||||
* @param chartId
|
||||
* @return 返回{@code null}表示没有找到
|
||||
*/
|
||||
public Chart getChart(String id)
|
||||
public Chart getChart(String chartId)
|
||||
{
|
||||
if (this.charts == null)
|
||||
return null;
|
||||
|
||||
for (Chart chart : this.charts)
|
||||
{
|
||||
if (chart.getId().equals(id))
|
||||
if (chart.getId().equals(chartId))
|
||||
return chart;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取{@linkplain DashboardResult}。
|
||||
*
|
||||
* @param query
|
||||
* @return
|
||||
* @throws DataSetException
|
||||
*/
|
||||
public DashboardResult getResult(DashboardQuery query) throws DataSetException
|
||||
@Override
|
||||
protected ChartDefinition getChartDefinition(String chartId)
|
||||
{
|
||||
Map<String, ChartQuery> chartQueries = query.getChartQueries();
|
||||
boolean suppressChartError = query.isSuppressChartError();
|
||||
return getChart(chartId);
|
||||
}
|
||||
|
||||
Map<String, ChartResult> chartResults = new HashMap<String, ChartResult>(chartQueries.size());
|
||||
Map<String, ChartResultError> chartResultErrors = new HashMap<String, ChartResultError>();
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((id == null) ? 0 : id.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
for (Map.Entry<String, ChartQuery> entry : chartQueries.entrySet())
|
||||
@Override
|
||||
public boolean equals(Object obj)
|
||||
{
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
Dashboard other = (Dashboard) obj;
|
||||
if (id == null)
|
||||
{
|
||||
String chartId = entry.getKey();
|
||||
ChartQuery chartQuery = entry.getValue();
|
||||
Chart chart = getChart(chartId);
|
||||
|
||||
if (chart == null)
|
||||
throw new IllegalArgumentException("Chart '" + chartId + "' not found");
|
||||
|
||||
if (chartQuery.getResultDataFormat() == null && query.getResultDataFormat() != null)
|
||||
{
|
||||
chartQuery = chartQuery.copy();
|
||||
chartQuery.setResultDataFormat(query.getResultDataFormat());
|
||||
}
|
||||
|
||||
ChartResult chartResult = null;
|
||||
|
||||
if (suppressChartError)
|
||||
{
|
||||
try
|
||||
{
|
||||
chartResult = chart.getResult(chartQuery);
|
||||
chartResults.put(chartId, chartResult);
|
||||
}
|
||||
catch (Throwable t)
|
||||
{
|
||||
chartResultErrors.put(chartId, new ChartResultError(t));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
chartResult = chart.getResult(chartQuery);
|
||||
chartResults.put(chartId, chartResult);
|
||||
}
|
||||
if (other.id != null)
|
||||
return false;
|
||||
}
|
||||
else if (!id.equals(other.id))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
DashboardResult dashboardResult = new DashboardResult(chartResults);
|
||||
dashboardResult.setChartResultErrors(chartResultErrors);
|
||||
|
||||
return dashboardResult;
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return getClass().getSimpleName() + " [id=" + id + "]";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
* Copyright 2018 datagear.tech
|
||||
*
|
||||
* Licensed under the LGPLv3 license:
|
||||
* http://www.gnu.org/licenses/lgpl-3.0.html
|
||||
*/
|
||||
|
||||
package org.datagear.analysis;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* {@linkplain DashboardQuery}处理器。
|
||||
*
|
||||
* @author datagear@163.com
|
||||
*
|
||||
*/
|
||||
public abstract class DashboardQueryHandler
|
||||
{
|
||||
public DashboardQueryHandler()
|
||||
{
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取{@linkplain DashboardResult}。
|
||||
*
|
||||
* @param query
|
||||
* @return
|
||||
* @throws DataSetException
|
||||
*/
|
||||
public DashboardResult getResult(DashboardQuery query) throws DataSetException
|
||||
{
|
||||
Map<String, ChartQuery> chartQueries = query.getChartQueries();
|
||||
boolean suppressChartError = query.isSuppressChartError();
|
||||
|
||||
Map<String, ChartResult> chartResults = new HashMap<String, ChartResult>(chartQueries.size());
|
||||
Map<String, ChartResultError> chartResultErrors = new HashMap<String, ChartResultError>();
|
||||
|
||||
for (Map.Entry<String, ChartQuery> entry : chartQueries.entrySet())
|
||||
{
|
||||
String chartId = entry.getKey();
|
||||
ChartQuery chartQuery = entry.getValue();
|
||||
ChartDefinition chart = getChartDefinition(chartId);
|
||||
|
||||
if (chart == null)
|
||||
throw new IllegalArgumentException("Chart '" + chartId + "' not found");
|
||||
|
||||
if (chartQuery.getResultDataFormat() == null && query.getResultDataFormat() != null)
|
||||
{
|
||||
chartQuery = chartQuery.copy();
|
||||
chartQuery.setResultDataFormat(query.getResultDataFormat());
|
||||
}
|
||||
|
||||
ChartResult chartResult = null;
|
||||
|
||||
if (suppressChartError)
|
||||
{
|
||||
try
|
||||
{
|
||||
chartResult = chart.getResult(chartQuery);
|
||||
chartResults.put(chartId, chartResult);
|
||||
}
|
||||
catch (Throwable t)
|
||||
{
|
||||
chartResultErrors.put(chartId, new ChartResultError(t));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
chartResult = chart.getResult(chartQuery);
|
||||
chartResults.put(chartId, chartResult);
|
||||
}
|
||||
}
|
||||
|
||||
DashboardResult dashboardResult = new DashboardResult(chartResults);
|
||||
dashboardResult.setChartResultErrors(chartResultErrors);
|
||||
|
||||
return dashboardResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定图表ID对应的{@linkplain ChartDefinition}。
|
||||
*
|
||||
* @param chartId
|
||||
* {@linkplain Chart#getId()}
|
||||
* @return 允许返回{@code null}
|
||||
*/
|
||||
protected abstract ChartDefinition getChartDefinition(String chartId);
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* Copyright 2018 datagear.tech
|
||||
*
|
||||
* Licensed under the LGPLv3 license:
|
||||
* http://www.gnu.org/licenses/lgpl-3.0.html
|
||||
*/
|
||||
|
||||
package org.datagear.analysis;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 简单{@linkplain DashboardQueryHandler}。
|
||||
*
|
||||
* @author datagear@163.com
|
||||
*
|
||||
*/
|
||||
public class SimpleDashboardQueryHandler extends DashboardQueryHandler
|
||||
{
|
||||
private Map<String, ? extends ChartDefinition> chartDefinitions;
|
||||
|
||||
public SimpleDashboardQueryHandler()
|
||||
{
|
||||
super();
|
||||
}
|
||||
|
||||
public SimpleDashboardQueryHandler(Map<String, ? extends ChartDefinition> chartDefinitions)
|
||||
{
|
||||
super();
|
||||
this.chartDefinitions = chartDefinitions;
|
||||
}
|
||||
|
||||
public Map<String, ? extends ChartDefinition> getChartDefinitions()
|
||||
{
|
||||
return chartDefinitions;
|
||||
}
|
||||
|
||||
public void setChartDefinitions(Map<String, ? extends ChartDefinition> chartDefinitions)
|
||||
{
|
||||
this.chartDefinitions = chartDefinitions;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ChartDefinition getChartDefinition(String chartId)
|
||||
{
|
||||
return (this.chartDefinitions == null ? null : this.chartDefinitions.get(chartId));
|
||||
}
|
||||
}
|
|
@ -119,7 +119,7 @@ public abstract class AbstractCsvDataSet extends AbstractResolvableDataSet imple
|
|||
}
|
||||
catch (Throwable t)
|
||||
{
|
||||
throw new DataSetSourceParseException(t);
|
||||
throw new DataSetSourceParseException(t, reader.getResolvedTemplate());
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
|
|
@ -124,7 +124,7 @@ public abstract class AbstractJsonDataSet extends AbstractResolvableDataSet impl
|
|||
}
|
||||
catch (Throwable t)
|
||||
{
|
||||
throw new DataSetSourceParseException(t);
|
||||
throw new DataSetSourceParseException(t, reader.getResolvedTemplate());
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
|
|
@ -120,4 +120,21 @@ public class ChartWidget extends ChartDefinition implements Serializable
|
|||
{
|
||||
return IDUtil.uuid();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取由{@linkplain ChartWidget#render(RenderContext)}渲染的{@linkplain Chart}所关联的{@linkplain ChartWidget#getId()}。
|
||||
*
|
||||
* @param chart
|
||||
* @return 可能返回{@code null}
|
||||
*/
|
||||
public static String getChartWidget(Chart chart)
|
||||
{
|
||||
if (chart == null)
|
||||
return null;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Object> chartWidgetInfo = (Map<String, Object>) chart.getAttribute(ATTR_CHART_WIDGET);
|
||||
|
||||
return (chartWidgetInfo == null ? null : (String) chartWidgetInfo.get(ChartWidget.PROPERTY_ID));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,6 +19,8 @@ public class DataSetSourceParseException extends DataSetException
|
|||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private String source = null;
|
||||
|
||||
public DataSetSourceParseException()
|
||||
{
|
||||
super();
|
||||
|
@ -38,4 +40,20 @@ public class DataSetSourceParseException extends DataSetException
|
|||
{
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public DataSetSourceParseException(Throwable cause, String source)
|
||||
{
|
||||
super(cause);
|
||||
this.source = source;
|
||||
}
|
||||
|
||||
public String getSource()
|
||||
{
|
||||
return source;
|
||||
}
|
||||
|
||||
public void setSource(String source)
|
||||
{
|
||||
this.source = source;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -335,11 +335,15 @@ public class HttpDataSet extends AbstractResolvableDataSet
|
|||
protected TemplateResolvedDataSetResult resolveResult(DataSetQuery query, List<DataSetProperty> properties,
|
||||
boolean resolveProperties) throws DataSetException
|
||||
{
|
||||
String uri = null;
|
||||
String headerContent = null;
|
||||
String requestContent = null;
|
||||
|
||||
try
|
||||
{
|
||||
String uri = resolveTemplateUri(query);
|
||||
String headerContent = resolveTemplateHeaderContent(query);
|
||||
String requestContent = resolveTemplateRequestContent(query);
|
||||
uri = resolveTemplateUri(query);
|
||||
headerContent = resolveTemplateHeaderContent(query);
|
||||
requestContent = resolveTemplateRequestContent(query);
|
||||
|
||||
ClassicHttpRequest request = createHttpRequest(uri);
|
||||
|
||||
|
@ -353,13 +357,8 @@ public class HttpDataSet extends AbstractResolvableDataSet
|
|||
|
||||
ResolvedDataSetResult result = this.httpClient.execute(request, responseHandler);
|
||||
|
||||
String templateResult = "URI:" + System.lineSeparator() + uri //
|
||||
+ System.lineSeparator() + "-----------------------------------------" + System.lineSeparator() //
|
||||
+ "Request headers:" + System.lineSeparator() + headerContent //
|
||||
+ System.lineSeparator() + "-----------------------------------------" + System.lineSeparator() //
|
||||
+ "Request content:" + System.lineSeparator() + requestContent;
|
||||
|
||||
return new TemplateResolvedDataSetResult(result.getResult(), result.getProperties(), templateResult);
|
||||
return new TemplateResolvedDataSetResult(result.getResult(), result.getProperties(),
|
||||
buildResolvedTemplate(uri, headerContent, requestContent));
|
||||
}
|
||||
catch (DataSetException e)
|
||||
{
|
||||
|
@ -367,10 +366,44 @@ public class HttpDataSet extends AbstractResolvableDataSet
|
|||
}
|
||||
catch (Throwable t)
|
||||
{
|
||||
throw new DataSetSourceParseException(t);
|
||||
throw new DataSetSourceParseException(t, buildResolvedTemplate(uri, headerContent, requestContent));
|
||||
}
|
||||
}
|
||||
|
||||
protected String buildResolvedTemplate(String uri, String headerContent, String requestContent)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
if (!StringUtil.isEmpty(uri))
|
||||
{
|
||||
if (sb.length() > 0)
|
||||
sb.append(
|
||||
System.lineSeparator() + "-----------------------------------------" + System.lineSeparator());
|
||||
|
||||
sb.append("URI:" + System.lineSeparator() + uri);
|
||||
}
|
||||
|
||||
if (!StringUtil.isEmpty(headerContent))
|
||||
{
|
||||
if (sb.length() > 0)
|
||||
sb.append(
|
||||
System.lineSeparator() + "-----------------------------------------" + System.lineSeparator());
|
||||
|
||||
sb.append("Request headers:" + System.lineSeparator() + headerContent);
|
||||
}
|
||||
|
||||
if (!StringUtil.isEmpty(requestContent))
|
||||
{
|
||||
if (sb.length() > 0)
|
||||
sb.append(
|
||||
System.lineSeparator() + "-----------------------------------------" + System.lineSeparator());
|
||||
|
||||
sb.append("Request content:" + System.lineSeparator() + requestContent);
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
protected void setHttpHeaders(ClassicHttpRequest request, String headerContent) throws Throwable
|
||||
{
|
||||
if (StringUtil.isEmpty(headerContent))
|
||||
|
|
|
@ -877,6 +877,13 @@ public abstract class HtmlTplDashboardWidgetRenderer extends TextParserSupport
|
|||
|
||||
List<String> excludes = StringUtil.splitWithTrim(importExclude, ",");
|
||||
|
||||
// 后台生成的样式应该放在最开头,确保页面生成的、用户自定义的css有更高优先级
|
||||
if (!excludes.contains(this.themeImportName))
|
||||
{
|
||||
writeNewLine(out);
|
||||
writeDashboardThemeStyle(renderContext, renderAttr, out, dashboard);
|
||||
}
|
||||
|
||||
if (this.htmlTplDashboardImport != null)
|
||||
{
|
||||
List<ImportItem> importItems = this.htmlTplDashboardImport.getImportItems();
|
||||
|
@ -901,12 +908,6 @@ public abstract class HtmlTplDashboardWidgetRenderer extends TextParserSupport
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!excludes.contains(this.themeImportName))
|
||||
{
|
||||
writeNewLine(out);
|
||||
writeDashboardThemeStyle(renderContext, renderAttr, out, dashboard);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1029,7 +1030,6 @@ public abstract class HtmlTplDashboardWidgetRenderer extends TextParserSupport
|
|||
writeNewLine(out);
|
||||
|
||||
out.write("</style>");
|
||||
writeNewLine(out);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<parent>
|
||||
<groupId>org.datagear</groupId>
|
||||
<artifactId>datagear</artifactId>
|
||||
<version>2.8.0</version>
|
||||
<version>2.9.0</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>datagear-connection</artifactId>
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<groupId>org.datagear</groupId>
|
||||
<artifactId>datagear</artifactId>
|
||||
<version>2.8.0</version>
|
||||
<version>2.9.0</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>datagear-dataexchange</artifactId>
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<parent>
|
||||
<groupId>org.datagear</groupId>
|
||||
<artifactId>datagear</artifactId>
|
||||
<version>2.8.0</version>
|
||||
<version>2.9.0</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>datagear-management</artifactId>
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
package org.datagear.management.domain;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.Set;
|
||||
|
@ -221,4 +222,44 @@ public class User extends AbstractStringIdEntity implements CloneableEntity
|
|||
{
|
||||
return ADMIN_USER_ID.equals(userId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否包含管理员账号。
|
||||
*
|
||||
* @param userIds
|
||||
* @return
|
||||
*/
|
||||
public static boolean containsAdminUser(String[] userIds)
|
||||
{
|
||||
if (userIds == null)
|
||||
return false;
|
||||
|
||||
for (String userId : userIds)
|
||||
{
|
||||
if (ADMIN_USER_ID.equals(userId))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否包含管理员账号。
|
||||
*
|
||||
* @param userIds
|
||||
* @return
|
||||
*/
|
||||
public static boolean containsAdminUser(Collection<String> userIds)
|
||||
{
|
||||
if (userIds == null)
|
||||
return false;
|
||||
|
||||
for (String userId : userIds)
|
||||
{
|
||||
if (ADMIN_USER_ID.equals(userId))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,18 +16,50 @@ package org.datagear.management.service;
|
|||
public interface CreateUserEntityService
|
||||
{
|
||||
/**
|
||||
* 更新创建用户ID。
|
||||
* 更新创建用户。
|
||||
*
|
||||
* @param oldUserId
|
||||
* 待更新的旧用户ID
|
||||
* @param newUserId
|
||||
* 要更新到的新用户ID
|
||||
* @return
|
||||
*/
|
||||
int updateCreateUserId(String oldUserId, String newUserId);
|
||||
|
||||
/**
|
||||
* 更新创建用户。
|
||||
*
|
||||
* @param oldUserIds
|
||||
* 待更新的旧用户ID
|
||||
* @param newUserId
|
||||
* 要更新到的新用户ID
|
||||
* @return
|
||||
*/
|
||||
int updateCreateUserId(String[] oldUserIds, String newUserId);
|
||||
|
||||
/**
|
||||
* 删除指定用户ID的所有实体。
|
||||
*
|
||||
* TODO 有些业务的删除操作并不是仅删除数据库记录那么简单,后续再考虑实现此接口。
|
||||
* <p>
|
||||
* 注意:
|
||||
* </p>
|
||||
* <p>
|
||||
* 这个接口的目的是为删除用户时同时删除其创建的数据提供支持,但它并不能很好地实现,原因如下:
|
||||
* </p>
|
||||
* <ul>
|
||||
* <li>有些业务的删除操作并不是仅删除数据库记录,也可能有相关的外部资源,导致其无法直接通过SQL实现;</li>
|
||||
* <li>待删除的数据有可能被外键引用,而导致删除SQL出错,或者从业务角度来考虑它们不应被删除;</li>
|
||||
* </ul>
|
||||
* <p>
|
||||
* 所以,这里先注释此接口。
|
||||
* </p>
|
||||
* <p>
|
||||
* 对于删除用户操作,应采用如下方式:
|
||||
* </p>
|
||||
* <ol>
|
||||
* <li>使用{@linkplain #updateCreateUserId(String, String)}先将待删除用户的数据迁移另一个用户;</li>
|
||||
* <li>删除用户信息。</li>
|
||||
* </ol>
|
||||
*
|
||||
* @param userIds
|
||||
* @return
|
||||
|
|
|
@ -17,11 +17,4 @@ import org.datagear.management.domain.Schema;
|
|||
*/
|
||||
public interface SchemaService extends DataPermissionEntityService<String, Schema>, CreateUserEntityService
|
||||
{
|
||||
/**
|
||||
* 删除指定用户ID的{@linkplain Schema}。
|
||||
*
|
||||
* @param userIds
|
||||
* @return
|
||||
*/
|
||||
int deleteByUserId(String... userIds);
|
||||
}
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
|
||||
package org.datagear.management.service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.datagear.management.domain.User;
|
||||
|
||||
/**
|
||||
|
@ -33,6 +35,16 @@ public interface UserService extends EntityService<String, User>
|
|||
*/
|
||||
User getByIdNoPassword(String id);
|
||||
|
||||
/**
|
||||
* 根据ID获取用户,其密码已被清除。
|
||||
*
|
||||
* @param ids
|
||||
* @param discardNull
|
||||
* 对于未找到的元素,是否丢弃而不是返回{@code null}元素
|
||||
* @return
|
||||
*/
|
||||
List<User> getByIdsNoPassword(String[] ids, boolean discardNull);
|
||||
|
||||
/**
|
||||
* 更新,但是忽略{@linkplain User#getRoles()}。
|
||||
*
|
||||
|
@ -50,4 +62,32 @@ public interface UserService extends EntityService<String, User>
|
|||
* @return
|
||||
*/
|
||||
boolean updatePasswordById(String id, String newPassword, boolean encrypt);
|
||||
|
||||
/**
|
||||
* 删除用户。
|
||||
* <p>
|
||||
* 注意:此接口仅删除用户本身信息,另参考{@linkplain #deleteByIds(String[], String)}。
|
||||
* </p>
|
||||
*/
|
||||
@Override
|
||||
boolean deleteById(String id);
|
||||
|
||||
/**
|
||||
* 删除用户。
|
||||
* <p>
|
||||
* 注意:此接口仅删除用户本身信息,另参考{@linkplain #deleteByIds(String[], String)}。
|
||||
* </p>
|
||||
*/
|
||||
@Override
|
||||
boolean[] deleteByIds(String[] ids);
|
||||
|
||||
/**
|
||||
* 删除用户,同时将其创建的业务数据都迁移至目标用户。
|
||||
*
|
||||
* @param ids
|
||||
* 待删除的用户ID
|
||||
* @param migrateToId
|
||||
* 业务数据要迁移到的用户ID
|
||||
*/
|
||||
void deleteByIds(String[] ids, String migrateToId);
|
||||
}
|
||||
|
|
|
@ -288,9 +288,9 @@ public abstract class AbstractMybatisDataPermissionEntityService<ID, T extends D
|
|||
}
|
||||
|
||||
@Override
|
||||
protected int updateCreateUserId(String oldUserId, String newUserId)
|
||||
protected int updateCreateUserId(String[] oldUserIds, String newUserId)
|
||||
{
|
||||
int count = super.updateCreateUserId(oldUserId, newUserId);
|
||||
int count = super.updateCreateUserId(oldUserIds, newUserId);
|
||||
|
||||
if (count > 0)
|
||||
permissionCacheInvalidate();
|
||||
|
|
|
@ -263,10 +263,7 @@ public abstract class AbstractMybatisEntityService<ID, T extends Entity<ID>> ext
|
|||
}
|
||||
|
||||
/**
|
||||
* 更新创建用户ID。
|
||||
* <p>
|
||||
* 此方法调用底层的{@code updateCreateUserId} SQL。
|
||||
* </p>
|
||||
* 更新创建用户。
|
||||
* <p>
|
||||
* 此方法主要为子类实现{@linkplain CreateUserEntityService#updateCreateUserId(String, String)}提供支持。
|
||||
* </p>
|
||||
|
@ -274,11 +271,31 @@ public abstract class AbstractMybatisEntityService<ID, T extends Entity<ID>> ext
|
|||
* @param oldUserId
|
||||
* @param newUserId
|
||||
* @return
|
||||
* @see #updateCreateUserId(String[], String)
|
||||
*/
|
||||
protected int updateCreateUserId(String oldUserId, String newUserId)
|
||||
{
|
||||
String[] oldUserIds = new String[] { oldUserId };
|
||||
return updateCreateUserId(oldUserIds, newUserId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新创建用户。
|
||||
* <p>
|
||||
* 此方法调用底层的{@code updateCreateUserId} SQL。
|
||||
* </p>
|
||||
* <p>
|
||||
* 此方法主要为子类实现{@linkplain CreateUserEntityService#updateCreateUserId(String[], String)}提供支持。
|
||||
* </p>
|
||||
*
|
||||
* @param oldUserIds
|
||||
* @param newUserId
|
||||
* @return
|
||||
*/
|
||||
protected int updateCreateUserId(String[] oldUserIds, String newUserId)
|
||||
{
|
||||
Map<String, Object> params = buildParamMap();
|
||||
params.put("oldUserId", oldUserId);
|
||||
params.put("oldUserIds", oldUserIds);
|
||||
params.put("newUserId", newUserId);
|
||||
|
||||
int count = updateMybatis("updateCreateUserId", params);
|
||||
|
@ -293,7 +310,8 @@ public abstract class AbstractMybatisEntityService<ID, T extends Entity<ID>> ext
|
|||
* 如果{@linkplain CreateUserEntity#getCreateUser()}不为空,
|
||||
* 则使用{@linkplain UserService#getByIdNoPassword(String)}对其进行更新。
|
||||
*
|
||||
* @param entity 允许为{@code null}
|
||||
* @param entity
|
||||
* 允许为{@code null}
|
||||
* @param service
|
||||
*/
|
||||
protected void inflateCreateUserEntity(CreateUserEntity<?> entity, UserService service)
|
||||
|
|
|
@ -93,6 +93,12 @@ public class AnalysisProjectServiceImpl extends AbstractMybatisDataPermissionEnt
|
|||
return super.updateCreateUserId(oldUserId, newUserId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int updateCreateUserId(String[] oldUserIds, String newUserId)
|
||||
{
|
||||
return super.updateCreateUserId(oldUserIds, newUserId);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AnalysisProject postProcessGet(AnalysisProject obj)
|
||||
{
|
||||
|
|
|
@ -225,6 +225,12 @@ public class DataSetEntityServiceImpl extends AbstractMybatisDataPermissionEntit
|
|||
return super.updateCreateUserId(oldUserId, newUserId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int updateCreateUserId(String[] oldUserIds, String newUserId)
|
||||
{
|
||||
return super.updateCreateUserId(oldUserIds, newUserId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PagingData<DataSetEntity> pagingQuery(User user, PagingQuery pagingQuery, String dataFilter,
|
||||
String analysisProjectId)
|
||||
|
|
|
@ -77,6 +77,12 @@ public class DataSetResDirectoryServiceImpl extends
|
|||
return super.updateCreateUserId(oldUserId, newUserId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int updateCreateUserId(String[] oldUserIds, String newUserId)
|
||||
{
|
||||
return super.updateCreateUserId(oldUserIds, newUserId);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DataSetResDirectory postProcessGet(DataSetResDirectory obj)
|
||||
{
|
||||
|
|
|
@ -199,6 +199,12 @@ public class HtmlChartWidgetEntityServiceImpl
|
|||
return super.updateCreateUserId(oldUserId, newUserId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int updateCreateUserId(String[] oldUserIds, String newUserId)
|
||||
{
|
||||
return super.updateCreateUserId(oldUserIds, newUserId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PagingData<HtmlChartWidgetEntity> pagingQuery(User user, PagingQuery pagingQuery, String dataFilter,
|
||||
String analysisProjectId)
|
||||
|
|
|
@ -132,6 +132,12 @@ public class HtmlTplDashboardWidgetEntityServiceImpl
|
|||
return super.updateCreateUserId(oldUserId, newUserId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int updateCreateUserId(String[] oldUserIds, String newUserId)
|
||||
{
|
||||
return super.updateCreateUserId(oldUserIds, newUserId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PagingData<HtmlTplDashboardWidgetEntity> pagingQuery(User user, PagingQuery pagingQuery, String dataFilter,
|
||||
String analysisProjectId)
|
||||
|
|
|
@ -7,8 +7,6 @@
|
|||
|
||||
package org.datagear.management.service.impl;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.ibatis.session.SqlSessionFactory;
|
||||
import org.datagear.connection.DriverEntityManager;
|
||||
import org.datagear.management.domain.Schema;
|
||||
|
@ -127,17 +125,9 @@ public class SchemaServiceImpl extends AbstractMybatisDataPermissionEntityServic
|
|||
}
|
||||
|
||||
@Override
|
||||
public int deleteByUserId(String... userIds)
|
||||
public int updateCreateUserId(String[] oldUserIds, String newUserId)
|
||||
{
|
||||
Map<String, Object> params = buildParamMap();
|
||||
params.put("userIds", userIds);
|
||||
|
||||
int count = updateMybatis("deleteByUserId", params);
|
||||
|
||||
if (count > 0)
|
||||
cacheInvalidate();
|
||||
|
||||
return count;
|
||||
return super.updateCreateUserId(oldUserIds, newUserId);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
package org.datagear.management.service.impl;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
@ -17,6 +18,7 @@ import org.apache.ibatis.session.SqlSessionFactory;
|
|||
import org.datagear.management.domain.Role;
|
||||
import org.datagear.management.domain.User;
|
||||
import org.datagear.management.service.AuthorizationListener;
|
||||
import org.datagear.management.service.CreateUserEntityService;
|
||||
import org.datagear.management.service.RoleService;
|
||||
import org.datagear.management.service.UserService;
|
||||
import org.datagear.management.util.dialect.MbSqlDialect;
|
||||
|
@ -41,6 +43,8 @@ public class UserServiceImpl extends AbstractMybatisEntityService<String, User>
|
|||
|
||||
private AuthorizationListener authorizationListener = null;
|
||||
|
||||
private List<CreateUserEntityService> createUserEntityServices = null;
|
||||
|
||||
public UserServiceImpl()
|
||||
{
|
||||
super();
|
||||
|
@ -92,6 +96,16 @@ public class UserServiceImpl extends AbstractMybatisEntityService<String, User>
|
|||
this.authorizationListener = authorizationListener;
|
||||
}
|
||||
|
||||
public List<CreateUserEntityService> getCreateUserEntityServices()
|
||||
{
|
||||
return createUserEntityServices;
|
||||
}
|
||||
|
||||
public void setCreateUserEntityServices(List<CreateUserEntityService> createUserEntityServices)
|
||||
{
|
||||
this.createUserEntityServices = createUserEntityServices;
|
||||
}
|
||||
|
||||
@Override
|
||||
public User getByName(String name)
|
||||
{
|
||||
|
@ -117,6 +131,24 @@ public class UserServiceImpl extends AbstractMybatisEntityService<String, User>
|
|||
return user;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<User> getByIdsNoPassword(String[] ids, boolean discardNull)
|
||||
{
|
||||
List<User> users = new ArrayList<User>();
|
||||
|
||||
for (String id : ids)
|
||||
{
|
||||
User user = getByIdNoPassword(id);
|
||||
|
||||
if (user == null && discardNull)
|
||||
continue;
|
||||
|
||||
users.add(user);
|
||||
}
|
||||
|
||||
return users;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean updatePasswordById(String id, String newPassword, boolean encrypt)
|
||||
{
|
||||
|
@ -141,6 +173,18 @@ public class UserServiceImpl extends AbstractMybatisEntityService<String, User>
|
|||
return update(user, params);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteByIds(String[] ids, String migrateToId)
|
||||
{
|
||||
if (this.createUserEntityServices != null)
|
||||
{
|
||||
for (CreateUserEntityService service : this.createUserEntityServices)
|
||||
service.updateCreateUserId(ids, migrateToId);
|
||||
}
|
||||
|
||||
this.deleteByIds(ids);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void add(User entity, Map<String, Object> params)
|
||||
{
|
||||
|
|
|
@ -848,3 +848,9 @@ CREATE TABLE DATAGEAR_SCHEMA_GUARD
|
|||
SG_CREATE_TIME TIMESTAMP,
|
||||
PRIMARY KEY (SG_ID)
|
||||
);
|
||||
|
||||
|
||||
-----------------------------------------
|
||||
--version[2.9.0], DO NOT EDIT THIS LINE!
|
||||
-----------------------------------------
|
||||
|
||||
|
|
|
@ -26,7 +26,10 @@
|
|||
UPDATE DATAGEAR_ANALYSIS_PROJECT SET
|
||||
AP_CREATE_USER_ID = #{newUserId}
|
||||
WHERE
|
||||
AP_CREATE_USER_ID = #{oldUserId}
|
||||
AP_CREATE_USER_ID IN
|
||||
<foreach item="item" index="index" collection="oldUserIds" open="(" separator="," close=")">
|
||||
#{item}
|
||||
</foreach>
|
||||
</update>
|
||||
|
||||
<delete id="deleteById">
|
||||
|
|
|
@ -142,7 +142,10 @@
|
|||
UPDATE DATAGEAR_DATA_SET SET
|
||||
DS_CREATE_USER_ID = #{newUserId}
|
||||
WHERE
|
||||
DS_CREATE_USER_ID = #{oldUserId}
|
||||
DS_CREATE_USER_ID IN
|
||||
<foreach item="item" index="index" collection="oldUserIds" open="(" separator="," close=")">
|
||||
#{item}
|
||||
</foreach>
|
||||
</update>
|
||||
|
||||
<update id="updateSqlDataSetEntity">
|
||||
|
|
|
@ -26,7 +26,10 @@
|
|||
UPDATE DATAGEAR_DSR_DIRECTORY SET
|
||||
DD_CREATE_USER_ID = #{newUserId}
|
||||
WHERE
|
||||
DD_CREATE_USER_ID = #{oldUserId}
|
||||
DD_CREATE_USER_ID IN
|
||||
<foreach item="item" index="index" collection="oldUserIds" open="(" separator="," close=")">
|
||||
#{item}
|
||||
</foreach>
|
||||
</update>
|
||||
|
||||
<delete id="deleteById">
|
||||
|
|
|
@ -44,7 +44,10 @@
|
|||
UPDATE DATAGEAR_HTML_CHART_WIDGET SET
|
||||
HCW_CREATE_USER_ID = #{newUserId}
|
||||
WHERE
|
||||
HCW_CREATE_USER_ID = #{oldUserId}
|
||||
HCW_CREATE_USER_ID IN
|
||||
<foreach item="item" index="index" collection="oldUserIds" open="(" separator="," close=")">
|
||||
#{item}
|
||||
</foreach>
|
||||
</update>
|
||||
|
||||
<delete id="deleteById">
|
||||
|
|
|
@ -41,7 +41,10 @@
|
|||
UPDATE DATAGEAR_HTML_DASHBOARD SET
|
||||
HD_CREATE_USER_ID = #{newUserId}
|
||||
WHERE
|
||||
HD_CREATE_USER_ID = #{oldUserId}
|
||||
HD_CREATE_USER_ID IN
|
||||
<foreach item="item" index="index" collection="oldUserIds" open="(" separator="," close=")">
|
||||
#{item}
|
||||
</foreach>
|
||||
</update>
|
||||
|
||||
<delete id="deleteById">
|
||||
|
|
|
@ -31,7 +31,10 @@
|
|||
UPDATE DATAGEAR_SCHEMA SET
|
||||
SCHEMA_CREATE_USER_ID = #{newUserId}
|
||||
WHERE
|
||||
SCHEMA_CREATE_USER_ID = #{oldUserId}
|
||||
SCHEMA_CREATE_USER_ID IN
|
||||
<foreach item="item" index="index" collection="oldUserIds" open="(" separator="," close=")">
|
||||
#{item}
|
||||
</foreach>
|
||||
</update>
|
||||
|
||||
<delete id="deleteById">
|
||||
|
@ -40,15 +43,6 @@
|
|||
SCHEMA_ID = #{id}
|
||||
</delete>
|
||||
|
||||
<delete id="deleteByUserId">
|
||||
DELETE FROM DATAGEAR_SCHEMA
|
||||
WHERE
|
||||
SCHEMA_CREATE_USER_ID IN
|
||||
<foreach item="item" index="index" collection="userIds" open="(" separator="," close=")">
|
||||
#{item}
|
||||
</foreach>
|
||||
</delete>
|
||||
|
||||
<select id="getById" resultType="org.datagear.management.domain.Schema">
|
||||
SELECT
|
||||
T.*
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<parent>
|
||||
<groupId>org.datagear</groupId>
|
||||
<artifactId>datagear</artifactId>
|
||||
<version>2.8.0</version>
|
||||
<version>2.9.0</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>datagear-meta</artifactId>
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<parent>
|
||||
<groupId>org.datagear</groupId>
|
||||
<artifactId>datagear</artifactId>
|
||||
<version>2.8.0</version>
|
||||
<version>2.9.0</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>datagear-persistence</artifactId>
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<groupId>org.datagear</groupId>
|
||||
<artifactId>datagear</artifactId>
|
||||
<version>2.8.0</version>
|
||||
<version>2.9.0</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>datagear-util</artifactId>
|
||||
|
|
|
@ -21,7 +21,7 @@ public final class Global
|
|||
}
|
||||
|
||||
/** 当前版本号 */
|
||||
public static final String VERSION = "2.8.0";
|
||||
public static final String VERSION = "2.9.0";
|
||||
|
||||
/** 中文产品名称 */
|
||||
public static final String PRODUCT_NAME_ZH = "数据齿轮";
|
||||
|
|
|
@ -22,6 +22,10 @@
|
|||
#默认角色:匿名用户
|
||||
#defaultRole.anonymous=ROLE_DATA_ADMIN
|
||||
|
||||
#清理临时目录
|
||||
#执行清理时间间隔
|
||||
cleanTempDirectory.interval=0 0 1 * * ?
|
||||
|
||||
#日志级别
|
||||
#ERROR, WARN, INFO, DEBUG, TRACE
|
||||
logging.level.org.datagear=INFO
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
不要删除这个placeholder文件夹,不然程序将无法启动!
|
||||
|
||||
SpringBoot升级至2.4.6版本后,
|
||||
有一个BUG会导致程序启动失败(详见:https://github.com/spring-projects/spring-boot/issues/26627),
|
||||
所以临时添加这个占位文件夹,确保程序可以正常启动。
|
|
@ -6,7 +6,7 @@
|
|||
<parent>
|
||||
<groupId>org.datagear</groupId>
|
||||
<artifactId>datagear</artifactId>
|
||||
<version>2.8.0</version>
|
||||
<version>2.9.0</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>datagear-web</artifactId>
|
||||
|
|
|
@ -54,6 +54,7 @@ import org.datagear.management.service.AnalysisProjectAuthorizationListener;
|
|||
import org.datagear.management.service.AnalysisProjectService;
|
||||
import org.datagear.management.service.AuthorizationListener;
|
||||
import org.datagear.management.service.AuthorizationService;
|
||||
import org.datagear.management.service.CreateUserEntityService;
|
||||
import org.datagear.management.service.DataPermissionEntityService;
|
||||
import org.datagear.management.service.DataSetEntityService;
|
||||
import org.datagear.management.service.DataSetResDirectoryService;
|
||||
|
@ -628,7 +629,7 @@ public class CoreConfig implements ApplicationListener<ContextRefreshedEvent>
|
|||
|
||||
// JS
|
||||
importItems.add(ImportItem.valueOfJavaScript("jquery", libPrefix + "/jquery-1.12.4/jquery-1.12.4.min.js"));
|
||||
importItems.add(ImportItem.valueOfJavaScript("echarts", libPrefix + "/echarts-5.1.2/echarts.js"));
|
||||
importItems.add(ImportItem.valueOfJavaScript("echarts", libPrefix + "/echarts-5.2.0/echarts.min.js"));
|
||||
importItems.add(ImportItem.valueOfJavaScript("wordcloud",
|
||||
libPrefix + "/echarts-wordcloud-2.0.0/echarts-wordcloud.min.js"));
|
||||
importItems.add(ImportItem.valueOfJavaScript("liquidfill",
|
||||
|
@ -769,6 +770,7 @@ public class CoreConfig implements ApplicationListener<ContextRefreshedEvent>
|
|||
initAnalysisProjectAuthorizationListenerAwares(context);
|
||||
initServiceCaches(context);
|
||||
initDevotedDataExchangeServices(context);
|
||||
initUserServiceCreateUserEntityServices(context);
|
||||
}
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
|
@ -838,4 +840,29 @@ public class CoreConfig implements ApplicationListener<ContextRefreshedEvent>
|
|||
devotedDataExchangeServices.add(this.batchDataExchangeService());
|
||||
this.dataExchangeService().setDevotedDataExchangeServices(devotedDataExchangeServices);
|
||||
}
|
||||
|
||||
protected void initUserServiceCreateUserEntityServices(ApplicationContext context)
|
||||
{
|
||||
List<CreateUserEntityService> serviceList = getCreateUserEntityServices(context);
|
||||
|
||||
UserService userService = this.userService();
|
||||
|
||||
if (userService instanceof UserServiceImpl)
|
||||
((UserServiceImpl) userService).setCreateUserEntityServices(serviceList);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有{@linkplain CreateUserEntityService}实例。
|
||||
*
|
||||
* @param context
|
||||
* @return
|
||||
*/
|
||||
public static List<CreateUserEntityService> getCreateUserEntityServices(ApplicationContext context)
|
||||
{
|
||||
Map<String, CreateUserEntityService> serviceMap = context.getBeansOfType(CreateUserEntityService.class);
|
||||
List<CreateUserEntityService> serviceList = new ArrayList<CreateUserEntityService>(serviceMap.size());
|
||||
serviceList.addAll(serviceMap.values());
|
||||
|
||||
return serviceList;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,8 +21,11 @@ import org.datagear.web.security.AuthUser;
|
|||
import org.datagear.web.security.AuthenticationSuccessHandlerImpl;
|
||||
import org.datagear.web.security.UserDetailsServiceImpl;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.event.ContextRefreshedEvent;
|
||||
import org.springframework.security.authentication.AnonymousAuthenticationProvider;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.builders.WebSecurity;
|
||||
|
@ -38,7 +41,7 @@ import org.springframework.security.web.firewall.StrictHttpFirewall;
|
|||
* @author datagear@163.com
|
||||
*/
|
||||
@Configuration
|
||||
public class SecurityConfig extends WebSecurityConfigurerAdapter
|
||||
public class SecurityConfig extends WebSecurityConfigurerAdapter implements ApplicationListener<ContextRefreshedEvent>
|
||||
{
|
||||
/**
|
||||
* 授权角色:(登录用户 或 系统管理员) 且 数据管理员
|
||||
|
@ -121,16 +124,11 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter
|
|||
this.coreConfig = coreConfig;
|
||||
}
|
||||
|
||||
protected AuthenticationSuccessHandler getAuthenticationSuccessHandler()
|
||||
@Bean
|
||||
public AuthenticationSuccessHandler authenticationSuccessHandler()
|
||||
{
|
||||
AuthenticationSuccessHandlerImpl bean = new AuthenticationSuccessHandlerImpl();
|
||||
|
||||
List<CreateUserEntityService> createUserEntityServices = Arrays.asList(this.coreConfig.schemaService(),
|
||||
this.coreConfig.dataSetEntityService(), this.coreConfig.htmlChartWidgetEntityService(),
|
||||
this.coreConfig.htmlTplDashboardWidgetEntityService(), this.coreConfig.analysisProjectService());
|
||||
|
||||
bean.setCreateUserEntityServices(createUserEntityServices);
|
||||
|
||||
return bean;
|
||||
}
|
||||
|
||||
|
@ -299,7 +297,7 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter
|
|||
.antMatchers("/**").access(disableAnonymous ? AUTH_USER_ADMIN : AUTH_ANONYMOUS_USER_ADMIN)
|
||||
|
||||
.and().formLogin().loginPage("/login").loginProcessingUrl("/login/doLogin").usernameParameter("name")
|
||||
.passwordParameter("password").successHandler(getAuthenticationSuccessHandler())
|
||||
.passwordParameter("password").successHandler(authenticationSuccessHandler())
|
||||
|
||||
.and().logout().logoutUrl("/logout").invalidateHttpSession(true).logoutSuccessUrl("/")
|
||||
|
||||
|
@ -351,4 +349,22 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter
|
|||
firewall.setAllowSemicolon(true);
|
||||
return firewall;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onApplicationEvent(ContextRefreshedEvent event)
|
||||
{
|
||||
ApplicationContext context = event.getApplicationContext();
|
||||
|
||||
inflateAuthenticationSuccessHandler(context);
|
||||
}
|
||||
|
||||
protected void inflateAuthenticationSuccessHandler(ApplicationContext context)
|
||||
{
|
||||
List<CreateUserEntityService> serviceList = CoreConfig.getCreateUserEntityServices(context);
|
||||
|
||||
AuthenticationSuccessHandler ash = authenticationSuccessHandler();
|
||||
|
||||
if (ash instanceof AuthenticationSuccessHandlerImpl)
|
||||
((AuthenticationSuccessHandlerImpl) ash).setCreateUserEntityServices(serviceList);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ import java.io.Serializable;
|
|||
import java.io.Writer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
@ -30,10 +31,12 @@ import org.datagear.analysis.DashboardTheme;
|
|||
import org.datagear.analysis.DashboardThemeSource;
|
||||
import org.datagear.analysis.DataSetQuery;
|
||||
import org.datagear.analysis.RenderContext;
|
||||
import org.datagear.analysis.SimpleDashboardQueryHandler;
|
||||
import org.datagear.analysis.support.ChartWidget;
|
||||
import org.datagear.analysis.support.DataSetParamValueConverter;
|
||||
import org.datagear.analysis.support.DefaultRenderContext;
|
||||
import org.datagear.analysis.support.SimpleDashboardThemeSource;
|
||||
import org.datagear.analysis.support.html.HtmlTplDashboard;
|
||||
import org.datagear.analysis.support.html.HtmlChartWidget;
|
||||
import org.datagear.analysis.support.html.HtmlTplDashboardRenderAttr;
|
||||
import org.datagear.analysis.support.html.HtmlTplDashboardRenderAttr.WebContext;
|
||||
import org.datagear.analysis.support.html.HtmlTplDashboardWidgetRenderer;
|
||||
|
@ -167,34 +170,64 @@ public abstract class AbstractDataAnalysisController extends AbstractController
|
|||
* 获取看板结果。
|
||||
*
|
||||
* @param request
|
||||
* @param response
|
||||
* @param model
|
||||
* @param webContext
|
||||
* @param form
|
||||
* @param renderer
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
protected DashboardResult getDashboardResult(HttpServletRequest request, HttpServletResponse response,
|
||||
org.springframework.ui.Model model, WebContext webContext, DashboardQueryForm form) throws Exception
|
||||
protected DashboardResult getDashboardResult(HttpServletRequest request, DashboardQueryForm form,
|
||||
HtmlTplDashboardWidgetRenderer renderer)
|
||||
{
|
||||
String dashboardId = form.getDashboardId();
|
||||
DashboardQuery dashboardQuery = form.getDashboardQuery();
|
||||
|
||||
if (StringUtil.isEmpty(dashboardId))
|
||||
if (StringUtil.isEmpty(form.getDashboardId()))
|
||||
throw new IllegalInputException();
|
||||
|
||||
SessionHtmlTplDashboardManager dashboardManager = getSessionHtmlTplDashboardManagerNotNull(request);
|
||||
HtmlTplDashboard dashboard = dashboardManager.get(dashboardId);
|
||||
|
||||
if (dashboard == null)
|
||||
throw new RecordNotFoundException();
|
||||
SessionDashboardInfoManager dashboardInfoManager = getSessionDashboardInfoManagerNotNull(request);
|
||||
DashboardInfo dashboardInfo = dashboardInfoManager.get(form.getDashboardId());
|
||||
|
||||
DashboardQuery queriesConverted = convertDashboardQuery(dashboard, dashboardQuery);
|
||||
if (dashboardInfo == null)
|
||||
throw new IllegalInputException();
|
||||
|
||||
return dashboard.getResult(queriesConverted);
|
||||
DashboardQuery dashboardQuery = form.getDashboardQuery();
|
||||
Map<String, HtmlChartWidget> chartWidgets = getChartWidgets(form.getDashboardQuery(), dashboardInfo, renderer);
|
||||
|
||||
DashboardQuery queriesConverted = convertDashboardQuery(dashboardQuery, chartWidgets);
|
||||
|
||||
SimpleDashboardQueryHandler dqh = new SimpleDashboardQueryHandler(chartWidgets);
|
||||
|
||||
return dqh.getResult(queriesConverted);
|
||||
}
|
||||
|
||||
protected DashboardQuery convertDashboardQuery(Dashboard dashboard, DashboardQuery query)
|
||||
/**
|
||||
* 获取【图表ID-图表部件】映射表。
|
||||
*
|
||||
* @param query
|
||||
* @param dashboardInfo
|
||||
* @param renderer
|
||||
* @return
|
||||
*/
|
||||
protected Map<String, HtmlChartWidget> getChartWidgets(DashboardQuery query, DashboardInfo dashboardInfo,
|
||||
HtmlTplDashboardWidgetRenderer renderer)
|
||||
{
|
||||
Map<String, ChartQuery> chartQueries = query.getChartQueries();
|
||||
|
||||
Map<String, HtmlChartWidget> chartWidgets = new HashMap<String, HtmlChartWidget>(chartQueries.size());
|
||||
|
||||
for (String chartId : chartQueries.keySet())
|
||||
{
|
||||
String chartWidgetId = dashboardInfo.getChartWidgetId(chartId);
|
||||
|
||||
if (chartWidgetId == null)
|
||||
throw new IllegalInputException("Chart '" + chartId + "' not found");
|
||||
|
||||
HtmlChartWidget chartWidget = renderer.getHtmlChartWidget(chartWidgetId);
|
||||
|
||||
chartWidgets.put(chartId, chartWidget);
|
||||
}
|
||||
|
||||
return chartWidgets;
|
||||
}
|
||||
|
||||
protected DashboardQuery convertDashboardQuery(DashboardQuery query,
|
||||
Map<String, ? extends ChartWidget> chartWidgets)
|
||||
{
|
||||
if (query == null)
|
||||
return new DashboardQuery();
|
||||
|
@ -206,12 +239,12 @@ public abstract class AbstractDataAnalysisController extends AbstractController
|
|||
{
|
||||
String chartId = entry.getKey();
|
||||
ChartQuery chartQuery = entry.getValue();
|
||||
Chart chart = dashboard.getChart(chartId);
|
||||
ChartWidget chartWidget = chartWidgets.get(chartId);
|
||||
|
||||
if (chart == null)
|
||||
if (chartWidget == null)
|
||||
throw new IllegalInputException("Chart '" + chartId + "' not found");
|
||||
|
||||
ChartDataSet[] chartDataSets = chart.getChartDataSets();
|
||||
ChartDataSet[] chartDataSets = chartWidget.getChartDataSets();
|
||||
List<DataSetQuery> dataSetQueries = chartQuery.getDataSetQueries();
|
||||
|
||||
ChartQuery chartQueryRe = null;
|
||||
|
@ -245,25 +278,6 @@ public abstract class AbstractDataAnalysisController extends AbstractController
|
|||
return queryRe;
|
||||
}
|
||||
|
||||
protected SessionHtmlTplDashboardManager getSessionHtmlTplDashboardManagerNotNull(HttpServletRequest request)
|
||||
{
|
||||
HttpSession session = request.getSession();
|
||||
|
||||
SessionHtmlTplDashboardManager dashboardManager = (SessionHtmlTplDashboardManager) session
|
||||
.getAttribute(SessionHtmlTplDashboardManager.class.getName());
|
||||
|
||||
synchronized (session)
|
||||
{
|
||||
if (dashboardManager == null)
|
||||
{
|
||||
dashboardManager = new SessionHtmlTplDashboardManager();
|
||||
session.setAttribute(SessionHtmlTplDashboardManager.class.getName(), dashboardManager);
|
||||
}
|
||||
}
|
||||
|
||||
return dashboardManager;
|
||||
}
|
||||
|
||||
protected void addHeartBeatValue(HttpServletRequest request, WebContext webContext)
|
||||
{
|
||||
String heartbeatURL = "/dashboard" + DashboardController.HEARTBEAT_TAIL_URL;
|
||||
|
@ -288,34 +302,25 @@ public abstract class AbstractDataAnalysisController extends AbstractController
|
|||
return WebUtils.addJsessionidParam(url, sessionId);
|
||||
}
|
||||
|
||||
protected static class SessionHtmlTplDashboardManager implements Serializable
|
||||
protected SessionDashboardInfoManager getSessionDashboardInfoManagerNotNull(HttpServletRequest request)
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
HttpSession session = request.getSession();
|
||||
|
||||
private transient Map<String, HtmlTplDashboard> htmlTplDashboards;
|
||||
SessionDashboardInfoManager dashboardManager = (SessionDashboardInfoManager) session
|
||||
.getAttribute(SessionDashboardInfoManager.class.getName());
|
||||
|
||||
public SessionHtmlTplDashboardManager()
|
||||
synchronized (session)
|
||||
{
|
||||
super();
|
||||
if (dashboardManager == null)
|
||||
{
|
||||
dashboardManager = new SessionDashboardInfoManager();
|
||||
session.setAttribute(SessionDashboardInfoManager.class.getName(), dashboardManager);
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized HtmlTplDashboard get(String htmlTplDashboardId)
|
||||
{
|
||||
if (this.htmlTplDashboards == null)
|
||||
return null;
|
||||
|
||||
return this.htmlTplDashboards.get(htmlTplDashboardId);
|
||||
}
|
||||
|
||||
public synchronized void put(HtmlTplDashboard dashboard)
|
||||
{
|
||||
if (this.htmlTplDashboards == null)
|
||||
this.htmlTplDashboards = new HashMap<>();
|
||||
|
||||
this.htmlTplDashboards.put(dashboard.getId(), dashboard);
|
||||
}
|
||||
return dashboardManager;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 看板查询表单。
|
||||
*
|
||||
|
@ -353,4 +358,96 @@ public abstract class AbstractDataAnalysisController extends AbstractController
|
|||
this.dashboardQuery = dashboardQuery;
|
||||
}
|
||||
}
|
||||
|
||||
protected static class SessionDashboardInfoManager implements Serializable
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private Map<String, DashboardInfo> dashboardInfos = null;
|
||||
|
||||
public SessionDashboardInfoManager()
|
||||
{
|
||||
super();
|
||||
}
|
||||
|
||||
public synchronized DashboardInfo get(String dashboardId)
|
||||
{
|
||||
if (this.dashboardInfos == null)
|
||||
return null;
|
||||
|
||||
return this.dashboardInfos.get(dashboardId);
|
||||
}
|
||||
|
||||
public synchronized void put(DashboardInfo dashboardInfo)
|
||||
{
|
||||
if (this.dashboardInfos == null)
|
||||
this.dashboardInfos = new HashMap<>();
|
||||
|
||||
this.dashboardInfos.put(dashboardInfo.getDashboardId(), dashboardInfo);
|
||||
}
|
||||
}
|
||||
|
||||
protected static class DashboardInfo implements Serializable
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**看板ID*/
|
||||
private final String dashboardId;
|
||||
|
||||
/**看板部件ID*/
|
||||
private final String dashboardWidgetId;
|
||||
|
||||
/** 图表ID-图表部件ID映射表 */
|
||||
private final Map<String, String> chartIdToChartWidgetIds = new HashMap<String, String>();
|
||||
|
||||
public DashboardInfo(String dashboardId, String dashboardWidgetId)
|
||||
{
|
||||
super();
|
||||
this.dashboardId = dashboardId;
|
||||
this.dashboardWidgetId = dashboardWidgetId;
|
||||
}
|
||||
|
||||
public DashboardInfo(Dashboard dashboard)
|
||||
{
|
||||
this.dashboardId = dashboard.getId();
|
||||
this.dashboardWidgetId = dashboard.getWidget().getId();
|
||||
|
||||
if (dashboard.hasChart())
|
||||
{
|
||||
List<Chart> charts = dashboard.getCharts();
|
||||
for (Chart chart : charts)
|
||||
this.chartIdToChartWidgetIds.put(chart.getId(), ChartWidget.getChartWidget(chart));
|
||||
}
|
||||
}
|
||||
|
||||
public String getDashboardId()
|
||||
{
|
||||
return dashboardId;
|
||||
}
|
||||
|
||||
public String getDashboardWidgetId()
|
||||
{
|
||||
return dashboardWidgetId;
|
||||
}
|
||||
|
||||
public synchronized Map<String, String> getChartIdToChartWidgetIds()
|
||||
{
|
||||
return Collections.unmodifiableMap(chartIdToChartWidgetIds);
|
||||
}
|
||||
|
||||
public synchronized String getChartWidgetId(String chartId)
|
||||
{
|
||||
return this.chartIdToChartWidgetIds.get(chartId);
|
||||
}
|
||||
|
||||
public synchronized void putChartWidgetId(String chartId, String chartWidgetId)
|
||||
{
|
||||
this.chartIdToChartWidgetIds.put(chartId, chartWidgetId);
|
||||
}
|
||||
|
||||
public synchronized void putChartWidgetIds(Map<String, String> chartIdToChartWidgetIds)
|
||||
{
|
||||
this.chartIdToChartWidgetIds.putAll(chartIdToChartWidgetIds);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -481,8 +481,8 @@ public class ChartController extends AbstractChartPluginAwareController implemen
|
|||
public ErrorMessageDashboardResult showData(HttpServletRequest request, HttpServletResponse response,
|
||||
org.springframework.ui.Model model, @RequestBody DashboardQueryForm form) throws Exception
|
||||
{
|
||||
WebContext webContext = createWebContext(request);
|
||||
DashboardResult dashboardResult = getDashboardResult(request, response, model, webContext, form);
|
||||
DashboardResult dashboardResult = getDashboardResult(request, form,
|
||||
this.chartShowHtmlTplDashboardWidgetHtmlRenderer);
|
||||
|
||||
return new ErrorMessageDashboardResult(dashboardResult, true);
|
||||
}
|
||||
|
@ -526,8 +526,8 @@ public class ChartController extends AbstractChartPluginAwareController implemen
|
|||
|
||||
HtmlTplDashboard dashboard = dashboardWidget.render(renderContext);
|
||||
|
||||
SessionHtmlTplDashboardManager dashboardManager = getSessionHtmlTplDashboardManagerNotNull(request);
|
||||
dashboardManager.put(dashboard);
|
||||
SessionDashboardInfoManager dashboardInfoManager = getSessionDashboardInfoManagerNotNull(request);
|
||||
dashboardInfoManager.put(new DashboardInfo(dashboard));
|
||||
}
|
||||
|
||||
protected WebContext createWebContext(HttpServletRequest request)
|
||||
|
|
|
@ -446,7 +446,7 @@ public class ControllerAdvice extends AbstractController
|
|||
DataSetSourceParseException exception)
|
||||
{
|
||||
setOperationMessageForThrowable(request, buildMessageCode(DataSetSourceParseException.class), exception, false,
|
||||
exception.getMessage());
|
||||
exception.getMessage(), exception.getSource());
|
||||
|
||||
return getErrorView(request, response);
|
||||
}
|
||||
|
@ -457,7 +457,7 @@ public class ControllerAdvice extends AbstractController
|
|||
HttpServletResponse response, SqlDataSetSqlExecutionException exception)
|
||||
{
|
||||
setOperationMessageForThrowable(request, buildMessageCode(SqlDataSetSqlExecutionException.class), exception,
|
||||
false, exception.getMessage());
|
||||
false, exception.getMessage(), exception.getSql());
|
||||
|
||||
return getErrorView(request, response);
|
||||
}
|
||||
|
|
|
@ -28,7 +28,6 @@ import javax.servlet.http.HttpServletRequest;
|
|||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
||||
import org.datagear.analysis.Chart;
|
||||
import org.datagear.analysis.DashboardResult;
|
||||
import org.datagear.analysis.RenderContext;
|
||||
import org.datagear.analysis.TemplateDashboardWidgetResManager;
|
||||
|
@ -1037,8 +1036,8 @@ public class DashboardController extends AbstractDataAnalysisController implemen
|
|||
|
||||
HtmlTplDashboard dashboard = dashboardWidget.render(renderContext, template);
|
||||
|
||||
SessionHtmlTplDashboardManager dashboardManager = getSessionHtmlTplDashboardManagerNotNull(request);
|
||||
dashboardManager.put(dashboard);
|
||||
SessionDashboardInfoManager dashboardInfoManager = getSessionDashboardInfoManagerNotNull(request);
|
||||
dashboardInfoManager.put(new DashboardInfo(dashboard));
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
@ -1061,8 +1060,8 @@ public class DashboardController extends AbstractDataAnalysisController implemen
|
|||
public ErrorMessageDashboardResult showData(HttpServletRequest request, HttpServletResponse response,
|
||||
org.springframework.ui.Model model, @RequestBody DashboardQueryForm form) throws Exception
|
||||
{
|
||||
WebContext webContext = createWebContext(request);
|
||||
DashboardResult dashboardResult = getDashboardResult(request, response, model, webContext, form);
|
||||
DashboardResult dashboardResult = getDashboardResult(request, form,
|
||||
this.htmlTplDashboardWidgetEntityService.getHtmlTplDashboardWidgetRenderer());
|
||||
|
||||
return new ErrorMessageDashboardResult(dashboardResult, true);
|
||||
}
|
||||
|
@ -1082,13 +1081,19 @@ public class DashboardController extends AbstractDataAnalysisController implemen
|
|||
@RequestParam(LOAD_CHART_PARAM_DASHBOARD_ID) String dashboardId,
|
||||
@RequestParam(LOAD_CHART_PARAM_CHART_WIDGET_ID) String[] chartWidgetIds) throws Throwable
|
||||
{
|
||||
SessionHtmlTplDashboardManager dashboardManager = getSessionHtmlTplDashboardManagerNotNull(request);
|
||||
HtmlTplDashboard dashboard = dashboardManager.get(dashboardId);
|
||||
User user = WebUtils.getUser(request, response);
|
||||
|
||||
if (dashboard == null)
|
||||
SessionDashboardInfoManager dashboardInfoManager = getSessionDashboardInfoManagerNotNull(request);
|
||||
DashboardInfo dashboardInfo = dashboardInfoManager.get(dashboardId);
|
||||
|
||||
if (dashboardInfo == null)
|
||||
throw new RecordNotFoundException();
|
||||
|
||||
HtmlTplDashboardWidgetEntity dashboardWidget = (HtmlTplDashboardWidgetEntity) dashboard.getWidget();
|
||||
HtmlTplDashboardWidgetEntity dashboardWidget = this.htmlTplDashboardWidgetEntityService
|
||||
.getHtmlTplDashboardWidget(user, dashboardInfo.getDashboardWidgetId());
|
||||
|
||||
if (dashboardWidget == null)
|
||||
throw new RecordNotFoundException();
|
||||
|
||||
// 确保看板创建用户对看板模板内定义的图表有权限
|
||||
ChartWidgetSourceContext.set(new ChartWidgetSourceContext(dashboardWidget.getCreateUser()));
|
||||
|
@ -1099,9 +1104,7 @@ public class DashboardController extends AbstractDataAnalysisController implemen
|
|||
try
|
||||
{
|
||||
for (int i = 0; i < chartWidgetIds.length; i++)
|
||||
{
|
||||
chartWidgets[i] = dashboardWidgetRenderer.getHtmlChartWidget(chartWidgetIds[i]);
|
||||
}
|
||||
|
||||
// 不缓存
|
||||
response.setContentType(CONTENT_TYPE_JSON);
|
||||
|
@ -1109,14 +1112,11 @@ public class DashboardController extends AbstractDataAnalysisController implemen
|
|||
|
||||
HtmlChart[] charts = this.htmlChartWidgetJsonWriter.write(out, chartWidgets);
|
||||
|
||||
synchronized (dashboard)
|
||||
{
|
||||
List<Chart> dashboardCharts = dashboard.getCharts();
|
||||
List<Chart> newCharts = (dashboardCharts == null || dashboardCharts.isEmpty() ? new ArrayList<>()
|
||||
: new ArrayList<>(dashboardCharts));
|
||||
newCharts.addAll(Arrays.asList(charts));
|
||||
dashboard.setCharts(newCharts);
|
||||
}
|
||||
Map<String, String> chartIdToChartWidgetIds = new HashMap<String, String>();
|
||||
for (int i = 0; i < chartWidgetIds.length; i++)
|
||||
chartIdToChartWidgetIds.put(charts[i].getId(), chartWidgetIds[i]);
|
||||
|
||||
dashboardInfo.putChartWidgetIds(chartIdToChartWidgetIds);
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
|
|
@ -9,6 +9,7 @@ package org.datagear.web.controller;
|
|||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashSet;
|
||||
|
@ -219,15 +220,43 @@ public class UserController extends AbstractController
|
|||
return "/user/user_form";
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/delete", produces = CONTENT_TYPE_JSON)
|
||||
@ResponseBody
|
||||
public ResponseEntity<OperationMessage> delete(HttpServletRequest request, HttpServletResponse response,
|
||||
@RequestBody String[] ids)
|
||||
@RequestMapping("/delete")
|
||||
public String delete(HttpServletRequest request, HttpServletResponse response, org.springframework.ui.Model model,
|
||||
@RequestParam("id") String[] ids)
|
||||
{
|
||||
this.userService.deleteByIds(ids);
|
||||
if (isEmpty(ids))
|
||||
throw new IllegalInputException();
|
||||
|
||||
this.schemaService.deleteByUserId(ids);
|
||||
// TODO 应该删除所有其他用户创建的数据
|
||||
List<User> users = this.userService.getByIdsNoPassword(ids, true);
|
||||
|
||||
model.addAttribute("deleteUsers", toWriteJsonTemplateModel(users));
|
||||
model.addAttribute(KEY_TITLE_MESSAGE_KEY, "user.deleteUser");
|
||||
model.addAttribute(KEY_FORM_ACTION, "deleteDo");
|
||||
|
||||
return "/user/user_delete";
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/deleteDo", produces = CONTENT_TYPE_JSON)
|
||||
@ResponseBody
|
||||
public ResponseEntity<OperationMessage> deleteDo(HttpServletRequest request, HttpServletResponse response,
|
||||
@RequestBody DeleteUserForm form)
|
||||
{
|
||||
if (isEmpty(form.getIds()) || isEmpty(form.getMigrateToId()))
|
||||
throw new IllegalInputException();
|
||||
|
||||
if (Arrays.asList(form.getIds()).contains(form.getMigrateToId()))
|
||||
throw new IllegalInputException();
|
||||
|
||||
if (User.containsAdminUser(form.getIds()))
|
||||
return buildOperationMessageFailResponseEntity(request, HttpStatus.BAD_REQUEST,
|
||||
buildMessageCode("deleteAdminUserDenied"));
|
||||
|
||||
User user = this.userService.getById(form.getMigrateToId());
|
||||
|
||||
if (user == null)
|
||||
throw new IllegalInputException();
|
||||
|
||||
this.userService.deleteByIds(form.getIds(), form.getMigrateToId());
|
||||
|
||||
return buildOperationMessageDeleteSuccessResponseEntity(request);
|
||||
}
|
||||
|
@ -368,4 +397,40 @@ public class UserController extends AbstractController
|
|||
this.confirmPassword = confirmPassword;
|
||||
}
|
||||
}
|
||||
|
||||
public static class DeleteUserForm implements Serializable
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** 要删除的用户ID */
|
||||
private String[] ids;
|
||||
|
||||
/** 数据迁移的目标用户ID */
|
||||
private String migrateToId;
|
||||
|
||||
public DeleteUserForm()
|
||||
{
|
||||
super();
|
||||
}
|
||||
|
||||
public String[] getIds()
|
||||
{
|
||||
return ids;
|
||||
}
|
||||
|
||||
public void setIds(String[] ids)
|
||||
{
|
||||
this.ids = ids;
|
||||
}
|
||||
|
||||
public String getMigrateToId()
|
||||
{
|
||||
return migrateToId;
|
||||
}
|
||||
|
||||
public void setMigrateToId(String migrateToId)
|
||||
{
|
||||
this.migrateToId = migrateToId;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,7 +50,7 @@ public class AuthenticationSuccessHandlerImpl implements AuthenticationSuccessHa
|
|||
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
|
||||
Authentication authentication) throws IOException, ServletException
|
||||
{
|
||||
mergeAnonymousUserEntities(request, response, authentication);
|
||||
migrateAnonymousUserData(request, response, authentication);
|
||||
|
||||
String redirectPath = WebUtils.getContextPath(request);
|
||||
|
||||
|
@ -68,7 +68,7 @@ public class AuthenticationSuccessHandlerImpl implements AuthenticationSuccessHa
|
|||
* @param response
|
||||
* @param loginUser
|
||||
*/
|
||||
protected void mergeAnonymousUserEntities(HttpServletRequest request, HttpServletResponse response,
|
||||
protected void migrateAnonymousUserData(HttpServletRequest request, HttpServletResponse response,
|
||||
Authentication authentication)
|
||||
{
|
||||
User user = WebUtils.getUser(authentication);
|
||||
|
|
|
@ -4,6 +4,10 @@
|
|||
#当系统作为war包部署至Servlet容器时将加载这里配置项
|
||||
#-----------------------------------------
|
||||
|
||||
#清理临时目录
|
||||
#执行清理时间间隔
|
||||
cleanTempDirectory.interval=0 0 1 * * ?
|
||||
|
||||
#日志级别
|
||||
#ERROR, WARN, INFO, DEBUG, TRACE
|
||||
logging.level.org.datagear=INFO
|
||||
|
|
|
@ -59,8 +59,8 @@ defaultRole.anonymous=ROLE_DATA_ADMIN
|
|||
#清理临时目录
|
||||
#可删除的过期文件分钟数
|
||||
cleanTempDirectory.expiredMinutes=1440
|
||||
#执行清理间隔
|
||||
cleanTempDirectory.interval=0 0 1 * * ?
|
||||
#执行清理时间间隔
|
||||
cleanTempDirectory.interval=0 0/10 * * * ?
|
||||
|
||||
#数据库
|
||||
datasource.driverClassName=org.apache.derby.jdbc.EmbeddedDriver
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -515,3 +515,9 @@ DataGear版本更新日志
|
|||
改进:看板编辑页面插入图表对话框改为悬浮面板,便于多次插入图表操作;
|
||||
改进:登录页、注册页、重置密码页添加右上角系统菜单;
|
||||
改进:程序发布包配置文件中添加DataGearWorkspace配置项模板;
|
||||
|
||||
|
||||
-----------------------------------------
|
||||
--v2.9.0
|
||||
-----------------------------------------
|
||||
|
||||
|
|
|
@ -377,6 +377,7 @@ user.viewUser=查看用户
|
|||
user.manageUser=管理用户
|
||||
user.selectUser=选择用户
|
||||
user.personalSet=个人设置
|
||||
user.deleteUser=删除用户
|
||||
user.id=ID
|
||||
user.name=用户名
|
||||
user.password=密码
|
||||
|
@ -387,9 +388,12 @@ user.createTime=创建日期
|
|||
user.roles=角色
|
||||
user.confirmPassword=确认密码
|
||||
user.validation.confirmPasswordError=与[密码]项不一致
|
||||
user.validation.migrateToUserIdIllegal=不能选择待删除的用户
|
||||
user.confirmDelete=确定删除选中的用户吗?用户创建的数据源也会被删除
|
||||
user.deleteAdminUserDenied=管理员账号不允许删除
|
||||
user.userNameExists=用户[{0}]已存在
|
||||
user.migrateDataToUser=数据迁移至
|
||||
user.migrateDataToUser.desc=将待删除用户的所有数据迁移至此用户
|
||||
|
||||
#about
|
||||
about.about=关于
|
||||
|
|
|
@ -377,6 +377,7 @@ user.viewUser=View user
|
|||
user.manageUser=Manage user
|
||||
user.selectUser=Select user
|
||||
user.personalSet=Personal set
|
||||
user.deleteUser=Delete user
|
||||
user.id=ID
|
||||
user.name=User name
|
||||
user.password=Password
|
||||
|
@ -387,9 +388,12 @@ user.createTime=Create time
|
|||
user.roles=Roles
|
||||
user.confirmPassword=Confirm password
|
||||
user.validation.confirmPasswordError=Must be the same with [Password]
|
||||
user.validation.migrateToUserIdIllegal=Must select user out of deleting list
|
||||
user.confirmDelete=Confirm delete selected user? All data related will be deleted also
|
||||
user.deleteAdminUserDenied=Administrator user can not be deleted
|
||||
user.userNameExists=User [{0}] already exists
|
||||
user.migrateDataToUser=Migrate data to
|
||||
user.migrateDataToUser.desc=Migrate their data to this user
|
||||
|
||||
#about
|
||||
about.about=About
|
||||
|
|
|
@ -109,22 +109,57 @@
|
|||
.dg-chart-label{
|
||||
position: relative;
|
||||
}
|
||||
.dg-chart-label .dg-chart-label-wrapper{
|
||||
}
|
||||
.dg-chart-label .dg-chart-label-wrapper .dg-chart-label-item .label-name{
|
||||
.dg-chart-label .dg-chart-label-item .label-name{
|
||||
text-align: center;
|
||||
}
|
||||
.dg-chart-label .dg-chart-label-wrapper .dg-chart-label-item .label-value{
|
||||
.dg-chart-label .dg-chart-label-item .label-value{
|
||||
text-align: center;
|
||||
font-size: 1.5em;
|
||||
font-weight: bold;
|
||||
}
|
||||
.dg-chart-label .dg-chart-label-wrapper.dg-chart-label-inline,
|
||||
.dg-chart-label .dg-chart-label-wrapper.dg-chart-label-inline .dg-chart-label-item,
|
||||
.dg-chart-label .dg-chart-label-wrapper.dg-chart-label-inline .dg-chart-label-item .label-name,
|
||||
.dg-chart-label .dg-chart-label-wrapper.dg-chart-label-inline .dg-chart-label-item .label-value{
|
||||
.dg-chart-label.dg-chart-label-inline .dg-chart-label-item,
|
||||
.dg-chart-label.dg-chart-label-inline .dg-chart-label-item .label-name,
|
||||
.dg-chart-label.dg-chart-label-inline .dg-chart-label-item .label-value{
|
||||
display: inline-block;
|
||||
}
|
||||
.dg-chart-label.dg-chart-label-flex{
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
}
|
||||
.dg-chart-label.dg-chart-label-flex.dg-chart-label-flex-around{
|
||||
justify-content: space-around;
|
||||
}
|
||||
.dg-chart-label.dg-chart-label-flex.dg-chart-label-flex-start{
|
||||
justify-content: flex-start;
|
||||
}
|
||||
.dg-chart-label.dg-chart-label-flex.dg-chart-label-flex-end{
|
||||
justify-content: flex-end;
|
||||
}
|
||||
.dg-chart-label.dg-chart-label-flex.dg-chart-label-flex-center{
|
||||
justify-content: center;
|
||||
}
|
||||
.dg-chart-label.dg-chart-label-flex.dg-chart-label-flex-between{
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
/*下拉框图表*/
|
||||
.dg-chart-select{}
|
||||
.dg-chart-select.dg-chart-select-fill{
|
||||
position: relative;
|
||||
}
|
||||
.dg-chart-select.dg-chart-select-fill .dg-chart-select-select{
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
-webkit-box-sizing: border-box;
|
||||
}
|
||||
|
||||
/*数据集参数值表单*/
|
||||
.dg-dspv-form{}
|
||||
|
|
|
@ -1415,6 +1415,9 @@ table.dataTable tbody tr td select{
|
|||
.page-form-user .selectUserRoleBtn{
|
||||
vertical-align: top;
|
||||
}
|
||||
.page-form-user-delete .delete-users{
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
/*驱动信息管理表单页*/
|
||||
.page-form-driverEntity{
|
||||
|
@ -2610,6 +2613,7 @@ table.dataTable tbody tr td select{
|
|||
box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
-webkit-box-sizing: border-box;
|
||||
resize: none;
|
||||
}
|
||||
.page-form-dataSet .workspace .workspace-operation-wrapper .preview-result-table-wrapper .result-data-max-count{
|
||||
float: left;
|
||||
|
@ -2625,6 +2629,23 @@ table.dataTable tbody tr td select{
|
|||
width: 100%;
|
||||
font-size: 0.8em;
|
||||
}
|
||||
.page-form-dataSet .workspace .workspace-operation-wrapper .preview-result-table-wrapper .preview-error-info{
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
display: none;
|
||||
}
|
||||
.page-form-dataSet .workspace .workspace-operation-wrapper .preview-result-table-wrapper .preview-error-info textarea{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin: 0 0;
|
||||
box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
-webkit-box-sizing: border-box;
|
||||
resize: none;
|
||||
}
|
||||
.page-form-dataSet .workspace .workspace-operation-wrapper .input-in-table{
|
||||
width: 90%!important;
|
||||
}
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
注意:
|
||||
|
||||
项目使用的是有改动的echarts.js(参考第5883行),而非echarts.min.js,因为官网发布版对与关系地图支持有BUG。
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
45
datagear-web/src/main/resources/org/datagear/web/static/lib/echarts-5.2.0/echarts.min.js
vendored
Normal file
45
datagear-web/src/main/resources/org/datagear/web/static/lib/echarts-5.2.0/echarts.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
|
@ -193,13 +193,19 @@
|
|||
chartFactory.CHART_EVENT_CHART_TYPE_HTML = "html";
|
||||
|
||||
/**内置名字标识片段*/
|
||||
chartFactory.BUILT_IN_NAME_PART = "datagear";
|
||||
chartFactory._BUILT_IN_NAME_PART = "datagear";
|
||||
|
||||
/**内置名字标识片段*/
|
||||
chartFactory.BUILT_IN_NAME_UNDERSCORE_PREFIX = "_" + chartFactory.BUILT_IN_NAME_PART;
|
||||
chartFactory._BUILT_IN_NAME_UNDERSCORE_PREFIX = "_" + chartFactory._BUILT_IN_NAME_PART;
|
||||
|
||||
/**数据对象的原始信息属性名*/
|
||||
chartFactory.DATA_ORIGINAL_INFO_PROP_NAME = chartFactory.BUILT_IN_NAME_UNDERSCORE_PREFIX + "OriginalInfo";
|
||||
chartFactory._DATA_ORIGINAL_INFO_PROP_NAME = chartFactory._BUILT_IN_NAME_UNDERSCORE_PREFIX + "OriginalInfo";
|
||||
|
||||
/**图表主题的CSS信息属性名*/
|
||||
chartFactory._KEY_THEME_STYLE_SHEET_INFO = chartFactory._BUILT_IN_NAME_UNDERSCORE_PREFIX + "StyleSheetInfo";
|
||||
|
||||
/** 关键字:注册得ECharts主题名 */
|
||||
chartFactory._KEY_REGISTERED_ECHARTS_THEME_NAME = chartFactory._BUILT_IN_NAME_UNDERSCORE_PREFIX + "RegisteredEchartsThemeName";
|
||||
|
||||
/**
|
||||
* 图表使用的渲染上下文属性名。
|
||||
|
@ -315,10 +321,10 @@
|
|||
if(theme.color && theme.actualBackgroundColor)
|
||||
{
|
||||
if(!theme.legendColor)
|
||||
theme.legendColor = chartFactory.getGradualColor(theme, 0.8);
|
||||
theme.legendColor = chartFactory.gradualColor(theme, 0.8);
|
||||
|
||||
if(!theme.borderColor)
|
||||
theme.borderColor = chartFactory.getGradualColor(theme, 0.3);
|
||||
theme.borderColor = chartFactory.gradualColor(theme, 0.3);
|
||||
|
||||
if(!theme.tooltipTheme)
|
||||
{
|
||||
|
@ -326,9 +332,9 @@
|
|||
{
|
||||
name: "tooltipTheme",
|
||||
color: theme.actualBackgroundColor,
|
||||
backgroundColor: chartFactory.getGradualColor(theme, 0.7),
|
||||
actualBackgroundColor: chartFactory.getGradualColor(theme, 0.7),
|
||||
borderColor: chartFactory.getGradualColor(theme, 0.9),
|
||||
backgroundColor: chartFactory.gradualColor(theme, 0.7),
|
||||
actualBackgroundColor: chartFactory.gradualColor(theme, 0.7),
|
||||
borderColor: chartFactory.gradualColor(theme, 0.9),
|
||||
borderWidth: 1,
|
||||
gradient: theme.gradient
|
||||
};
|
||||
|
@ -342,9 +348,9 @@
|
|||
{
|
||||
name: "highlightTheme",
|
||||
color: theme.actualBackgroundColor,
|
||||
backgroundColor: chartFactory.getGradualColor(theme, 0.8),
|
||||
actualBackgroundColor: chartFactory.getGradualColor(theme, 0.8),
|
||||
borderColor: chartFactory.getGradualColor(theme, 1),
|
||||
backgroundColor: chartFactory.gradualColor(theme, 0.8),
|
||||
actualBackgroundColor: chartFactory.gradualColor(theme, 0.8),
|
||||
borderColor: chartFactory.gradualColor(theme, 1),
|
||||
borderWidth: 1,
|
||||
gradient: theme.gradient
|
||||
};
|
||||
|
@ -387,21 +393,6 @@
|
|||
delete chart.resultDataFormat;
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取/设置图表的内置扩展属性值。
|
||||
* chart.extValue()是允许用户级使用的,此函数应用于内置设置/获取操作,可避免属性名冲突。
|
||||
*
|
||||
* @param chart 图表对象
|
||||
* @param name 扩展属性名
|
||||
* @param value 可选,要设置的扩展属性值,不设置则执行获取操作
|
||||
*/
|
||||
chartFactory.extValueBuiltin = function(chart, name, value)
|
||||
{
|
||||
name = chartFactory.BUILT_IN_NAME_UNDERSCORE_PREFIX+"_" + name;
|
||||
|
||||
return chart.extValue(name, value);
|
||||
};
|
||||
|
||||
//----------------------------------------
|
||||
// chartBase start
|
||||
//----------------------------------------
|
||||
|
@ -951,8 +942,10 @@
|
|||
if(chartFactory.renderedChart($element) != null)
|
||||
throw new Error("Chart element '#"+this.elementId+"' has been rendered");
|
||||
|
||||
this._createChartEleThemeCssIfNon();
|
||||
|
||||
$element.addClass(this.themeStyleName());
|
||||
$element.data(chartFactory._KEY_ELEMENT_RENDERED_CHART, this);
|
||||
chartFactory.setThemeStyle($element, this.theme());
|
||||
|
||||
this.statusRendering(true);
|
||||
|
||||
|
@ -968,6 +961,35 @@
|
|||
}
|
||||
};
|
||||
|
||||
chartBase._createChartEleThemeCssIfNon = function()
|
||||
{
|
||||
var thisChart = this;
|
||||
|
||||
this.themeStyleSheet(chartFactory.builtinPropName("ChartEle"), function()
|
||||
{
|
||||
var theme = thisChart.theme();
|
||||
|
||||
var css=
|
||||
{
|
||||
name: "",
|
||||
value:
|
||||
{
|
||||
"color": theme.color,
|
||||
"background-color": theme.backgroundColor,
|
||||
"border-color": theme.borderColor
|
||||
}
|
||||
};
|
||||
|
||||
if(theme.borderWidth)
|
||||
{
|
||||
css.value["border-width"] = theme.borderWidth;
|
||||
css.value["border-style"] = "solid";
|
||||
}
|
||||
|
||||
return css;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 调用底层图表渲染器的render函数,执行渲染。
|
||||
*/
|
||||
|
@ -1095,6 +1117,8 @@
|
|||
var $element = this.elementJquery();
|
||||
|
||||
this.statusDestroyed(true);
|
||||
|
||||
$element.removeClass(this.themeStyleName());
|
||||
$element.data(chartFactory._KEY_ELEMENT_RENDERED_CHART, null);
|
||||
|
||||
var renderer = this.renderer();
|
||||
|
@ -2391,7 +2415,7 @@
|
|||
*/
|
||||
chartBase._isEchartsInstance = function(obj)
|
||||
{
|
||||
return (obj && obj.constructor && obj.constructor.name && /ECharts/i.test(obj.constructor.name));
|
||||
return (obj && obj.setOption && obj.isDisposed && obj.dispose && obj.off);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -2404,21 +2428,16 @@
|
|||
//从ChartTheme构建ECharts主题
|
||||
if(!themeName)
|
||||
{
|
||||
var chartTheme = this.theme();
|
||||
var theme = this.theme();
|
||||
themeName = theme[chartFactory._KEY_REGISTERED_ECHARTS_THEME_NAME];
|
||||
|
||||
if(!chartTheme._registeredEchartsThemeName)
|
||||
if(!themeName)
|
||||
{
|
||||
var seq = (chartFactory._REGISTERED_ECHARTS_THEME_NAME_SEQ != null ?
|
||||
chartFactory._REGISTERED_ECHARTS_THEME_NAME_SEQ : 0);
|
||||
chartFactory._REGISTERED_ECHARTS_THEME_NAME_SEQ = seq + 1;
|
||||
themeName = (theme[chartFactory._KEY_REGISTERED_ECHARTS_THEME_NAME] = chartFactory.nextElementId());
|
||||
|
||||
chartTheme._registeredEchartsThemeName = chartFactory.BUILT_IN_NAME_UNDERSCORE_PREFIX + "EChartsThemeByChartTheme" + seq;
|
||||
|
||||
var echartsTheme = chartFactory.buildEchartsTheme(chartTheme);
|
||||
echarts.registerTheme(chartTheme._registeredEchartsThemeName, echartsTheme);
|
||||
var echartsTheme = chartFactory.buildEchartsTheme(theme);
|
||||
echarts.registerTheme(themeName, echartsTheme);
|
||||
}
|
||||
|
||||
themeName = chartTheme._registeredEchartsThemeName;
|
||||
}
|
||||
|
||||
return themeName;
|
||||
|
@ -2784,7 +2803,7 @@
|
|||
resultDataIndex = undefined;
|
||||
}
|
||||
|
||||
var pname = chartFactory.DATA_ORIGINAL_INFO_PROP_NAME;
|
||||
var pname = chartFactory._DATA_ORIGINAL_INFO_PROP_NAME;
|
||||
|
||||
var isArray = $.isArray(data);
|
||||
|
||||
|
@ -2968,7 +2987,7 @@
|
|||
}
|
||||
theme = (theme == null ? this.theme() : theme);
|
||||
|
||||
return chartFactory.getGradualColor(theme, factor);
|
||||
return chartFactory.gradualColor(theme, factor);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -2998,6 +3017,50 @@
|
|||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取图表主题对应的CSS类名。
|
||||
* 图表在渲染前,会自动为图表元素添加这个CSS类。
|
||||
*
|
||||
* @returns CSS类名
|
||||
*/
|
||||
chartBase.themeStyleName = function()
|
||||
{
|
||||
var theme = this.theme();
|
||||
|
||||
var pn = chartFactory.builtinPropName("ChartEleStyleName");
|
||||
var sn = theme[pn];
|
||||
|
||||
if(!sn)
|
||||
sn = (theme[pn] = chartFactory.nextElementId());
|
||||
|
||||
return sn;
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取/设置与此图表主题和指定名称关联的CSS样式表。
|
||||
* 设置的CSS样式都会添加chartBase.themeStyleName()函数返回的类名选择器前缀,因此只会影响使用了相同主题的图表。
|
||||
* 同一图表主题和名称的CSS样式表,通常仅需创建一次,因此,此函数的建议使用方式如下:
|
||||
* chart.themeStyleSheet("...", function(){ return ...; });
|
||||
*
|
||||
* @param name 名称
|
||||
* @param css 可选,参考chartFactory.themeStyleSheet()的css参数
|
||||
* @param force 可选,参考chartFactory.themeStyleSheet()的force参数
|
||||
*
|
||||
* @returns 样式表<style>元素的ID,没有设置过则返回undefined
|
||||
*/
|
||||
chartBase.themeStyleSheet = function(name, css, force)
|
||||
{
|
||||
var theme = this.theme();
|
||||
|
||||
if(arguments.length == 1)
|
||||
return chartFactory.themeStyleSheet(theme, name);
|
||||
else
|
||||
{
|
||||
var cssNamePrefix = "." + this.themeStyleName();
|
||||
return chartFactory.themeStyleSheet(theme, name, css, cssNamePrefix, force);
|
||||
}
|
||||
};
|
||||
|
||||
//-------------
|
||||
// < 已弃用函数 start
|
||||
//-------------
|
||||
|
@ -3199,6 +3262,128 @@
|
|||
// chartBase end
|
||||
//----------------------------------------
|
||||
|
||||
/**
|
||||
* 获取/设置与指定主题和名称关联的CSS样式表。
|
||||
* 同一主题和名称的CSS样式表,通常仅需创建一次,因此,此函数的建议使用方式如下:
|
||||
* chartFactory.themeStyleSheet({ ... }, "...", function(){ return ...; }, "...");
|
||||
*
|
||||
* @param theme 主题对象,格式为:{ ... }
|
||||
* @param name 名称
|
||||
* @param css 可选,要设置的CSS,格式为:
|
||||
* function(){ return CSS样式表对象、[ CSS样式表对象, ... ] }
|
||||
* 或者
|
||||
* CSS样式表对象
|
||||
* 或者
|
||||
* [ CSS样式表对象, ... ]
|
||||
* 其中,CSS样式表对象格式为:
|
||||
* {
|
||||
* //CSS选择器,例如:" .success"、".success"、" .error"、[ ".success", " .error" ]
|
||||
* name: "..."、["...", ...],
|
||||
* //CSS属性对象、CSS属性字符串,例如:
|
||||
* //{ 'color': 'red', 'background-color': 'blue' }、
|
||||
* //"color:red;background-color:blue;"
|
||||
* value: { CSS属性名 : CSS属性值, ... }、"..."
|
||||
* }
|
||||
* @param cssNamePrefix 可选,当指定了css时,设置统一得CSS选择器前缀
|
||||
* @param force 可选,当指定了css时,是否强制执行设置,true 强制设置;false 只有name对应的样式表不存在时才设置,默认值为:false
|
||||
*
|
||||
* @returns 样式表<style>元素的ID,没有设置过则返回undefined
|
||||
*/
|
||||
chartFactory.themeStyleSheet = function(theme, name, css, cssNamePrefix, force)
|
||||
{
|
||||
//(theme, name, css, true)、(theme, name, css, false)
|
||||
if(force === undefined && (cssNamePrefix === true || cssNamePrefix === false))
|
||||
{
|
||||
force = cssNamePrefix;
|
||||
cssNamePrefix = undefined;
|
||||
}
|
||||
|
||||
var infoMap = theme[chartFactory._KEY_THEME_STYLE_SHEET_INFO];
|
||||
if(infoMap == null)
|
||||
infoMap = (theme[chartFactory._KEY_THEME_STYLE_SHEET_INFO] = {});
|
||||
|
||||
var styleId = infoMap[name];
|
||||
|
||||
if(css === undefined)
|
||||
return styleId;
|
||||
|
||||
if(styleId && (force != true))
|
||||
return styleId;
|
||||
|
||||
var cssText = "";
|
||||
|
||||
if($.isFunction(css))
|
||||
css = css();
|
||||
|
||||
if(!$.isArray(css))
|
||||
css = [ css ];
|
||||
|
||||
for(var i=0; i<css.length; i++)
|
||||
{
|
||||
var cssName = css[i].name;
|
||||
var cssValue = css[i].value;
|
||||
|
||||
if(cssName == null)
|
||||
continue;
|
||||
|
||||
if(!$.isArray(cssName))
|
||||
cssName = [ cssName ];
|
||||
|
||||
for(var j=0; j<cssName.length; j++)
|
||||
{
|
||||
cssText += (cssNamePrefix ? cssNamePrefix + cssName[j] : cssName[j]);
|
||||
|
||||
if(j < (cssName.length - 1))
|
||||
cssText += ",\n";
|
||||
}
|
||||
|
||||
cssText += "{\n";
|
||||
|
||||
if(cssValue)
|
||||
{
|
||||
if(typeof(cssValue) == "string")
|
||||
cssText += cssValue;
|
||||
else
|
||||
{
|
||||
for(var p in cssValue)
|
||||
cssText += p + ":" + cssValue[p]+";\n";
|
||||
}
|
||||
}
|
||||
|
||||
cssText += "}\n";
|
||||
}
|
||||
|
||||
if(!styleId)
|
||||
styleId = (infoMap[name] = chartFactory.nextElementId());
|
||||
|
||||
chartFactory.styleSheetText(styleId, cssText);
|
||||
|
||||
return styleId;
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取内置属性名(添加内置前缀)。
|
||||
* 内置属性名以'_'开头。
|
||||
*/
|
||||
chartFactory.builtinPropName = function(name)
|
||||
{
|
||||
return chartFactory._BUILT_IN_NAME_UNDERSCORE_PREFIX + name;
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取/设置图表的内置扩展属性值。
|
||||
* chart.extValue()是允许用户级使用的,此函数应用于内置设置/获取操作,可避免属性名冲突。
|
||||
*
|
||||
* @param chart 图表对象
|
||||
* @param name 扩展属性名
|
||||
* @param value 可选,要设置的扩展属性值,不设置则执行获取操作
|
||||
*/
|
||||
chartFactory.extValueBuiltin = function(chart, name, value)
|
||||
{
|
||||
name = chartFactory.builtinPropName(name);
|
||||
return chart.extValue(name, value);
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取/设置渲染上下文的属性值。
|
||||
*
|
||||
|
@ -3271,7 +3456,7 @@
|
|||
};
|
||||
|
||||
/** HTML元素上已渲染的图表对象KEY */
|
||||
chartFactory._KEY_ELEMENT_RENDERED_CHART = chartFactory.BUILT_IN_NAME_UNDERSCORE_PREFIX + "_renderedChart";
|
||||
chartFactory._KEY_ELEMENT_RENDERED_CHART = chartFactory._BUILT_IN_NAME_UNDERSCORE_PREFIX + "RenderedChart";
|
||||
|
||||
/**
|
||||
* 获取当前在指定HTML元素上渲染的图表对象,返回null表示元素上并未渲染图表。
|
||||
|
@ -3287,7 +3472,7 @@
|
|||
};
|
||||
|
||||
/** 生成元素ID用的前缀 */
|
||||
chartFactory._ELEMENT_ID_PREFIX = chartFactory.BUILT_IN_NAME_PART + new Number(new Date().getTime()).toString(16);
|
||||
chartFactory._ELEMENT_ID_PREFIX = chartFactory._BUILT_IN_NAME_PART + new Number(new Date().getTime()).toString(16);
|
||||
|
||||
/**
|
||||
* 执行JS代码。
|
||||
|
@ -3311,96 +3496,6 @@
|
|||
return (re || defaultValue);
|
||||
};
|
||||
|
||||
/**
|
||||
* 解析JSON。
|
||||
* 如果参数不合法,将返回空对象:{}。
|
||||
*/
|
||||
chartFactory.parseJSONSilently = function(str)
|
||||
{
|
||||
if(!str)
|
||||
return {};
|
||||
|
||||
try
|
||||
{
|
||||
if(typeof($) != "undefined" && $.parseJSON)
|
||||
return $.parseJSON(str);
|
||||
else
|
||||
return JSON.parse(str);
|
||||
}
|
||||
catch(e)
|
||||
{
|
||||
chartFactory.logException(e);
|
||||
}
|
||||
|
||||
return {};
|
||||
};
|
||||
|
||||
/**
|
||||
* 将不符合JSON规范的字符串定义规范化:属性名添加双引号、或将属性名单引号替换为双引号。
|
||||
*/
|
||||
chartFactory.trimJSONString = function(str)
|
||||
{
|
||||
if(!str)
|
||||
return str;
|
||||
|
||||
//替换单引号为双引号
|
||||
var str1 = "";
|
||||
for(var i=0; i<str.length;i++)
|
||||
{
|
||||
var c = str.charAt(i);
|
||||
|
||||
if(c == '\\')
|
||||
{
|
||||
str1 += c;
|
||||
i = i+1;
|
||||
str1 += str.charAt(i);
|
||||
}
|
||||
else if(c == '\'')
|
||||
str1 += '"';
|
||||
else
|
||||
str1 += c;
|
||||
}
|
||||
|
||||
str = str1;
|
||||
|
||||
//属性名匹配表达式
|
||||
var reg = /([{,]\s*)([^\:\s]*)(\s*:)/g;
|
||||
|
||||
return str.replace(reg, function(token, prefix, name, suffix)
|
||||
{
|
||||
var len = name.length;
|
||||
|
||||
if(len > 1 && name.charAt(0) == '"' && name.charAt(len-1) == '"')
|
||||
return token;
|
||||
else if(len > 1 && name.charAt(0) == '\'' && name.charAt(len-1) == '\'')
|
||||
{
|
||||
name = '"' + name.substring(1, len-1) + '"';
|
||||
return prefix + name + suffix;
|
||||
}
|
||||
else
|
||||
return prefix + '"' + name + '"' + suffix;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 将对象转换为JSON字符串。
|
||||
*/
|
||||
chartFactory.toJSONString = function(obj)
|
||||
{
|
||||
return JSON.stringify(obj);
|
||||
};
|
||||
|
||||
/**
|
||||
* 为元素设置主题样式。
|
||||
*
|
||||
* @param element HTML元素、Jquery对象
|
||||
* @param theme 主题对象
|
||||
*/
|
||||
chartFactory.setThemeStyle = function(element, theme)
|
||||
{
|
||||
return this.setStyles(element, theme);
|
||||
};
|
||||
|
||||
/**
|
||||
* 为元素设置样式集。
|
||||
*
|
||||
|
@ -3457,21 +3552,24 @@
|
|||
return (element.attr("style") || "");
|
||||
};
|
||||
|
||||
chartFactory._KEY_GRADUAL_COLORS = chartFactory._BUILT_IN_NAME_UNDERSCORE_PREFIX + "GradualColors";
|
||||
|
||||
/**
|
||||
* 获取主题从背景色(actualBackgroundColor)到前景色(color)之间的渐变因子对应的颜色。
|
||||
* 这个颜色是实际背景色(actualBackgroundColor)与前景色(color)之间的某个颜色。
|
||||
*
|
||||
* @param theme
|
||||
* @param factor 可选,渐变因子,0-1之间的小数
|
||||
* @returns 与上述factor对应的颜色,当未设置factor时,将返回一个包含所有渐变颜色的数组
|
||||
* @param theme 主题对象,格式为:{ color: "...", actualBackgroundColor: "..." }
|
||||
* @param factor 可选,渐变因子,0-1之间的小数,其中0表示最接近实际背景色的颜色、1表示最接近前景色的颜色
|
||||
* @returns 与factor匹配的颜色字符串,格式类似:"#FFFFFF",如果未设置factor,将返回一个包含所有渐变颜色的数组
|
||||
*/
|
||||
chartFactory.getGradualColor = function(theme, factor)
|
||||
chartFactory.gradualColor = function(theme, factor)
|
||||
{
|
||||
var gcs = theme._gradualColors;
|
||||
var gcs = theme[chartFactory._KEY_GRADUAL_COLORS];
|
||||
|
||||
if(!gcs || gcs.length == 0)
|
||||
{
|
||||
gcs = this.evalGradualColors(theme.actualBackgroundColor, theme.color, (theme.gradient || 10));
|
||||
theme._gradualColors = gcs;
|
||||
theme[chartFactory._KEY_GRADUAL_COLORS] = gcs;
|
||||
}
|
||||
|
||||
if(factor == null)
|
||||
|
@ -3600,55 +3698,55 @@
|
|||
};
|
||||
|
||||
/**
|
||||
* 创建CSS样式表。
|
||||
*
|
||||
* @param id 样式表元素ID
|
||||
* @param cssText 样式文本
|
||||
* @param position 可选,插入位置:"first"、"last"、"beforeFirstScript"(第一个<script>节点之前)、DOM(插入其前面),默认值为:"last"
|
||||
* 设置指定ID的样式表css文本。
|
||||
* 如果样式表不存在,将会自动创建,且会插入<head>中的靠前位置,确保其css效果优先级低于用户定义的css。
|
||||
*
|
||||
* @param styleId 样式表元素ID
|
||||
* @param cssText css文本内容
|
||||
*/
|
||||
chartFactory.createStyleSheet = function(id, cssText, position)
|
||||
chartFactory.styleSheetText = function(styleId, cssText)
|
||||
{
|
||||
if(!position)
|
||||
position = "last";
|
||||
var $style = $("#" + styleId);
|
||||
|
||||
var head = (document.head || document.getElementsByTagName("head")[0]);
|
||||
var style = document.createElement("style");
|
||||
|
||||
var beforeNode = null;
|
||||
|
||||
if(position === "last")
|
||||
if($style.length > 0)
|
||||
{
|
||||
}
|
||||
else if(position === "first")
|
||||
{
|
||||
beforeNode = head.firstChild;
|
||||
}
|
||||
else if(position === "beforeFirstScript")
|
||||
{
|
||||
var childNodes = (head.childNodes || []);
|
||||
for(var i=0; i<childNodes.length; i++)
|
||||
{
|
||||
if((childNodes[i].tagName || "").toLowerCase() == "script")
|
||||
{
|
||||
beforeNode = childNodes[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
$style.text(cssText);
|
||||
return;
|
||||
}
|
||||
|
||||
if(beforeNode)
|
||||
head.insertBefore(style, beforeNode);
|
||||
else
|
||||
head.appendChild(style);
|
||||
|
||||
style.id = id;
|
||||
style.type = "text/css";
|
||||
|
||||
// 旧版IE
|
||||
if (style.styleSheet)
|
||||
style.styleSheet.cssText = cssText;
|
||||
else
|
||||
style.appendChild(document.createTextNode(cssText));
|
||||
$style = $("<style />").attr("id", styleId)
|
||||
.attr("dg-generated-style", "true").attr("type", "text/css").text(cssText);
|
||||
|
||||
var $head = $("head:first");
|
||||
|
||||
var $lastGenStyle = $("style[dg-generated-style]:last", $head);
|
||||
|
||||
//后插入的优先级应高于先插入的
|
||||
if($lastGenStyle.length > 0)
|
||||
{
|
||||
$lastGenStyle.after($style);
|
||||
return;
|
||||
}
|
||||
|
||||
var $lastImport = $("[dg-import-name]:last", $head);
|
||||
|
||||
//优先级应高于导入的资源
|
||||
if($lastImport.length > 0)
|
||||
{
|
||||
$lastImport.after($style);
|
||||
return;
|
||||
}
|
||||
|
||||
var $lastLink = $("link:last", $head);
|
||||
|
||||
//优先级应高于link的css
|
||||
if($lastLink.length > 0)
|
||||
{
|
||||
$lastLink.after($style);
|
||||
return;
|
||||
}
|
||||
|
||||
$head.prepend($style);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -3665,6 +3763,7 @@
|
|||
|
||||
/**
|
||||
* 生成一个新的页面元素ID。
|
||||
* 这个ID仅包含[a-z]、[A-Z]、[0-9],且以字母开头。
|
||||
*
|
||||
* @param prefix 可选,ID前缀
|
||||
*/
|
||||
|
@ -3751,13 +3850,13 @@
|
|||
*/
|
||||
chartFactory.buildEchartsTheme = function(chartTheme)
|
||||
{
|
||||
var axisColor = this.getGradualColor(chartTheme, 0.7);
|
||||
var axisScaleLineColor = this.getGradualColor(chartTheme, 0.35);
|
||||
var areaColor0 = this.getGradualColor(chartTheme, 0.15);
|
||||
var areaBorderColor0 = this.getGradualColor(chartTheme, 0.3);
|
||||
var areaColor1 = this.getGradualColor(chartTheme, 0.25);
|
||||
var areaBorderColor1 = this.getGradualColor(chartTheme, 0.5);
|
||||
var shadowColor = this.getGradualColor(chartTheme, 0.9);
|
||||
var axisColor = chartFactory.gradualColor(chartTheme, 0.7);
|
||||
var axisScaleLineColor = chartFactory.gradualColor(chartTheme, 0.35);
|
||||
var areaColor0 = chartFactory.gradualColor(chartTheme, 0.15);
|
||||
var areaBorderColor0 = chartFactory.gradualColor(chartTheme, 0.3);
|
||||
var areaColor1 = chartFactory.gradualColor(chartTheme, 0.25);
|
||||
var areaBorderColor1 = chartFactory.gradualColor(chartTheme, 0.5);
|
||||
var shadowColor = chartFactory.gradualColor(chartTheme, 0.9);
|
||||
|
||||
// < @deprecated 兼容1.8.1版本有ChartTheme.axisColor的结构
|
||||
if(chartTheme.axisColor)
|
||||
|
|
|
@ -115,7 +115,10 @@
|
|||
|
||||
//创建表单样式表
|
||||
if(options.chartTheme)
|
||||
chartSetting.setDataSetParamValueFormStyle($form, options.chartTheme);
|
||||
{
|
||||
var styleName = chartSetting.dataSetParamValueFormThemeStyle(options.chartTheme);
|
||||
$form.addClass(styleName);
|
||||
}
|
||||
|
||||
var $head = $(".dg-dspv-form-head", $form);
|
||||
var $content = $(".dg-dspv-form-content", $form);
|
||||
|
@ -237,64 +240,85 @@
|
|||
return formEle;
|
||||
};
|
||||
|
||||
chartSetting.setDataSetParamValueFormStyle = function($form, chartTheme)
|
||||
chartSetting.dataSetParamValueFormThemeStyle = function(chartTheme)
|
||||
{
|
||||
var styleClassName = chartTheme._dataSetParamValueFormStyleClassName;
|
||||
if(!styleClassName)
|
||||
var styleNameKey = chartFactory.builtinPropName("DataSetParamValueFormStyleName");
|
||||
var styleName = chartTheme[styleNameKey];
|
||||
|
||||
if(styleName)
|
||||
return styleName;
|
||||
|
||||
styleName = (chartTheme[styleNameKey] = chartFactory.nextElementId());
|
||||
|
||||
chartFactory.themeStyleSheet(chartTheme, chartFactory.builtinPropName("DataSetParamValueForm"), function()
|
||||
{
|
||||
styleClassName = chartFactory.nextElementId();
|
||||
chartTheme._dataSetParamValueFormStyleClassName = styleClassName;
|
||||
}
|
||||
var color = chartFactory.gradualColor(chartTheme, 1);
|
||||
var bgColor = chartFactory.gradualColor(chartTheme, 0);
|
||||
var borderColor = chartFactory.gradualColor(chartTheme, 0.5);
|
||||
|
||||
var cssPrefix = "." + styleName + ".dg-dspv-form";
|
||||
|
||||
var css =
|
||||
[
|
||||
{
|
||||
name: cssPrefix,
|
||||
value:
|
||||
{
|
||||
"color": color,
|
||||
"background-color": bgColor,
|
||||
"border-color": borderColor
|
||||
}
|
||||
},
|
||||
{
|
||||
name:
|
||||
[
|
||||
cssPrefix + " .dg-dspv-form-item-value input",
|
||||
cssPrefix + " .dg-dspv-form-item-value textarea",
|
||||
cssPrefix + " .dg-dspv-form-item-value select",
|
||||
cssPrefix + " .dg-dspv-form-item-value select option",
|
||||
cssPrefix + " .dg-dspv-form-item-value .input"
|
||||
],
|
||||
value:
|
||||
{
|
||||
"color": color,
|
||||
"background-color": bgColor,
|
||||
"border-color": borderColor
|
||||
}
|
||||
},
|
||||
{
|
||||
name:
|
||||
[
|
||||
cssPrefix + " button",
|
||||
cssPrefix + " input[type=button]",
|
||||
cssPrefix + " input[type=submit]",
|
||||
cssPrefix + " .button"
|
||||
],
|
||||
value:
|
||||
{
|
||||
"color": color,
|
||||
"background-color": chartFactory.gradualColor(chartTheme, 0.1),
|
||||
"border-color": borderColor
|
||||
}
|
||||
},
|
||||
{
|
||||
name:
|
||||
[
|
||||
cssPrefix + " button:hover",
|
||||
cssPrefix + " input[type=button]:hover",
|
||||
cssPrefix + " input[type=submit]:hover",
|
||||
cssPrefix + " .button:hover"
|
||||
],
|
||||
value:
|
||||
{
|
||||
"background-color": chartFactory.gradualColor(chartTheme, 0.3)
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
return css;
|
||||
});
|
||||
|
||||
$form.addClass(styleClassName);
|
||||
|
||||
var styleId = (chartTheme._dataSetParamValueFormStyleSheetId
|
||||
|| (chartTheme._dataSetParamValueFormStyleSheetId = chartFactory.nextElementId()));
|
||||
|
||||
if(chartFactory.isStyleSheetCreated(styleId))
|
||||
return false;
|
||||
|
||||
var qualifier = "." + styleClassName;
|
||||
|
||||
var color = chartFactory.getGradualColor(chartTheme, 1);
|
||||
var bgColor = chartFactory.getGradualColor(chartTheme, 0);
|
||||
var borderColor = chartFactory.getGradualColor(chartTheme, 0.5);
|
||||
var hoverColor = chartFactory.getGradualColor(chartTheme, 0.3);
|
||||
|
||||
var cssText =
|
||||
qualifier + ".dg-dspv-form{"
|
||||
+" color: "+color+";"
|
||||
+" background: "+bgColor+";"
|
||||
+" border-color: "+borderColor+";"
|
||||
+" }\n"
|
||||
+qualifier + ".dg-dspv-form .dg-dspv-form-item-value input,\n"
|
||||
+qualifier + ".dg-dspv-form .dg-dspv-form-item-value textarea,\n"
|
||||
+qualifier + ".dg-dspv-form .dg-dspv-form-item-value select,\n"
|
||||
+qualifier + ".dg-dspv-form .dg-dspv-form-item-value select option,\n"
|
||||
+qualifier + ".dg-dspv-form .dg-dspv-form-item-value .input{"
|
||||
+" color: "+color+";"
|
||||
+" background: "+bgColor+";"
|
||||
+" border-color: "+borderColor+";"
|
||||
+" }\n"
|
||||
+qualifier + ".dg-dspv-form button,\n"
|
||||
+qualifier + ".dg-dspv-form input[type=button],\n"
|
||||
+qualifier + ".dg-dspv-form input[type=submit],\n"
|
||||
+qualifier + ".dg-dspv-form .button{"
|
||||
+" color: "+color+";"
|
||||
+" background: "+chartFactory.getGradualColor(chartTheme, 0.1)+";"
|
||||
+" border-color: "+borderColor+";"
|
||||
+"}\n"
|
||||
+qualifier + ".dg-dspv-form button:hover,\n"
|
||||
+qualifier + ".dg-dspv-form input[type=button]:hover,\n"
|
||||
+qualifier + ".dg-dspv-form input[type=submit]:hover,\n"
|
||||
+qualifier + ".dg-dspv-form .button:hover{"
|
||||
+" background: "+chartFactory.getGradualColor(chartTheme, 0.3)+";"
|
||||
+" }\n"
|
||||
;
|
||||
|
||||
chartFactory.createStyleSheet(styleId, cssText, "beforeFirstScript");
|
||||
|
||||
return true;
|
||||
return styleName;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -657,6 +681,8 @@
|
|||
$input.attr("dg-validation-number", "true");
|
||||
};
|
||||
|
||||
chartSetting._DATETIME_PICKER_ROOT_ID = chartFactory._BUILT_IN_NAME_PART + "DatetimepickerRoot";
|
||||
|
||||
chartSetting.datetimepicker = function($input, datetimepickerOptions, chartTheme)
|
||||
{
|
||||
//在这里检查并重写,避免依赖加载顺序
|
||||
|
@ -668,22 +694,24 @@
|
|||
chartSetting._datetimepickerSetLocale = true;
|
||||
}
|
||||
|
||||
var $rootWrapper = $("#" + chartSetting._DATETIME_PICKER_ROOT_ID);
|
||||
if($rootWrapper.length < 1)
|
||||
$rootWrapper = $("<div />").attr("id", chartSetting._DATETIME_PICKER_ROOT_ID).appendTo(document.body);
|
||||
|
||||
var wrapperId = chartFactory.nextElementId();
|
||||
var $wrapper = $("<div />").attr("id", wrapperId).appendTo($rootWrapper);
|
||||
|
||||
if(chartTheme)
|
||||
{
|
||||
var containerId = (chartTheme._datetimepickerContainerId
|
||||
|| (chartTheme._datetimepickerContainerId = chartFactory.nextElementId()));
|
||||
var container = document.getElementById(containerId);
|
||||
if(!container)
|
||||
container = $("<div class='dg-dspv-datetimepicker-container' />").attr("id", containerId).appendTo(document.body);
|
||||
|
||||
chartSetting.datetimepickerSetStyle("#"+containerId, chartTheme);
|
||||
var styleName = chartSetting.datetimepickerThemeStyle(chartTheme);
|
||||
$wrapper.addClass(styleName);
|
||||
}
|
||||
|
||||
datetimepickerOptions = $.extend(
|
||||
{
|
||||
//inline应该为false,为true的话下面的datetimepickerSetStyle函数创建的样式将不起作用
|
||||
//inline应该为false,为true的话下面的datetimepickerThemeStyle函数创建的样式将不起作用
|
||||
inline: false,
|
||||
parentID: (chartTheme ? "#"+containerId : document.body),
|
||||
parentID: "#"+wrapperId,
|
||||
i18n: chartSetting.datetimepickerI18n
|
||||
},
|
||||
datetimepickerOptions);
|
||||
|
@ -694,7 +722,7 @@
|
|||
{
|
||||
//显示确定按钮,用于直接选中默认年份
|
||||
datetimepickerOptions.showApplyButton = true;
|
||||
datetimepickerOptions.onGenerate = function(currentValue,$input)
|
||||
datetimepickerOptions.onGenerate = function(currentValue, $input)
|
||||
{
|
||||
var yearPickerInited = $(this).attr("yearPickerInited");
|
||||
if(!yearPickerInited)
|
||||
|
@ -731,102 +759,165 @@
|
|||
};
|
||||
|
||||
/**
|
||||
* 创建与指定图表主题匹配的datetimepicker组件样式表。
|
||||
* 获取或创建与指定图表主题匹配的datetimepicker组件样式表,并返回CSS类名。
|
||||
*
|
||||
* @param parentSelector datetimepicker组件所在的父元素CSS选择器
|
||||
* @param chartTheme
|
||||
*/
|
||||
chartSetting.datetimepickerSetStyle = function(parentSelector, chartTheme)
|
||||
chartSetting.datetimepickerThemeStyle = function(chartTheme)
|
||||
{
|
||||
var styleId = (chartTheme._datetimepickerStyleSheetId
|
||||
|| (chartTheme._datetimepickerStyleSheetId = chartFactory.nextElementId()));
|
||||
var styleNameKey = chartFactory.builtinPropName("DatetimepickerStyleName");
|
||||
var styleName = chartTheme[styleNameKey];
|
||||
|
||||
if(chartFactory.isStyleSheetCreated(styleId))
|
||||
return false;
|
||||
if(styleName)
|
||||
return styleName;
|
||||
|
||||
var color = chartFactory.getGradualColor(chartTheme, 1);
|
||||
var bgColor = chartFactory.getGradualColor(chartTheme, 0);
|
||||
var borderColor = chartFactory.getGradualColor(chartTheme, 0.3);
|
||||
var shadowColor = chartFactory.getGradualColor(chartTheme, 0.9);
|
||||
var hoverColor = chartFactory.getGradualColor(chartTheme, 0.3);
|
||||
styleName = (chartTheme[styleNameKey] = chartFactory.nextElementId());
|
||||
|
||||
var cssText =
|
||||
//主体
|
||||
parentSelector + " .xdsoft_datetimepicker{"
|
||||
+" color: "+color+";"
|
||||
+" background: "+bgColor+";"
|
||||
+" border-color: "+borderColor+";"
|
||||
+" box-shadow: 0px 0px 6px "+shadowColor+";"
|
||||
+" -webkit-box-shadow: 0px 0px 6px "+shadowColor+";"
|
||||
+" }\n"
|
||||
//前景色
|
||||
+parentSelector + " .xdsoft_datetimepicker .xdsoft_calendar td,\n"
|
||||
+parentSelector + " .xdsoft_datetimepicker .xdsoft_calendar th{"
|
||||
+" color: "+color+";"
|
||||
+" }\n"
|
||||
//按钮
|
||||
+parentSelector + " .xdsoft_datetimepicker .xdsoft_label i,\n"
|
||||
+parentSelector + " .xdsoft_datetimepicker .xdsoft_next,\n"
|
||||
+parentSelector + " .xdsoft_datetimepicker .xdsoft_prev,\n"
|
||||
+parentSelector + " .xdsoft_datetimepicker .xdsoft_today_button{"
|
||||
+" color:"+color+";"
|
||||
+" }\n"
|
||||
//年、月
|
||||
+parentSelector + " .xdsoft_datetimepicker .xdsoft_label{"
|
||||
+" background: "+bgColor+";"
|
||||
+" }\n"
|
||||
//年、月下拉框
|
||||
+parentSelector + " .xdsoft_datetimepicker .xdsoft_label>.xdsoft_select{"
|
||||
+" color: "+color+";"
|
||||
+" background: "+bgColor+";"
|
||||
+" border-color: "+borderColor+";"
|
||||
+" box-shadow: 0px 0px 6px "+shadowColor+";"
|
||||
+" -webkit-box-shadow: 0px 0px 6px "+shadowColor+";"
|
||||
+" }\n"
|
||||
//时间框
|
||||
+parentSelector + " .xdsoft_datetimepicker .xdsoft_timepicker .xdsoft_time_box{"
|
||||
+" border-color: "+borderColor+";"
|
||||
+" }\n"
|
||||
//时间条目
|
||||
+parentSelector + " .xdsoft_datetimepicker .xdsoft_timepicker .xdsoft_time_box>div>div{"
|
||||
+" color: "+color+";"
|
||||
+" border-color: "+borderColor+";"
|
||||
+" }\n"
|
||||
//悬停
|
||||
+parentSelector + " .xdsoft_datetimepicker .xdsoft_calendar td:hover,\n"
|
||||
+parentSelector + " .xdsoft_datetimepicker .xdsoft_timepicker .xdsoft_time_box>div>div:hover,\n"
|
||||
+parentSelector + " .xdsoft_datetimepicker .xdsoft_label>.xdsoft_select>div>.xdsoft_option:hover{"
|
||||
+" color: "+color+" !important;"
|
||||
+" background: "+hoverColor+" !important;"
|
||||
+" }\n"
|
||||
//今天
|
||||
+parentSelector + " .xdsoft_datetimepicker .xdsoft_calendar td.xdsoft_today{"
|
||||
+" color: "+color+";"
|
||||
+" font-weight: bold;"
|
||||
+" }\n"
|
||||
//选中
|
||||
+parentSelector + " .xdsoft_datetimepicker .xdsoft_calendar td.xdsoft_default,\n"
|
||||
+parentSelector + " .xdsoft_datetimepicker .xdsoft_calendar td.xdsoft_current,\n"
|
||||
+parentSelector + " .xdsoft_datetimepicker .xdsoft_timepicker .xdsoft_time_box>div>div.xdsoft_current,\n"
|
||||
+parentSelector + " .xdsoft_datetimepicker .xdsoft_label>.xdsoft_select>div>.xdsoft_option.xdsoft_current{"
|
||||
+" color: "+chartTheme.highlightTheme.color+";"
|
||||
+" background: "+chartTheme.highlightTheme.backgroundColor+";"
|
||||
+" box-shadow: none;"
|
||||
+" -webkit-box-shadow: none;"
|
||||
+" }\n"
|
||||
+parentSelector + " .xdsoft_datetimepicker .xdsoft_save_selected.xdsoft_save_selected_year{"
|
||||
+" color: "+color+";"
|
||||
+" background: "+bgColor+";"
|
||||
+" border: 1px solid "+borderColor+" !important;"
|
||||
+" }\n"
|
||||
+parentSelector + " .xdsoft_datetimepicker .xdsoft_save_selected.xdsoft_save_selected_year:hover{"
|
||||
+" background: "+hoverColor+";"
|
||||
+" }\n"
|
||||
;
|
||||
chartFactory.themeStyleSheet(chartTheme, chartFactory.builtinPropName("Datetimepicker"), function()
|
||||
{
|
||||
var color = chartFactory.gradualColor(chartTheme, 1);
|
||||
var bgColor = chartFactory.gradualColor(chartTheme, 0);
|
||||
var borderColor = chartFactory.gradualColor(chartTheme, 0.3);
|
||||
var shadowColor = chartFactory.gradualColor(chartTheme, 0.9);
|
||||
var hoverColor = chartFactory.gradualColor(chartTheme, 0.3);
|
||||
|
||||
var cssPrefix = "." + styleName + " .xdsoft_datetimepicker";
|
||||
|
||||
var css =
|
||||
[
|
||||
//主体
|
||||
{
|
||||
name: cssPrefix,
|
||||
value:
|
||||
{
|
||||
"color": color,
|
||||
"background": bgColor,
|
||||
"border-color": borderColor,
|
||||
"box-shadow": "0px 0px 6px " + shadowColor,
|
||||
"-webkit-box-shadow": "0px 0px 6px " + shadowColor
|
||||
}
|
||||
},
|
||||
//前景色
|
||||
{
|
||||
name: [ cssPrefix + " .xdsoft_calendar td", cssPrefix + " .xdsoft_calendar th" ],
|
||||
value:
|
||||
{
|
||||
"color": color
|
||||
}
|
||||
},
|
||||
//按钮
|
||||
{
|
||||
name:
|
||||
[
|
||||
cssPrefix + " .xdsoft_label i",
|
||||
cssPrefix + " .xdsoft_next",
|
||||
cssPrefix + " .xdsoft_prev",
|
||||
cssPrefix + " .xdsoft_today_button"
|
||||
],
|
||||
value:
|
||||
{
|
||||
"color": color
|
||||
}
|
||||
},
|
||||
//年、月
|
||||
{
|
||||
name: cssPrefix + " .xdsoft_label",
|
||||
value:
|
||||
{
|
||||
"background": bgColor
|
||||
}
|
||||
},
|
||||
//年、月下拉框
|
||||
{
|
||||
name: cssPrefix + " .xdsoft_label>.xdsoft_select",
|
||||
value:
|
||||
{
|
||||
"color": color,
|
||||
"background": bgColor,
|
||||
"border-color": borderColor,
|
||||
"box-shadow": "0px 0px 6px " + shadowColor,
|
||||
"-webkit-box-shadow": "0px 0px 6px " + shadowColor
|
||||
}
|
||||
},
|
||||
//时间框
|
||||
{
|
||||
name: cssPrefix + " .xdsoft_timepicker .xdsoft_time_box",
|
||||
value:
|
||||
{
|
||||
"border-color": borderColor
|
||||
}
|
||||
},
|
||||
//时间条目
|
||||
{
|
||||
name: cssPrefix + " .xdsoft_timepicker .xdsoft_time_box>div>div",
|
||||
value:
|
||||
{
|
||||
"color": color,
|
||||
"border-color": borderColor
|
||||
}
|
||||
},
|
||||
//悬停
|
||||
{
|
||||
name:
|
||||
[
|
||||
cssPrefix + " .xdsoft_calendar td:hover",
|
||||
cssPrefix + " .xdsoft_timepicker .xdsoft_time_box>div>div:hover",
|
||||
cssPrefix + " .xdsoft_label>.xdsoft_select>div>.xdsoft_option:hover"
|
||||
],
|
||||
value:
|
||||
{
|
||||
"color": color + " !important",
|
||||
"background": hoverColor + " !important"
|
||||
}
|
||||
},
|
||||
//今天
|
||||
{
|
||||
name: cssPrefix + " .xdsoft_calendar td.xdsoft_today",
|
||||
value:
|
||||
{
|
||||
"color": color,
|
||||
"font-weight": "bold"
|
||||
}
|
||||
},
|
||||
//选中
|
||||
{
|
||||
name:
|
||||
[
|
||||
cssPrefix + " .xdsoft_calendar td.xdsoft_default",
|
||||
cssPrefix + " .xdsoft_calendar td.xdsoft_current",
|
||||
cssPrefix + " .xdsoft_timepicker .xdsoft_time_box>div>div.xdsoft_current",
|
||||
cssPrefix + " .xdsoft_label>.xdsoft_select>div>.xdsoft_option.xdsoft_current"
|
||||
],
|
||||
value:
|
||||
{
|
||||
"color": chartTheme.highlightTheme.color,
|
||||
"background": chartTheme.highlightTheme.backgroundColor,
|
||||
"box-shadow": "none",
|
||||
"-webkit-box-shadow": "none"
|
||||
}
|
||||
},
|
||||
{
|
||||
name: cssPrefix + " .xdsoft_save_selected.xdsoft_save_selected_year",
|
||||
value:
|
||||
{
|
||||
"color": color,
|
||||
"background": bgColor,
|
||||
"border": "1px solid "+borderColor+" !important"
|
||||
}
|
||||
},
|
||||
{
|
||||
name: cssPrefix + " .xdsoft_save_selected.xdsoft_save_selected_year:hover",
|
||||
value:
|
||||
{
|
||||
"background": hoverColor
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
return css;
|
||||
});
|
||||
|
||||
chartFactory.createStyleSheet(styleId, cssText, "beforeFirstScript");
|
||||
|
||||
return true;
|
||||
return styleName;
|
||||
};
|
||||
|
||||
chartSetting.evalDataSetParamInputPayload = function(dataSetParam, defaultValue)
|
||||
|
@ -1189,7 +1280,7 @@
|
|||
{
|
||||
$box = $("<div class='dg-chart-setting-box' />").appendTo($chart);
|
||||
|
||||
chartSetting.setChartSettingBoxStyle($box, chart.theme());
|
||||
chartSetting.setChartSettingBoxThemeStyle(chart, $box);
|
||||
|
||||
//参数
|
||||
if(!disableSetting.param && chart.hasParamDataSet())
|
||||
|
@ -1253,64 +1344,73 @@
|
|||
$(".dg-chart-setting-box", chart.elementJquery()).hide();
|
||||
};
|
||||
|
||||
chartSetting.setChartSettingBoxStyle = function($box, chartTheme)
|
||||
chartSetting.setChartSettingBoxThemeStyle = function(chart, $box)
|
||||
{
|
||||
var styleClassName = chartTheme._chartSettingBoxStyleClassName;
|
||||
if(!styleClassName)
|
||||
chart.themeStyleSheet(chartFactory.builtinPropName("ChartSettingBox"), function()
|
||||
{
|
||||
styleClassName = chartFactory.nextElementId();
|
||||
chartTheme._chartSettingBoxStyleClassName = styleClassName;
|
||||
}
|
||||
|
||||
$box.addClass(styleClassName);
|
||||
|
||||
var styleId = (chartTheme._chartSettingBoxStyleSheetId
|
||||
|| (chartTheme._chartSettingBoxStyleSheetId = chartFactory.nextElementId()));
|
||||
|
||||
if(chartFactory.isStyleSheetCreated(styleId))
|
||||
return false;
|
||||
|
||||
var qualifier = "." + styleClassName;
|
||||
|
||||
var color = chartFactory.getGradualColor(chartTheme, 1);
|
||||
var bgColor = chartFactory.getGradualColor(chartTheme, 0);
|
||||
var borderColor = chartFactory.getGradualColor(chartTheme, 0.5);
|
||||
var shadowColor = chartFactory.getGradualColor(chartTheme, 0.9);
|
||||
|
||||
var cssText =
|
||||
qualifier + ".dg-chart-setting-box .dg-chart-setting-button{"
|
||||
+" color: "+color+";"
|
||||
+" background: "+bgColor+";"
|
||||
+" border-color: "+borderColor+";"
|
||||
+"} \n"
|
||||
+qualifier + ".dg-chart-setting-box .dg-chart-setting-button:hover{"
|
||||
+" background: "+chartFactory.getGradualColor(chartTheme, 0.2)+";"
|
||||
+"} \n"
|
||||
+qualifier + ".dg-chart-setting-box .dg-chart-setting-panel{"
|
||||
+" color: "+color+";"
|
||||
+" background: "+bgColor+";"
|
||||
+" border-color: "+borderColor+";"
|
||||
+" box-shadow: 0px 0px 6px "+shadowColor+";"
|
||||
+" -webkit-box-shadow: 0px 0px 6px "+shadowColor+";"
|
||||
+"} \n"
|
||||
+qualifier + ".dg-chart-setting-box .dg-chart-setting-panel .dg-chartdataset-section{"
|
||||
+" color: "+color+";"
|
||||
+" background: "+bgColor+";"
|
||||
+" border-color: "+borderColor+";"
|
||||
+"} \n"
|
||||
+qualifier + ".dg-chart-setting-box .dg-chart-setting-panel .dg-chart-setting-panel-foot button{"
|
||||
+" color: "+color+";"
|
||||
+" background: "+chartFactory.getGradualColor(chartTheme, 0.1)+";"
|
||||
+" border-color: "+borderColor+";"
|
||||
+"} \n"
|
||||
+qualifier + ".dg-chart-setting-box .dg-chart-setting-panel .dg-chart-setting-panel-foot button:hover{"
|
||||
+" background: "+chartFactory.getGradualColor(chartTheme, 0.3)+";"
|
||||
+"} \n"
|
||||
;
|
||||
|
||||
chartFactory.createStyleSheet(styleId, cssText, "beforeFirstScript");
|
||||
|
||||
return true;
|
||||
var color = chart.gradualColor(1);
|
||||
var bgColor = chart.gradualColor(0);
|
||||
var borderColor = chart.gradualColor(0.5);
|
||||
var shadowColor = chart.gradualColor(0.9);
|
||||
|
||||
var css =
|
||||
[
|
||||
{
|
||||
name: " .dg-chart-setting-box .dg-chart-setting-button",
|
||||
value:
|
||||
{
|
||||
"color": color,
|
||||
"background-color": bgColor,
|
||||
"border-color": borderColor
|
||||
}
|
||||
},
|
||||
{
|
||||
name: " .dg-chart-setting-box .dg-chart-setting-button:hover",
|
||||
value:
|
||||
{
|
||||
"background-color": chart.gradualColor(0.2)
|
||||
}
|
||||
},
|
||||
{
|
||||
name: " .dg-chart-setting-box .dg-chart-setting-panel",
|
||||
value:
|
||||
{
|
||||
"color": color,
|
||||
"background-color": bgColor,
|
||||
"border-color": borderColor,
|
||||
"box-shadow": "0px 0px 6px " + shadowColor,
|
||||
"-webkit-box-shadow": "0px 0px 6px " + shadowColor
|
||||
}
|
||||
},
|
||||
{
|
||||
name: " .dg-chart-setting-box .dg-chart-setting-panel .dg-chartdataset-section",
|
||||
value:
|
||||
{
|
||||
"color": color,
|
||||
"background-color": bgColor,
|
||||
"border-color": borderColor
|
||||
}
|
||||
},
|
||||
{
|
||||
name: " .dg-chart-setting-box .dg-chart-setting-panel .dg-chart-setting-panel-foot button",
|
||||
value:
|
||||
{
|
||||
"color": color,
|
||||
"background-color": chart.gradualColor(0.1),
|
||||
"border-color": borderColor
|
||||
}
|
||||
},
|
||||
{
|
||||
name: " .dg-chart-setting-box .dg-chart-setting-panel .dg-chart-setting-panel-foot button:hover",
|
||||
value:
|
||||
{
|
||||
"background-color": chart.gradualColor(0.3)
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
return css;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -1467,7 +1567,7 @@
|
|||
var $panelContent = $("<div class='dg-chart-setting-panel-content' />").appendTo($panel);
|
||||
var $panelFoot = $("<div class='dg-chart-setting-panel-foot' />").appendTo($panel);
|
||||
|
||||
chartSetting.setChartSettingDataPanelStyle($panel, chart.theme());
|
||||
chartSetting.setChartSettingDataPanelThemeStyle(chart, $panel);
|
||||
chartSetting.setChartSetingPanelContentSizeRange(chart, $panel, $panelContent,$panelFoot);
|
||||
|
||||
for(var i=0; i<chartDataSets.length; i++)
|
||||
|
@ -1688,72 +1788,100 @@
|
|||
return title;
|
||||
};
|
||||
|
||||
chartSetting.setChartSettingDataPanelStyle = function($panel, chartTheme)
|
||||
chartSetting.setChartSettingDataPanelThemeStyle = function(chart, $panel)
|
||||
{
|
||||
var styleClassName = chartTheme._chartSettingDataPanelStyleClassName;
|
||||
if(!styleClassName)
|
||||
chart.themeStyleSheet(chartFactory.builtinPropName("ChartSettingDataPanel"), function()
|
||||
{
|
||||
styleClassName = chartFactory.nextElementId();
|
||||
chartTheme._chartSettingDataPanelStyleClassName = styleClassName;
|
||||
}
|
||||
|
||||
$panel.addClass(styleClassName);
|
||||
|
||||
var styleId = (chartTheme._chartSettingDataPanelStyleSheetId
|
||||
|| (chartTheme._chartSettingDataPanelStyleSheetId = chartFactory.nextElementId()));
|
||||
|
||||
if(chartFactory.isStyleSheetCreated(styleId))
|
||||
return false;
|
||||
|
||||
//表格背景色应与面板背景色一致,且不能设透明背景色,因为设置了固定列
|
||||
var bgColor = chartFactory.getGradualColor(chartTheme, 0);
|
||||
|
||||
var qualifier = "." + styleClassName;
|
||||
|
||||
var cssText =
|
||||
qualifier + " table.dataTable tbody tr{"
|
||||
+ " color:"+chartTheme.color+";"
|
||||
+" }\n"
|
||||
+qualifier + " table.dataTable thead th,\n"
|
||||
+qualifier + " table.dataTable thead td{"
|
||||
+" color:"+chartTheme.titleColor+";"
|
||||
+" background:"+bgColor+";"
|
||||
+" }\n"
|
||||
+qualifier + " table.dataTable.stripe tbody tr.odd,\n"
|
||||
+qualifier + " table.dataTable.display tbody tr.odd{"
|
||||
+" background:"+chartFactory.getGradualColor(chartTheme, 0.1)+";"
|
||||
+" } \n"
|
||||
+qualifier + " table.dataTable.stripe tbody tr.even,\n"
|
||||
+qualifier + " table.dataTable.display tbody tr.even{"
|
||||
+" background:"+bgColor+";"
|
||||
+" }\n"
|
||||
+qualifier + " table.dataTable.hover tbody tr.hover,\n"
|
||||
+qualifier + " table.dataTable.hover tbody tr:hover,\n"
|
||||
+qualifier + " table.dataTable.display tbody tr:hover,\n"
|
||||
+qualifier + " table.dataTable.hover tbody tr.hover.selected,\n"
|
||||
+qualifier + " table.dataTable.hover tbody > tr.selected:hover,\n"
|
||||
+qualifier + " table.dataTable.hover tbody > tr > .selected:hover,\n"
|
||||
+qualifier + " table.dataTable.display tbody > tr.selected:hover,\n"
|
||||
+qualifier + " table.dataTable.display tbody > tr > .selected:hover{"
|
||||
+" background:"+chartFactory.getGradualColor(chartTheme, 0.3)+";"
|
||||
+" }\n"
|
||||
+qualifier + " table.dataTable tbody > tr.selected,\n"
|
||||
+qualifier + " table.dataTable tbody > tr > .selected,\n"
|
||||
+qualifier + " table.dataTable.stripe tbody > tr.even.selected,\n"
|
||||
+qualifier + " table.dataTable.stripe tbody > tr.even > .selected,\n"
|
||||
+qualifier + " table.dataTable.display tbody > tr.even.selected,\n"
|
||||
+qualifier + " table.dataTable.display tbody > tr.even > .selected,\n"
|
||||
+qualifier + " table.dataTable.stripe tbody > tr.odd.selected,\n"
|
||||
+qualifier + " table.dataTable.stripe tbody > tr.odd > .selected,\n"
|
||||
+qualifier + " table.dataTable.display tbody > tr.odd.selected,\n"
|
||||
+qualifier + " table.dataTable.display tbody > tr.odd > .selected{"
|
||||
+" color:"+chartTheme.highlightTheme.color+";"
|
||||
+" background:"+chartTheme.highlightTheme.backgroundColor+";"
|
||||
+" }\n";
|
||||
|
||||
chartFactory.createStyleSheet(styleId, cssText, "beforeFirstScript");
|
||||
|
||||
return true;
|
||||
var theme = chart.theme();
|
||||
//表格背景色应与面板背景色一致,且不能设透明背景色,因为设置了固定列
|
||||
var bgColor = chart.gradualColor(0);
|
||||
|
||||
var cssPrefix = " .dg-chart-setting-box .dg-chart-setting-data-panel";
|
||||
|
||||
var css =
|
||||
[
|
||||
{
|
||||
name: cssPrefix + " table.dataTable tbody tr",
|
||||
value:
|
||||
{
|
||||
"color": theme.color
|
||||
}
|
||||
},
|
||||
{
|
||||
name:
|
||||
[
|
||||
cssPrefix + " table.dataTable thead th",
|
||||
cssPrefix + " table.dataTable thead td"
|
||||
],
|
||||
value:
|
||||
{
|
||||
"color": theme.titleColor,
|
||||
"background-color": bgColor
|
||||
}
|
||||
},
|
||||
{
|
||||
name:
|
||||
[
|
||||
cssPrefix + " table.dataTable.stripe tbody tr.odd",
|
||||
cssPrefix + " table.dataTable.display tbody tr.odd"
|
||||
],
|
||||
value:
|
||||
{
|
||||
"background-color": chart.gradualColor(0.1)
|
||||
}
|
||||
},
|
||||
{
|
||||
name:
|
||||
[
|
||||
cssPrefix + " table.dataTable.stripe tbody tr.even",
|
||||
cssPrefix + " table.dataTable.display tbody tr.even"
|
||||
],
|
||||
value:
|
||||
{
|
||||
"background-color": bgColor
|
||||
}
|
||||
},
|
||||
{
|
||||
name:
|
||||
[
|
||||
cssPrefix + " table.dataTable.hover tbody tr.hover",
|
||||
cssPrefix + " table.dataTable.hover tbody tr:hover",
|
||||
cssPrefix + " table.dataTable.display tbody tr:hover",
|
||||
cssPrefix + " table.dataTable.hover tbody tr.hover.selected",
|
||||
cssPrefix + " table.dataTable.hover tbody > tr.selected:hover",
|
||||
cssPrefix + " table.dataTable.hover tbody > tr > .selected:hover",
|
||||
cssPrefix + " table.dataTable.display tbody > tr.selected:hover",
|
||||
cssPrefix + " table.dataTable.display tbody > tr > .selected:hover"
|
||||
],
|
||||
value:
|
||||
{
|
||||
"background-color": chart.gradualColor(0.3)
|
||||
}
|
||||
},
|
||||
{
|
||||
name:
|
||||
[
|
||||
cssPrefix + " table.dataTable tbody > tr.selected",
|
||||
cssPrefix + " table.dataTable tbody > tr > .selected",
|
||||
cssPrefix + " table.dataTable.stripe tbody > tr.even.selected",
|
||||
cssPrefix + " table.dataTable.stripe tbody > tr.even > .selected",
|
||||
cssPrefix + " table.dataTable.display tbody > tr.even.selected",
|
||||
cssPrefix + " table.dataTable.display tbody > tr.even > .selected",
|
||||
cssPrefix + " table.dataTable.stripe tbody > tr.odd.selected",
|
||||
cssPrefix + " table.dataTable.stripe tbody > tr.odd > .selected",
|
||||
cssPrefix + " table.dataTable.display tbody > tr.odd.selected",
|
||||
cssPrefix + " table.dataTable.display tbody > tr.odd > .selected"
|
||||
],
|
||||
value:
|
||||
{
|
||||
"color": theme.highlightTheme.color,
|
||||
"background-color": theme.highlightTheme.backgroundColor
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
return css;
|
||||
});
|
||||
};
|
||||
|
||||
chartSetting.updateChartSettingDataTableData = function(chart, chartDataSets, index, $dataTable)
|
||||
|
|
|
@ -1954,12 +1954,11 @@
|
|||
|
||||
for(var j=0; j<data.length; j++)
|
||||
{
|
||||
//在ECharts-4.9.0时,这里格式为:{name: ..., value:[经度值, 纬度值, 关系数值]},是没问题的,
|
||||
//但是升级至ECharts-5.0+后,会报错:Can not read property 'off' of undefined
|
||||
//按照ECharts-5.0+的graph的官方配置项,这里格式应为:{name: ..., x: 经度值, y: 纬度值, value: 关系数值}
|
||||
//但是这样仍然会报上述错误!
|
||||
//所以这里仍恢复为采用ECharts-4.9.0时的格式,配合修改了ECharts-5.1.2的源码后,终于解决了上述问题!
|
||||
//具体源码修改位置参考echarts-5.1.2/echarts.js的58833行
|
||||
//ECharts-4.9.0时graph官方数据格式为【名/值数组】:{name: ..., value:[经度值, 纬度值, 关系数值]}
|
||||
//ECharts-5.0+ 时graph官方数据格式为【名/X/Y/值】:{name: ..., x: 经度值, y: 纬度值, value: 关系数值}
|
||||
//在ECharts由4.9.0升级至5.1.2版本后,【名/值数组】、【名/X/Y/值】格式都会报错:Can not read property 'off' of undefined,
|
||||
//在修改了源码(修改位置参考DataGear-2.8.0版本echarts-5.1.2/echarts.js的58833行)同时采用【名/值数组】格式后才解决。
|
||||
//在ECharts由5.1.2升级至5.2.0版本后,【名/X/Y/值】格式不会报错但是显示位置不对,【名/值数组】则可以正常展示
|
||||
var sd = { name: chart.resultRowCell(data[j], snp), value: [ chart.resultRowCell(data[j], slop), chart.resultRowCell(data[j], slap) ] };
|
||||
var td = { name: chart.resultRowCell(data[j], tnp), value: [ chart.resultRowCell(data[j], tlop), chart.resultRowCell(data[j], tlap) ] };
|
||||
|
||||
|
@ -3936,10 +3935,10 @@
|
|||
hideVerticalScrollbar: true
|
||||
};
|
||||
|
||||
var themeBindTableOptions = chartTheme._chartTableThemeBindOptions;
|
||||
if(themeBindTableOptions == null)
|
||||
var themeAwareOptionsAttrTable = chartTheme._chartTableThemeAwareOptionsAttrTable;
|
||||
if(themeAwareOptionsAttrTable == null)
|
||||
{
|
||||
themeBindTableOptions=
|
||||
themeAwareOptionsAttrTable=
|
||||
{
|
||||
//表头样式
|
||||
"header":
|
||||
|
@ -3980,10 +3979,10 @@
|
|||
renderValue: undefined
|
||||
};
|
||||
|
||||
themeBindTableOptions._chartTableStyleClassName = chartFactory.nextElementId();
|
||||
themeBindTableOptions._chartTableStyleSheetId = chartFactory.nextElementId();
|
||||
themeAwareOptionsAttrTable._chartTableStyleClassName = chartFactory.nextElementId();
|
||||
themeAwareOptionsAttrTable._chartTableStyleSheetId = chartFactory.nextElementId();
|
||||
|
||||
chartTheme._chartTableThemeBindOptions = themeBindTableOptions;
|
||||
chartTheme._chartTableThemeAwareOptionsAttrTable = themeAwareOptionsAttrTable;
|
||||
}
|
||||
|
||||
var columns = [];
|
||||
|
@ -4016,14 +4015,14 @@
|
|||
"backgroundColor": chartTheme.backgroundColor
|
||||
},
|
||||
|
||||
//表格,格式参考上面的themeBindTableOptions
|
||||
//表格,格式参考上面的themeAwareOptionsAttrTable
|
||||
table: undefined,
|
||||
|
||||
//轮播,格式可以为:true、false、轮播interval数值、轮播interval返回函数、{...}
|
||||
carousel: undefined,
|
||||
|
||||
//后置处理列函数,格式为:function(columns){ return columns; }
|
||||
postProcessColumns: undefined,
|
||||
//是否美化滚动条(仅支持webkit内核浏览器)
|
||||
beautifyScrollbar: true,
|
||||
|
||||
//DataTable配置项
|
||||
"columns": columns,
|
||||
|
@ -4059,12 +4058,12 @@
|
|||
},
|
||||
options, null, function(options)
|
||||
{
|
||||
//如果没有定义table选项,则采用全局themeBindTableOptions
|
||||
//如果没有定义table选项,则采用全局themeAwareOptionsAttrTable
|
||||
if(options.table == null)
|
||||
options.table = themeBindTableOptions;
|
||||
options.table = themeAwareOptionsAttrTable;
|
||||
else
|
||||
{
|
||||
options.table = $.extend(true, {}, themeBindTableOptions, options.table);
|
||||
options.table = $.extend(true, {}, themeAwareOptionsAttrTable, options.table);
|
||||
options.table._chartTableStyleClassName =chartFactory.nextElementId();
|
||||
options.table._chartTableStyleSheetId = chartFactory.nextElementId();
|
||||
}
|
||||
|
@ -4133,9 +4132,14 @@
|
|||
if(evalHeight)
|
||||
options.scrollY = 4;
|
||||
|
||||
if(options.beautifyScrollbar)
|
||||
chartEle.addClass("dg-chart-beautify-scrollbar");
|
||||
|
||||
if(options.carousel.enable)
|
||||
chartEle.addClass("dg-chart-table-carousel");
|
||||
|
||||
chartEle.addClass(options.table._chartTableStyleClassName);
|
||||
|
||||
chartSupport.tableCreateTableStyleSheet(chart, options,
|
||||
options.table._chartTableStyleClassName, options.table._chartTableStyleSheetId);
|
||||
|
||||
|
@ -4252,10 +4256,14 @@
|
|||
chartSupport.tableDestroy = function(chart)
|
||||
{
|
||||
var chartEle = chart.elementJquery();
|
||||
var renderOptions = chart.renderOptions();
|
||||
|
||||
chartSupport.tableStopCarousel(chart);
|
||||
chartEle.removeClass("dg-chart-table");
|
||||
chartEle.removeClass("dg-hide-title");
|
||||
chartEle.removeClass("dg-chart-table-carousel");
|
||||
chartEle.removeClass("dg-chart-beautify-scrollbar");
|
||||
chartEle.removeClass(renderOptions.table._chartTableStyleClassName);
|
||||
$(".dg-chart-table-title", chartEle).remove();
|
||||
$(".dg-chart-table-content", chartEle).remove();
|
||||
};
|
||||
|
@ -4330,13 +4338,12 @@
|
|||
|
||||
chartSupport.tableCreateTableStyleSheet = function(chart, chartOptions, styleClassName, styleSheetId)
|
||||
{
|
||||
chart.elementJquery().addClass(styleClassName);
|
||||
|
||||
if(chartFactory.isStyleSheetCreated(styleSheetId))
|
||||
return false;
|
||||
|
||||
//样式要加".dg-chart-table-content"限定,因为图表的数据透视表功能也采用的是DataTable组件,可能会处在同一个表格图表div内
|
||||
var qualifier = "." + styleClassName + " .dg-chart-table-content";
|
||||
var qualifierBeautifyScrollbar = "." + styleClassName + ".dg-chart-beautify-scrollbar .dg-chart-table-content";
|
||||
|
||||
var cssText =
|
||||
qualifier + " table.dataTable tbody tr{"
|
||||
|
@ -4386,9 +4393,21 @@
|
|||
+qualifier + " table.dataTable thead th.sorting_desc div.DataTables_sort_wrapper span{"
|
||||
+ " border-top-color:" + chartOptions.table.header.color+";"
|
||||
+ " background: none;"
|
||||
+" }\n";
|
||||
+" }\n"
|
||||
+qualifierBeautifyScrollbar + " .dataTables_scrollBody::-webkit-scrollbar{"
|
||||
+ " width: 10px;"
|
||||
+ " height: 10px;"
|
||||
+" }\n"
|
||||
+qualifierBeautifyScrollbar + " .dataTables_scrollBody::-webkit-scrollbar-thumb{"
|
||||
+ " border-radius: 10px;"
|
||||
+ " background: "+chart.gradualColor(0.3)+";"
|
||||
+" }\n"
|
||||
+qualifierBeautifyScrollbar + " .dataTables_scrollBody::-webkit-scrollbar-track{"
|
||||
+ " background: "+chart.gradualColor(0.1)+";"
|
||||
+" }\n"
|
||||
;
|
||||
|
||||
chartFactory.createStyleSheet(styleSheetId, cssText, "beforeFirstScript");
|
||||
chartFactory.styleSheetText(styleSheetId, cssText);
|
||||
|
||||
return true;
|
||||
};
|
||||
|
@ -4681,10 +4700,6 @@
|
|||
var chartEle = chart.elementJquery();
|
||||
chartEle.addClass("dg-chart-label");
|
||||
|
||||
var labelWrapper = $(".dg-chart-label-wrapper", chartEle);
|
||||
if(labelWrapper.length == 0)
|
||||
labelWrapper = $("<div class='dg-chart-label-wrapper' />").appendTo(chartEle);
|
||||
|
||||
options = chartSupport.inflateRenderOptions(chart,
|
||||
{
|
||||
//将在update中设置:
|
||||
|
@ -4692,6 +4707,9 @@
|
|||
|
||||
//是否所有标签都行内显示
|
||||
"inline": false,
|
||||
//是否以flex布局展示标签
|
||||
//弹性布局:true 是、居中间隔;false 否;"around" 居中间隔;"start" 左对齐;"end" 右对齐;"center" 居中;"between" 贴边间隔;
|
||||
"flex": false,
|
||||
//是否标签值在前
|
||||
"valueFirst": false,
|
||||
//标签名样式,这里不必添加默认样式,因为图表元素已设置
|
||||
|
@ -4705,7 +4723,23 @@
|
|||
options);
|
||||
|
||||
if(options.inline == true)
|
||||
labelWrapper.addClass("dg-chart-label-inline");
|
||||
chartEle.addClass("dg-chart-label-inline");
|
||||
|
||||
if(options.flex != null && options.flex != false)
|
||||
{
|
||||
chartEle.addClass("dg-chart-label-flex");
|
||||
|
||||
if(options.flex == "start")
|
||||
chartEle.addClass("dg-chart-label-flex-start");
|
||||
else if(options.flex == "end")
|
||||
chartEle.addClass("dg-chart-label-flex-end");
|
||||
else if(options.flex == "center")
|
||||
chartEle.addClass("dg-chart-label-flex-center");
|
||||
else if(options.flex == "between")
|
||||
chartEle.addClass("dg-chart-label-flex-between");
|
||||
else
|
||||
chartEle.addClass("dg-chart-label-flex-around");
|
||||
}
|
||||
|
||||
// < @deprecated 兼容2.7.0版本的{label:{name:{...},value:{...}}}配置项结构,未来版本会移除
|
||||
if(options.label && options.label.name)
|
||||
|
@ -4714,7 +4748,7 @@
|
|||
options.value = $.extend(true, {}, options.value, options.label.value);
|
||||
// > @deprecated 兼容2.7.0版本的{label:{name:{...},value:{...}}}配置项结构,未来版本会移除
|
||||
|
||||
chart.internal(labelWrapper[0]);
|
||||
chart.internal(chart.element());
|
||||
};
|
||||
|
||||
chartSupport.labelUpdate = function(chart, results)
|
||||
|
@ -4855,8 +4889,10 @@
|
|||
chartSupport.labelDestroy = function(chart)
|
||||
{
|
||||
var chartEle = chart.elementJquery();
|
||||
chartEle.removeClass("dg-chart-label");
|
||||
$(chart.internal()).remove();
|
||||
chartEle.removeClass("dg-chart-label dg-chart-label-inline dg-chart-label-flex "
|
||||
+"dg-chart-label-flex-around dg-chart-label-flex-start dg-chart-label-flex-end "
|
||||
+"dg-chart-label-flex-center dg-chart-label-flex-between");
|
||||
$(".dg-chart-label-item", chart.internal()).remove();
|
||||
};
|
||||
|
||||
chartSupport.labelOn = function(chart, eventType, handler)
|
||||
|
@ -4902,6 +4938,276 @@
|
|||
chartSupport.setChartEventOriginalInfo(chart, chartEvent, chartData);
|
||||
};
|
||||
|
||||
//下拉框
|
||||
|
||||
chartSupport.selectRender = function(chart, nameSign, valueSign, options)
|
||||
{
|
||||
chartSupport.chartSignNameMap(chart, { name: nameSign, value: valueSign });
|
||||
|
||||
var chartEle = chart.elementJquery();
|
||||
chartEle.addClass("dg-chart-select");
|
||||
|
||||
options = chartSupport.inflateRenderOptions(chart,
|
||||
{
|
||||
//将在update中设置:
|
||||
//下拉框数据:
|
||||
// data:
|
||||
// [
|
||||
// {
|
||||
// //选项名,可选,默认为选项值
|
||||
// name: "...",
|
||||
// //选项值
|
||||
// value: ...,
|
||||
// //是否选中,可选,默认为:false
|
||||
// selected: true 或 false,
|
||||
// //选项css样式,可选
|
||||
// itemStyle: { ... }
|
||||
// },
|
||||
// ...
|
||||
// ]
|
||||
|
||||
//下拉框名称
|
||||
name: undefined,
|
||||
//是否多选
|
||||
multiple: false,
|
||||
//可见选项数目
|
||||
size: undefined,
|
||||
//默认选中项:null:默认;数值或其数组:选中指定索引的选项;
|
||||
selected: undefined,
|
||||
//前置添加的条目项,格式同data元素,或者其数组,通常用于添加默认选中项
|
||||
prepend: undefined,
|
||||
//是否美化多选时的滚动条(仅支持webkit内核浏览器)
|
||||
beautifyScrollbar: true,
|
||||
//下拉框是否填满父元素,"auto" 当是内联框时填满;true 是;false 否
|
||||
fillParent: "auto",
|
||||
//select框css样式,格式为:{ ... }
|
||||
selectStyle: undefined,
|
||||
//option选项整体css样式,格式为:{ ... }
|
||||
itemStyle: undefined
|
||||
},
|
||||
options);
|
||||
|
||||
chartSupport.selectThemeStyleSheet(chart);
|
||||
|
||||
var isDropdown = (!options.multiple && (options.size == null || options.size <= 1));
|
||||
|
||||
if(options.beautifyScrollbar)
|
||||
chartEle.addClass("dg-chart-beautify-scrollbar");
|
||||
if(isDropdown)
|
||||
chartEle.addClass("dg-chart-select-dropdown");
|
||||
if(options.fillParent === true || (options.fillParent == "auto" && !isDropdown))
|
||||
chartEle.addClass("dg-chart-select-fill");
|
||||
|
||||
var $select = $("<select class='dg-chart-select-select' />").appendTo(chartEle);
|
||||
|
||||
if(options.name)
|
||||
$select.attr("name", options.name);
|
||||
if(options.multiple)
|
||||
$select.attr("multiple", "multiple");
|
||||
if(options.size != null)
|
||||
$select.attr("size", options.size);
|
||||
if(options.selectStyle)
|
||||
chartFactory.setStyles($select, options.selectStyle);
|
||||
|
||||
chart.internal($select[0]);
|
||||
};
|
||||
|
||||
chartSupport.selectUpdate = function(chart, results)
|
||||
{
|
||||
var signNameMap = chartSupport.chartSignNameMap(chart);
|
||||
var renderOptions = chart.renderOptions();
|
||||
|
||||
var chartDataSets = chart.chartDataSetsMain();
|
||||
|
||||
var $select = $(chart.internal());
|
||||
|
||||
$select.empty();
|
||||
|
||||
var selected = renderOptions.selected;
|
||||
|
||||
if(selected != null && typeof(selected) == "number")
|
||||
selected = [ selected ];
|
||||
|
||||
var updateOptions = { data: [] };
|
||||
|
||||
for(var i=0; i<chartDataSets.length; i++)
|
||||
{
|
||||
var chartDataSet = chartDataSets[i];
|
||||
|
||||
var result = chart.resultOf(results, chartDataSet);
|
||||
|
||||
var nps = chart.dataSetPropertiesOfSign(chartDataSet, signNameMap.name);
|
||||
var vps = chart.dataSetPropertiesOfSign(chartDataSet, signNameMap.value);
|
||||
var hasNps = (nps && nps.length > 0);
|
||||
|
||||
if(hasNps && nps.length != vps.length)
|
||||
throw new Error("The ["+signNameMap.name+"] sign column must be "
|
||||
+"one-to-one with ["+signNameMap.value+"] sign column");
|
||||
|
||||
var namess = (hasNps ? chart.resultRowArrays(result, nps) : []);
|
||||
var valuess = chart.resultRowArrays(result, vps);
|
||||
|
||||
for(var j=0; j<valuess.length; j++)
|
||||
{
|
||||
var values = valuess[j];
|
||||
var names = (hasNps ? namess[j] : values);
|
||||
|
||||
for(var k=0; k<names.length; k++)
|
||||
{
|
||||
var sv = { name: names[k], value: values[k] };
|
||||
chart.originalInfo(sv, chartDataSet, j);
|
||||
|
||||
updateOptions.data.push(sv);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
updateOptions = chart.inflateUpdateOptions(results, updateOptions);
|
||||
var data = updateOptions.data;
|
||||
|
||||
if(renderOptions.prepend)
|
||||
{
|
||||
var newData = ($.isArray(renderOptions.prepend) ? renderOptions.prepend : [ renderOptions.prepend ]);
|
||||
data = newData.concat(data);
|
||||
}
|
||||
|
||||
for(var i=0; i<data.length; i++)
|
||||
{
|
||||
var optData = data[i];
|
||||
|
||||
var $opt = $("<option />").attr("value", optData.value)
|
||||
.html(optData.name ? optData.name : optData.value).appendTo($select);
|
||||
|
||||
if(optData.selected || (selected != null && $.inArray(i, selected) > -1))
|
||||
$opt.attr("selected", "selected");
|
||||
|
||||
$opt.data("_dgChartSelectOptionChartData", optData);
|
||||
|
||||
var itemStyle = null;
|
||||
|
||||
if(renderOptions.itemStyle && optData.itemStyle)
|
||||
itemStyle = $.extend({}, renderOptions.itemStyle, optData.itemStyle);
|
||||
else if(renderOptions.itemStyle)
|
||||
itemStyle = renderOptions.itemStyle;
|
||||
else if(optData.itemStyle)
|
||||
itemStyle = optData.itemStyle;
|
||||
|
||||
if(itemStyle)
|
||||
chartFactory.setStyles($opt, itemStyle);
|
||||
}
|
||||
};
|
||||
|
||||
chartSupport.selectResize = function(chart)
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
chartSupport.selectDestroy = function(chart)
|
||||
{
|
||||
var chartEle = chart.elementJquery();
|
||||
|
||||
chartEle.removeClass("dg-chart-select dg-chart-select-dropdown dg-chart-beautify-scrollbar");
|
||||
|
||||
$(chart.internal()).remove();
|
||||
};
|
||||
|
||||
chartSupport.selectOn = function(chart, eventType, handler)
|
||||
{
|
||||
var handlerDelegation = function(htmlEvent)
|
||||
{
|
||||
var $select = $(this);
|
||||
var chartEvent = chart.eventNewHtml(eventType, htmlEvent);
|
||||
chartSupport.selectSetChartEventData(chart, chartEvent, htmlEvent, $select);
|
||||
|
||||
chart.callEventHandler(handler, chartEvent);
|
||||
};
|
||||
|
||||
chart.registerEventHandlerDelegation(eventType, handler, handlerDelegation);
|
||||
$(chart.internal()).on(eventType, handlerDelegation);
|
||||
};
|
||||
|
||||
chartSupport.selectOff = function(chart, eventType, handler)
|
||||
{
|
||||
var internal = $(chart.internal());
|
||||
|
||||
chart.removeEventHandlerDelegation(eventType, handler, function(et, eh, ehd)
|
||||
{
|
||||
internal.off(et, ehd);
|
||||
});
|
||||
};
|
||||
|
||||
chartSupport.selectSetChartEventData = function(chart, chartEvent, htmlEvent, $select)
|
||||
{
|
||||
var signNameMap = chartSupport.chartSignNameMap(chart);
|
||||
|
||||
var chartData = $select.data("_dgChartSelectOptionChartData");
|
||||
|
||||
var data = {};
|
||||
|
||||
if(chartData)
|
||||
{
|
||||
data[signNameMap.name] = chartData.name;
|
||||
data[signNameMap.value] = chartData.value;
|
||||
}
|
||||
|
||||
chart.eventData(chartEvent, data);
|
||||
chartSupport.setChartEventOriginalInfo(chart, chartEvent, chartData);
|
||||
};
|
||||
|
||||
chartSupport.selectThemeStyleSheet = function(chart)
|
||||
{
|
||||
chart.themeStyleSheet(chartFactory.builtinPropName("SelectChart"), function()
|
||||
{
|
||||
var chartTheme = chart.theme();
|
||||
|
||||
var css=
|
||||
[
|
||||
{
|
||||
name: " .dg-chart-select-select",
|
||||
value:
|
||||
{
|
||||
"color": chartTheme.color,
|
||||
"background-color": chartTheme.backgroundColor,
|
||||
"border-color": chartTheme.borderColor
|
||||
}
|
||||
},
|
||||
{
|
||||
name: ".dg-chart-select-dropdown .dg-chart-select-select option",
|
||||
value:
|
||||
{
|
||||
"color": chartTheme.color,
|
||||
"background-color": chart.gradualColor(0.1)
|
||||
}
|
||||
},
|
||||
{
|
||||
name: ".dg-chart-beautify-scrollbar .dg-chart-select-select::-webkit-scrollbar",
|
||||
value:
|
||||
{
|
||||
"width": "10px",
|
||||
"height": "10px"
|
||||
}
|
||||
},
|
||||
{
|
||||
name: ".dg-chart-beautify-scrollbar .dg-chart-select-select::-webkit-scrollbar-thumb",
|
||||
value:
|
||||
{
|
||||
"border-radius": "10px",
|
||||
"background": chart.gradualColor(0.3)
|
||||
}
|
||||
},
|
||||
{
|
||||
name: ".dg-chart-beautify-scrollbar .dg-chart-select-select::-webkit-scrollbar-track",
|
||||
value:
|
||||
{
|
||||
"background": chart.gradualColor(0.1)
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
return css;
|
||||
});
|
||||
};
|
||||
|
||||
//自定义
|
||||
|
||||
chartSupport.customAsyncRender = function(chart)
|
||||
|
|
|
@ -2141,7 +2141,7 @@
|
|||
|
||||
var re = [];
|
||||
|
||||
var pname = chartFactory.DATA_ORIGINAL_INFO_PROP_NAME;
|
||||
var pname = chartFactory._DATA_ORIGINAL_INFO_PROP_NAME;
|
||||
|
||||
for(var i=0; i<data.length; i++)
|
||||
{
|
||||
|
|
|
@ -3391,7 +3391,7 @@
|
|||
}
|
||||
};
|
||||
|
||||
$.handleAjaxOperationMessage = function(jqXHR, errorThrown)
|
||||
$.handleAjaxOperationMessage = function(event, jqXHR, ajaxSettings, data, thrownError)
|
||||
{
|
||||
if(!window._showAjaxOperationMessageDetail)
|
||||
{
|
||||
|
@ -3399,9 +3399,9 @@
|
|||
{
|
||||
$.closeTip();
|
||||
|
||||
var $operationMessageParent = $("#__operationMessageParent");
|
||||
var $omp = $("#__operationMessageParent");
|
||||
|
||||
var isSuccessMessage = ("true" == $operationMessageParent.attr("success"));
|
||||
var isSuccessMessage = ("true" == $omp.attr("success"));
|
||||
|
||||
var $dialog = $("<div id='dialog-"+new Date().getTime()+"' class='operation-message-dialog'></div>").appendTo(document.body);
|
||||
|
||||
|
@ -3409,11 +3409,11 @@
|
|||
if(!isSuccessMessage)
|
||||
$messageDetail.addClass("ui-state-error");
|
||||
$messageDetail.appendTo($dialog);
|
||||
$messageDetail.html($(".message-detail", $operationMessageParent).html());
|
||||
$messageDetail.html($(".message-detail", $omp).html());
|
||||
|
||||
$._dialog($dialog,
|
||||
{
|
||||
title : $(".message", $operationMessageParent).text(),
|
||||
title : $(".message", $omp).text(),
|
||||
modal : true,
|
||||
height: "60%",
|
||||
position: {my: "center top", at: "center top+3"},
|
||||
|
@ -3436,25 +3436,24 @@
|
|||
};
|
||||
}
|
||||
|
||||
var isSuccessMessage = (jqXHR.status == 200);
|
||||
var $omp = $("#__operationMessageParent");
|
||||
if($omp.length == 0)
|
||||
$omp = $("<div id='__operationMessageParent' style='display:none;' />").appendTo(document.body);
|
||||
|
||||
var isSuccessResponse = (jqXHR.status == 200);
|
||||
var hasResponseMessage = false;
|
||||
|
||||
if(jqXHR.responseText)
|
||||
{
|
||||
var $operationMessageParent = $("#__operationMessageParent");
|
||||
if($operationMessageParent.length == 0)
|
||||
$operationMessageParent = $("<div id='__operationMessageParent' style='display:none;' />").appendTo(document.body);
|
||||
|
||||
var operationMessage = $.getResponseJson(jqXHR);
|
||||
|
||||
var hasMessage = false;
|
||||
|
||||
//操作消息的JSON响应
|
||||
//响应为JSON操作消息的
|
||||
if(operationMessage && operationMessage.type && operationMessage.code && operationMessage.message)
|
||||
{
|
||||
$operationMessageParent.empty();
|
||||
$omp.empty();
|
||||
|
||||
var $omdiv = $("<div class='operation-message "+operationMessage.type+"' />").appendTo($operationMessageParent);
|
||||
var $mdiv = $("<div class='message' />").appendTo($omdiv).html(operationMessage.message);
|
||||
var $omdiv = $("<div class='operation-message "+operationMessage.type+"' />").appendTo($omp);
|
||||
$("<div class='message' />").appendTo($omdiv).html(operationMessage.message);
|
||||
|
||||
if(operationMessage.detail)
|
||||
{
|
||||
|
@ -3465,54 +3464,64 @@
|
|||
$("<div />").appendTo($ddiv).html(operationMessage.detail);
|
||||
}
|
||||
|
||||
hasMessage = true;
|
||||
hasResponseMessage = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(isSuccessMessage)
|
||||
hasMessage = false;
|
||||
else
|
||||
var rtPrefix = jqXHR.responseText.substr(0, 100);
|
||||
var dpnValue = null;
|
||||
|
||||
var dpnToken = "dg-page-name=\"";
|
||||
var dpnStartIdx = rtPrefix.indexOf(dpnToken);
|
||||
if(dpnStartIdx > -1)
|
||||
{
|
||||
//操作消息的HTML响应
|
||||
$operationMessageParent.html(jqXHR.responseText);
|
||||
hasMessage = true;
|
||||
dpnStartIdx = dpnStartIdx + dpnToken.length;
|
||||
var dpnEndIdx = rtPrefix.indexOf("\"", dpnStartIdx);
|
||||
dpnValue = (dpnEndIdx > dpnStartIdx ? rtPrefix.substring(dpnStartIdx, dpnEndIdx) : null);
|
||||
}
|
||||
}
|
||||
|
||||
if(hasMessage)
|
||||
{
|
||||
$operationMessageParent.attr("success", isSuccessMessage);
|
||||
var message = $(".message", $operationMessageParent).html();
|
||||
|
||||
if($(".message-detail", $operationMessageParent).length > 0)
|
||||
message += "<span class='ui-icon ui-icon-comment message-detail-icon' onclick='_showAjaxOperationMessageDetail();'></span>";
|
||||
|
||||
if(isSuccessMessage)
|
||||
$.tipSuccess(message);
|
||||
else
|
||||
$.tipError(message);
|
||||
//响应为HTML操作消息的
|
||||
if(dpnValue == "error")
|
||||
{
|
||||
$omp.html(jqXHR.responseText);
|
||||
hasResponseMessage = true;
|
||||
}
|
||||
//当登录超时后,列表页点击【查询】按钮,ajax响应可能会重定向到登录页,这里特殊处理
|
||||
else if(dpnValue == "login")
|
||||
{
|
||||
var url = ajaxSettings.url;
|
||||
|
||||
if(url && url.indexOf("/login") < 0)
|
||||
{
|
||||
thrownError = "Login expired";
|
||||
hasResponseMessage = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
if(hasResponseMessage)
|
||||
{
|
||||
if(isSuccessMessage)
|
||||
;
|
||||
$omp.attr("success", isSuccessResponse);
|
||||
var message = $(".message", $omp).html();
|
||||
|
||||
if($(".message-detail", $omp).length > 0)
|
||||
message += "<span class='ui-icon ui-icon-comment message-detail-icon' onclick='_showAjaxOperationMessageDetail();'></span>";
|
||||
|
||||
if(isSuccessResponse)
|
||||
$.tipSuccess(message);
|
||||
else
|
||||
{
|
||||
/* 在firefox中,cometd连接有可能会被用户操作请求中断,导致莫名其妙地弹出错误提示,因此把此处代码禁用
|
||||
var msg = (jqXHR.statusText || "Error");
|
||||
|
||||
if(errorThrown && errorThrown.message)
|
||||
{
|
||||
if(msg)
|
||||
msg += " : ";
|
||||
|
||||
msg += errorThrown.message;
|
||||
}
|
||||
|
||||
$.tipError(msg);
|
||||
*/
|
||||
}
|
||||
$.tipError(message);
|
||||
}
|
||||
//客户端处理ajax响应出错
|
||||
else if(thrownError)
|
||||
{
|
||||
$.tipError(thrownError);
|
||||
}
|
||||
//客户端连接出错
|
||||
else if(event && event.type=="ajaxError")
|
||||
{
|
||||
$.tipError("Error");
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -3531,12 +3540,12 @@
|
|||
|
||||
$(document).ajaxError(function(event, jqXHR, ajaxSettings, thrownError)
|
||||
{
|
||||
$.handleAjaxOperationMessage(jqXHR, thrownError);
|
||||
$.handleAjaxOperationMessage(event, jqXHR, ajaxSettings, null, thrownError);
|
||||
});
|
||||
|
||||
$(document).ajaxSuccess(function(event, jqXHR, ajaxSettings, thrownError)
|
||||
$(document).ajaxSuccess(function(event, jqXHR, ajaxSettings, data)
|
||||
{
|
||||
$.handleAjaxOperationMessage(jqXHR, thrownError);
|
||||
$.handleAjaxOperationMessage(event, jqXHR, ajaxSettings, data, null);
|
||||
});
|
||||
|
||||
/**
|
||||
|
|
|
@ -62,6 +62,18 @@ form .form-content .form-item .form-item-value textarea.error{
|
|||
background-color: #f58400;
|
||||
}
|
||||
|
||||
/*危险操作按钮*/
|
||||
.ui-button.danger, .ui-button.danger:active{
|
||||
border: 1px solid red;
|
||||
background-color: red;
|
||||
color: #ffffff;
|
||||
}
|
||||
.ui-button.danger:hover, .ui-button.danger:focus{
|
||||
border: 1px solid #ff5252;
|
||||
background-color: #ff5252;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
/*对话框*/
|
||||
/*可保持ui-state-active状态组件样式,默认图标是灰色,这了改成白色*/
|
||||
.stated-active.ui-state-active .ui-icon, .stated-active.ui-state-active:focus .ui-icon, .stated-active.ui-state-active:hover .ui-icon{
|
||||
|
|
|
@ -62,6 +62,18 @@ form .form-content .form-item .form-item-value textarea.error{
|
|||
background-color: #59c908;
|
||||
}
|
||||
|
||||
/*危险操作按钮*/
|
||||
.ui-button.danger, .ui-button.danger:active{
|
||||
border: 1px solid red;
|
||||
background-color: red;
|
||||
color: #ffffff;
|
||||
}
|
||||
.ui-button.danger:hover, .ui-button.danger:focus{
|
||||
border: 1px solid #ff5252;
|
||||
background-color: #ff5252;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
/*对话框*/
|
||||
/*可保持ui-state-active状态组件样式,默认图标是灰色,这了改成白色*/
|
||||
.stated-active.ui-state-active .ui-icon, .stated-active.ui-state-active:focus .ui-icon, .stated-active.ui-state-active:hover .ui-icon{
|
||||
|
|
|
@ -62,6 +62,18 @@ form .form-content .form-item .form-item-value textarea.error{
|
|||
background-color: #007fff;
|
||||
}
|
||||
|
||||
/*危险操作按钮*/
|
||||
.ui-button.danger, .ui-button.danger:active{
|
||||
border: 1px solid red;
|
||||
background-color: red;
|
||||
color: #ffffff;
|
||||
}
|
||||
.ui-button.danger:hover, .ui-button.danger:focus{
|
||||
border: 1px solid #ff5252;
|
||||
background-color: #ff5252;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
/*对话框*/
|
||||
/*可保持ui-state-active状态组件样式,默认图标是灰色,这了改成白色*/
|
||||
.stated-active.ui-state-active .ui-icon, .stated-active.ui-state-active:focus .ui-icon, .stated-active.ui-state-active:hover .ui-icon{
|
||||
|
|
|
@ -101,9 +101,7 @@ readonly 是否只读操作,允许为null
|
|||
po.element(".nameRow-radios").controlgroup();
|
||||
po.initWorkspaceHeight();
|
||||
po.initWorkspaceTabs(true);
|
||||
po.initDataSetPropertiesTable(po.dataSetProperties);
|
||||
po.initDataSetParamsTable(po.dataSetParams);
|
||||
po.initPreviewParamValuePanel();
|
||||
po.initParamPropertyDataFormat(po.dataSetParams, po.dataSetProperties);
|
||||
po.initNameRowOperation(${(dataSet.nameRow)!"1"});
|
||||
|
||||
po.initDataSetFileInput(po.url("uploadFile"), "${((dataSet.fileSourceType)!'')?js_string?no_esc}", ${isAdd?string("true", "false")});
|
||||
|
@ -142,11 +140,12 @@ readonly 是否只读操作,允许为null
|
|||
var pd = po.previewOptions.data.dataSet;
|
||||
var dataSetResDirectory = (pd.dataSetResDirectory || {});
|
||||
|
||||
return (pd.fileSourceType != fileSourceType)
|
||||
return ((pd.fileSourceType != fileSourceType)
|
||||
|| (po.isFileSourceTypeUpload(fileSourceType) && pd.fileName != fileName)
|
||||
|| (po.isFileSourceTypeServer(fileSourceType) && (dataSetResDirectory.id != dataSetResDirectoryId || pd.dataSetResFileName != dataSetResFileName))
|
||||
|| (pd.encoding != encoding)
|
||||
|| (pd.nameRow != nameRow) ;
|
||||
|| (pd.nameRow != nameRow)
|
||||
|| po.isPreviewParamPropertyDataFormatModified());
|
||||
};
|
||||
|
||||
po.previewOptions.url = po.url("previewCsvFile");
|
||||
|
|
|
@ -103,9 +103,7 @@ readonly 是否只读操作,允许为null
|
|||
var selectionRange = po.csvEditor.getSelectionRange();
|
||||
return (po.csvEditor.session.getTextRange(selectionRange) || "");
|
||||
};
|
||||
po.initDataSetPropertiesTable(po.dataSetProperties);
|
||||
po.initDataSetParamsTable(po.dataSetParams);
|
||||
po.initPreviewParamValuePanel();
|
||||
po.initParamPropertyDataFormat(po.dataSetParams, po.dataSetProperties);
|
||||
po.initNameRowOperation(${(dataSet.nameRow)!"1"});
|
||||
|
||||
po.updatePreviewOptionsData = function()
|
||||
|
@ -131,7 +129,8 @@ readonly 是否只读操作,允许为null
|
|||
|
||||
var pd = po.previewOptions.data.dataSet;
|
||||
|
||||
return (pd.value != value) || (pd.nameRow != nameRow);
|
||||
return (pd.value != value || pd.nameRow != nameRow
|
||||
|| po.isPreviewParamPropertyDataFormatModified());
|
||||
};
|
||||
|
||||
po.previewOptions.url = po.url("previewCsvValue");
|
||||
|
|
|
@ -133,9 +133,7 @@ readonly 是否只读操作,允许为null
|
|||
po.element("#${pageId}-forceXls-${((dataSet.forceXls)!true)?string('true', 'false')}").click();
|
||||
po.initWorkspaceHeight();
|
||||
po.initWorkspaceTabs(true);
|
||||
po.initDataSetPropertiesTable(po.dataSetProperties);
|
||||
po.initDataSetParamsTable(po.dataSetParams);
|
||||
po.initPreviewParamValuePanel();
|
||||
po.initParamPropertyDataFormat(po.dataSetParams, po.dataSetProperties);
|
||||
po.initNameRowOperation(${(dataSet.nameRow)!"1"});
|
||||
|
||||
po.initDataSetFileInput(po.url("uploadFile"), "${((dataSet.fileSourceType)!'')?js_string?no_esc}", ${isAdd?string("true", "false")});
|
||||
|
@ -180,12 +178,13 @@ readonly 是否只读操作,允许为null
|
|||
var pd = po.previewOptions.data.dataSet;
|
||||
var dataSetResDirectory = (pd.dataSetResDirectory || {});
|
||||
|
||||
return (pd.fileSourceType != fileSourceType)
|
||||
|| (po.isFileSourceTypeUpload(fileSourceType) && pd.fileName != fileName)
|
||||
|| (po.isFileSourceTypeServer(fileSourceType) && (dataSetResDirectory.id != dataSetResDirectoryId || pd.dataSetResFileName != dataSetResFileName))
|
||||
|| (pd.sheetIndex != sheetIndex)
|
||||
|| (pd.nameRow != nameRow) || (pd.dataRowExp != dataRowExp)
|
||||
|| (pd.dataColumnExp != dataColumnExp) || (pd.forceXls != forceXls);
|
||||
return ((pd.fileSourceType != fileSourceType)
|
||||
|| (po.isFileSourceTypeUpload(fileSourceType) && pd.fileName != fileName)
|
||||
|| (po.isFileSourceTypeServer(fileSourceType) && (dataSetResDirectory.id != dataSetResDirectoryId || pd.dataSetResFileName != dataSetResFileName))
|
||||
|| (pd.sheetIndex != sheetIndex)
|
||||
|| (pd.nameRow != nameRow) || (pd.dataRowExp != dataRowExp)
|
||||
|| (pd.dataColumnExp != dataColumnExp) || (pd.forceXls != forceXls)
|
||||
|| po.isPreviewParamPropertyDataFormatModified());
|
||||
};
|
||||
|
||||
po.previewOptions.url = po.url("previewExcel");
|
||||
|
|
|
@ -199,9 +199,7 @@ readonly 是否只读操作,允许为null
|
|||
var selectionRange = currentEditor.getSelectionRange();
|
||||
return (currentEditor.session.getTextRange(selectionRange) || "");
|
||||
};
|
||||
po.initDataSetPropertiesTable(po.dataSetProperties);
|
||||
po.initDataSetParamsTable(po.dataSetParams);
|
||||
po.initPreviewParamValuePanel();
|
||||
po.initParamPropertyDataFormat(po.dataSetParams, po.dataSetProperties);
|
||||
|
||||
po.updatePreviewOptionsData = function()
|
||||
{
|
||||
|
@ -245,10 +243,11 @@ readonly 是否只读操作,允许为null
|
|||
|
||||
var pd = po.previewOptions.data.dataSet;
|
||||
|
||||
return (pd.uri != uri) || (pd.requestMethod != requestMethod) || (pd.requestContentType != requestContentType)
|
||||
return ((pd.uri != uri) || (pd.requestMethod != requestMethod) || (pd.requestContentType != requestContentType)
|
||||
|| (pd.requestContentCharset != requestContentCharset) || (pd.responseContentType != responseContentType)
|
||||
|| (pd.requestContent != requestContent) || (pd.headerContent != headerContent)
|
||||
|| (pd.responseDataJsonPath != responseDataJsonPath);
|
||||
|| (pd.responseDataJsonPath != responseDataJsonPath)
|
||||
|| po.isPreviewParamPropertyDataFormatModified());
|
||||
};
|
||||
|
||||
po.previewOptions.url = po.url("previewHttp");
|
||||
|
@ -264,6 +263,11 @@ readonly 是否只读操作,允许为null
|
|||
if(!this.data.dataSet.uri)
|
||||
return false;
|
||||
};
|
||||
po.previewOptions.error = function(operationMessage)
|
||||
{
|
||||
if(operationMessage && operationMessage.data)
|
||||
return operationMessage.data[1];
|
||||
};
|
||||
|
||||
po.initPreviewOperations();
|
||||
|
||||
|
|
|
@ -87,9 +87,7 @@ readonly 是否只读操作,允许为null
|
|||
po.element("select[name='encoding']").selectmenu({ appendTo : po.element(), classes : { "ui-selectmenu-menu" : "encoding-selectmenu-menu" } });
|
||||
po.initWorkspaceHeight();
|
||||
po.initWorkspaceTabs(true);
|
||||
po.initDataSetPropertiesTable(po.dataSetProperties);
|
||||
po.initDataSetParamsTable(po.dataSetParams);
|
||||
po.initPreviewParamValuePanel();
|
||||
po.initParamPropertyDataFormat(po.dataSetParams, po.dataSetProperties);
|
||||
|
||||
po.initDataSetFileInput(po.url("uploadFile"), "${((dataSet.fileSourceType)!'')?js_string?no_esc}", ${isAdd?string("true", "false")});
|
||||
|
||||
|
@ -127,10 +125,11 @@ readonly 是否只读操作,允许为null
|
|||
var pd = po.previewOptions.data.dataSet;
|
||||
var dataSetResDirectory = (pd.dataSetResDirectory || {});
|
||||
|
||||
return (pd.fileSourceType != fileSourceType)
|
||||
return ((pd.fileSourceType != fileSourceType)
|
||||
|| (po.isFileSourceTypeUpload(fileSourceType) && pd.fileName != fileName)
|
||||
|| (po.isFileSourceTypeServer(fileSourceType) && (dataSetResDirectory.id != dataSetResDirectoryId || pd.dataSetResFileName != dataSetResFileName))
|
||||
|| (pd.dataJsonPath != dataJsonPath) || (pd.encoding != encoding);
|
||||
|| (pd.dataJsonPath != dataJsonPath) || (pd.encoding != encoding)
|
||||
|| po.isPreviewParamPropertyDataFormatModified());
|
||||
};
|
||||
|
||||
po.previewOptions.url = po.url("previewJsonFile");
|
||||
|
|
|
@ -82,9 +82,7 @@ readonly 是否只读操作,允许为null
|
|||
var selectionRange = po.jsonEditor.getSelectionRange();
|
||||
return (po.jsonEditor.session.getTextRange(selectionRange) || "");
|
||||
};
|
||||
po.initDataSetPropertiesTable(po.dataSetProperties);
|
||||
po.initDataSetParamsTable(po.dataSetParams);
|
||||
po.initPreviewParamValuePanel();
|
||||
po.initParamPropertyDataFormat(po.dataSetParams, po.dataSetProperties);
|
||||
|
||||
po.updatePreviewOptionsData = function()
|
||||
{
|
||||
|
@ -107,7 +105,7 @@ readonly 是否只读操作,允许为null
|
|||
|
||||
var pd = po.previewOptions.data.dataSet;
|
||||
|
||||
return (pd.value != value);
|
||||
return (pd.value != value || po.isPreviewParamPropertyDataFormatModified());
|
||||
};
|
||||
|
||||
po.previewOptions.url = po.url("previewJsonValue");
|
||||
|
|
|
@ -119,9 +119,7 @@ readonly 是否只读操作,允许为null
|
|||
var selectionRange = po.sqlEditor.getSelectionRange();
|
||||
return (po.sqlEditor.session.getTextRange(selectionRange) || "");
|
||||
};
|
||||
po.initDataSetPropertiesTable(po.dataSetProperties);
|
||||
po.initDataSetParamsTable(po.dataSetParams);
|
||||
po.initPreviewParamValuePanel();
|
||||
po.initParamPropertyDataFormat(po.dataSetParams, po.dataSetProperties);
|
||||
|
||||
po.updatePreviewOptionsData = function()
|
||||
{
|
||||
|
@ -147,7 +145,7 @@ readonly 是否只读操作,允许为null
|
|||
|
||||
var pd = po.previewOptions.data.dataSet;
|
||||
|
||||
return (pd.sql != sql) || (po.previewOptions.data.schemaId != schemaId);
|
||||
return (pd.sql != sql || po.previewOptions.data.schemaId != schemaId || po.isPreviewParamPropertyDataFormatModified());
|
||||
};
|
||||
|
||||
po.previewOptions.url = po.url("previewSql");
|
||||
|
|
|
@ -37,6 +37,9 @@ DataSetEntity dataSet 允许为null
|
|||
<input type="text" class="resultFetchSizeInput ui-widget ui-widget-content ui-corner-all" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="preview-error-info ui-state-error">
|
||||
<textarea class="ui-widget ui-widget-content"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div id="${pageId}-dataSetParams" class="params-table-wrapper minor-dataTable">
|
||||
<div class="operation">
|
||||
|
|
|
@ -690,7 +690,13 @@ po.previewOptions.url = "...";
|
|||
return po.buildDataSetPropertiesColumns(previewResponse.properties);
|
||||
},
|
||||
//预览请求成功回调函数
|
||||
success: function(previewResponse){}
|
||||
success: function(previewResponse){},
|
||||
//预览出错回调函数,返回非空字符串表明将其显示在错误信息区内
|
||||
error: function(operationMessage, jqXHR)
|
||||
{
|
||||
if(operationMessage && operationMessage.data)
|
||||
return operationMessage.data[1];
|
||||
}
|
||||
};
|
||||
|
||||
po.resultFetchSizeVal = function(val)
|
||||
|
@ -750,9 +756,79 @@ po.previewOptions.url = "...";
|
|||
table.empty();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
po.isPreviewParamPropertyDataFormatModified = function()
|
||||
{
|
||||
var formParams = (po.getFormDataSetParams() || []);
|
||||
var formProperties = (po.getFormDataSetProperties() || []);
|
||||
var formDataFormat = (po.getFormDataFormat() || {});
|
||||
var params = (po.previewOptions.data.dataSet.params || []);
|
||||
var properties = (po.previewOptions.data.dataSet.properties || []);
|
||||
var dataFormat = (po.previewOptions.data.dataSet.dataFormat || {});
|
||||
|
||||
//参数数组大小必须一致,因为不一致有可能影响数据集结果
|
||||
if(formParams.length != params.length)
|
||||
return true;
|
||||
|
||||
for(var i=0; i<formParams.length; i++)
|
||||
{
|
||||
var fp = formParams[i];
|
||||
var p = null;
|
||||
|
||||
for(var j=0; j<params.length; j++)
|
||||
{
|
||||
if(params[j].name == fp.name)
|
||||
p = params[j];
|
||||
}
|
||||
|
||||
if(p == null || fp.name != p.name || fp.type != p.type || fp.required != p.required
|
||||
|| fp.inputType != p.inputType || fp.inputPayload != p.inputPayload)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
//属性数组大小不必一致,因为不一致不一定影响数据集结果
|
||||
for(var i=0; i<formProperties.length; i++)
|
||||
{
|
||||
var fp = formProperties[i];
|
||||
var p = null;
|
||||
|
||||
for(var j=0; j<properties.length; j++)
|
||||
{
|
||||
if(properties[j].name == fp.name)
|
||||
p = properties[j];
|
||||
}
|
||||
|
||||
if(p == null || fp.name != p.name || fp.type != p.type || fp.defaultValue != p.defaultValue)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if(formDataFormat.dateFormat != dataFormat.dateFormat || formDataFormat.timeFormat != dataFormat.timeFormat
|
||||
|| formDataFormat.timestampFormat != dataFormat.timestampFormat || formDataFormat.numberFormat != dataFormat.numberFormat)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
po.initParamPropertyDataFormat = function(params, properties)
|
||||
{
|
||||
po.initDataSetParamsTable(po.dataSetParams);
|
||||
po.initDataSetPropertiesTable(po.dataSetProperties);
|
||||
po.initPreviewParamValuePanel();
|
||||
|
||||
};
|
||||
|
||||
po.initPreviewOperations = function()
|
||||
{
|
||||
po.previewOptions.data.dataSet.params = po.getFormDataSetParams();
|
||||
po.previewOptions.data.dataSet.properties = po.getFormDataSetProperties();
|
||||
po.previewOptions.data.dataSet.dataFormat = po.getFormDataFormat();
|
||||
|
||||
po.element(".preview-result-table-wrapper .preview-button").click(function(event)
|
||||
{
|
||||
var previewValueModified = po.isPreviewValueModified();
|
||||
|
@ -845,6 +921,7 @@ po.previewOptions.url = "...";
|
|||
$(this).button("disable");
|
||||
});
|
||||
|
||||
po.element(".preview-error-info").hide();
|
||||
po.element(".preview-result-foot").hide();
|
||||
|
||||
var table = po.previewResultTableElement();
|
||||
|
@ -865,7 +942,10 @@ po.previewOptions.url = "...";
|
|||
//如果工作区内容已变更才更新属性,防止上次保存后的属性被刷新
|
||||
//属性表单内容为空也更新,比如用户删除了所有属性时
|
||||
if(previewValueModified || !po.hasFormDataSetProperty())
|
||||
{
|
||||
po.updateFormDataSetProperties(previewResponse.properties);
|
||||
po.previewOptions.data.dataSet.properties = po.getFormDataSetProperties();
|
||||
}
|
||||
|
||||
var tableData = (previewResponse.result.data || []);
|
||||
if(!$.isArray(tableData))
|
||||
|
@ -928,9 +1008,17 @@ po.previewOptions.url = "...";
|
|||
|
||||
po.previewOptions.success(previewResponse);
|
||||
},
|
||||
error: function()
|
||||
error: function(jqXHR)
|
||||
{
|
||||
po.previewSuccess(false);
|
||||
|
||||
var errorInfo = po.previewOptions.error(jqXHR.responseJSON, jqXHR);
|
||||
|
||||
if(errorInfo)
|
||||
{
|
||||
po.element(".preview-error-info textarea").val(errorInfo);
|
||||
po.element(".preview-error-info").show();
|
||||
}
|
||||
},
|
||||
complete: function()
|
||||
{
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
<#include "include/html_doctype.ftl">
|
||||
<html>
|
||||
<head>
|
||||
<meta dg-page-name="error" />
|
||||
<#include "include/html_head.ftl">
|
||||
<title><#include "include/html_title_app_name.ftl"><@spring.message code='error.errorOccure' /></title>
|
||||
</head>
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
<#include "include/html_doctype.ftl">
|
||||
<html>
|
||||
<head>
|
||||
<meta dg-page-name="login" />
|
||||
<#include "include/html_head.ftl">
|
||||
${detectNewVersionScript?no_esc}
|
||||
<title><#include "include/html_title_app_name.ftl"><@spring.message code='login.login' /></title>
|
||||
|
|
|
@ -0,0 +1,172 @@
|
|||
<#--
|
||||
*
|
||||
* Copyright 2018 datagear.tech
|
||||
*
|
||||
* Licensed under the LGPLv3 license:
|
||||
* http://www.gnu.org/licenses/lgpl-3.0.html
|
||||
*
|
||||
-->
|
||||
<#include "../include/import_global.ftl">
|
||||
<#include "../include/html_doctype.ftl">
|
||||
<#--
|
||||
titleMessageKey 标题标签I18N关键字,不允许null
|
||||
formAction 表单提交action,允许为null
|
||||
-->
|
||||
<#assign formAction=(formAction!'#')>
|
||||
<html>
|
||||
<head>
|
||||
<#include "../include/html_head.ftl">
|
||||
<title><#include "../include/html_title_app_name.ftl"><@spring.message code='${titleMessageKey}' /></title>
|
||||
</head>
|
||||
<body>
|
||||
<#include "../include/page_js_obj.ftl" >
|
||||
<div id="${pageId}" class="page-form page-form-user-delete">
|
||||
<form id="${pageId}-form" action="${contextPath}/user/${formAction}" method="POST">
|
||||
<div class="form-head"></div>
|
||||
<div class="form-content">
|
||||
<div class="form-item">
|
||||
<div class="form-item-label">
|
||||
<label><@spring.message code='user.name' /></label>
|
||||
</div>
|
||||
<div class="form-item-value">
|
||||
<div class="delete-users ui-widget ui-widget-content input minor-list deletable-list">
|
||||
</div>
|
||||
<input type="text" name="deleteUserPlaceholder" style="display:none;" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-item">
|
||||
<div class="form-item-label">
|
||||
<label title="<@spring.message code='user.migrateDataToUser.desc' />">
|
||||
<@spring.message code='user.migrateDataToUser' />
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-item-value">
|
||||
<input type="text" name="migrateUserName" value="" class="ui-widget ui-widget-content" readonly="readonly" />
|
||||
<input type="hidden" name="migrateToId" value="" />
|
||||
<button class="selectUserBtn" type="button"><@spring.message code='select' /></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-foot" style="text-align:center;">
|
||||
<input type="submit" value="<@spring.message code='delete' />" class="danger" />
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<#include "../include/page_obj_form.ftl">
|
||||
<script type="text/javascript">
|
||||
(function(po)
|
||||
{
|
||||
po.deleteUsers = <@writeJson var=deleteUsers />;
|
||||
|
||||
$.initButtons(po.element());
|
||||
|
||||
po.url = function(action)
|
||||
{
|
||||
return "${contextPath}/user/" + action;
|
||||
};
|
||||
|
||||
po.element(".delete-users").on("click", ".delete-icon", function()
|
||||
{
|
||||
$(this).closest(".minor-list-item").remove();
|
||||
});
|
||||
|
||||
po.renderUsers = function(roles)
|
||||
{
|
||||
roles = (roles || []);
|
||||
var $parent = po.element(".delete-users");
|
||||
|
||||
for(var i=0; i<roles.length; i++)
|
||||
po.renderUser($parent, roles[i]);
|
||||
}
|
||||
|
||||
po.renderUser = function($parent, user)
|
||||
{
|
||||
var $item = $("<div class='minor-list-item ui-widget ui-widget-content ui-corner-all' />").appendTo($parent);
|
||||
$("<input type='hidden' class='deleteUserIds' name='ids[]' />").attr("value", user.id).appendTo($item);
|
||||
|
||||
$("<span class='delete-icon ui-icon ui-icon-close' title='<@spring.message code='delete' />' />").appendTo($item);
|
||||
|
||||
$("<div class='item-content' />").text(user.nameLabel).appendTo($item);
|
||||
};
|
||||
|
||||
po.element(".selectUserBtn").click(function()
|
||||
{
|
||||
var options =
|
||||
{
|
||||
pageParam :
|
||||
{
|
||||
select : function(user)
|
||||
{
|
||||
po.element("input[name='migrateToId']").val(user.id);
|
||||
po.element("input[name='migrateUserName']").val(user.nameLabel);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
$.setGridPageHeightOption(options);
|
||||
|
||||
po.open("${contextPath}/user/select", options);
|
||||
});
|
||||
|
||||
$.validator.addMethod("deleteUserIdRequired", function(value, element)
|
||||
{
|
||||
var $du = po.element(".deleteUserIds");
|
||||
return ($du.length > 0);
|
||||
});
|
||||
|
||||
$.validator.addMethod("migrateToUserIdIllegal", function(value, element)
|
||||
{
|
||||
var $du = po.element(".deleteUserIds");
|
||||
var mu = po.element("input[name='migrateToId']").val();
|
||||
|
||||
for(var i=0; i<$du.length; i++)
|
||||
{
|
||||
if(mu == $($du[i]).val())
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
po.form().validate(
|
||||
{
|
||||
ignore : "",
|
||||
rules :
|
||||
{
|
||||
deleteUserPlaceholder : "deleteUserIdRequired",
|
||||
migrateUserName : { "required": true, "migrateToUserIdIllegal": true }
|
||||
},
|
||||
messages :
|
||||
{
|
||||
deleteUserPlaceholder : "<@spring.message code='validation.required' />",
|
||||
migrateUserName :
|
||||
{
|
||||
"required": "<@spring.message code='validation.required' />",
|
||||
"migrateToUserIdIllegal": "<@spring.message code='user.validation.migrateToUserIdIllegal' />"
|
||||
}
|
||||
},
|
||||
submitHandler : function(form)
|
||||
{
|
||||
var data = $.formToJson(form, ["deleteUserPlaceholder", "migrateUserName"]);
|
||||
|
||||
$.ajaxJson($(form).attr("action"),
|
||||
{
|
||||
data: data,
|
||||
success : function(response)
|
||||
{
|
||||
po.pageParamCallAfterSave(true, response.data);
|
||||
}
|
||||
});
|
||||
},
|
||||
errorPlacement : function(error, element)
|
||||
{
|
||||
error.appendTo(element.closest(".form-item-value"));
|
||||
}
|
||||
});
|
||||
|
||||
po.renderUsers(po.deleteUsers);
|
||||
})
|
||||
(${pageId});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -34,7 +34,7 @@ readonly 是否只读操作,允许为null
|
|||
<label><@spring.message code='user.name' /></label>
|
||||
</div>
|
||||
<div class="form-item-value">
|
||||
<input type="text" name="name" value="${(user.name)!''}" class="ui-widget ui-widget-content" />
|
||||
<input type="text" name="name" value="${(user.name)!''}" class="ui-widget ui-widget-content" autocomplete="off" />
|
||||
</div>
|
||||
</div>
|
||||
<#if !readonly>
|
||||
|
@ -60,7 +60,7 @@ readonly 是否只读操作,允许为null
|
|||
<label><@spring.message code='user.realName' /></label>
|
||||
</div>
|
||||
<div class="form-item-value">
|
||||
<input type="text" name="realName" value="${(user.realName)!''}" class="ui-widget ui-widget-content" />
|
||||
<input type="text" name="realName" value="${(user.realName)!''}" class="ui-widget ui-widget-content" autocomplete="off" />
|
||||
</div>
|
||||
</div>
|
||||
<#if !disableRoles>
|
||||
|
|
|
@ -114,7 +114,12 @@ boolean readonly 是否只读操作,默认为false
|
|||
{
|
||||
po.executeOnSelects(function(rows)
|
||||
{
|
||||
po.confirmDeleteEntities(po.url("delete"), rows);
|
||||
var data = $.getPropertyParamString(rows, "id");
|
||||
|
||||
po.open(po.url("delete"),
|
||||
{
|
||||
data : data
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
|
4
pom.xml
4
pom.xml
|
@ -4,7 +4,7 @@
|
|||
|
||||
<groupId>org.datagear</groupId>
|
||||
<artifactId>datagear</artifactId>
|
||||
<version>2.8.0</version>
|
||||
<version>2.9.0</version>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<name>datagear</name>
|
||||
|
@ -13,7 +13,7 @@
|
|||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<java.version>1.8</java.version>
|
||||
<springboot.version>2.4.6</springboot.version>
|
||||
<springboot.version>2.4.10</springboot.version>
|
||||
<javax.json.version>1.0.4</javax.json.version>
|
||||
<commons-csv.version>1.4</commons-csv.version>
|
||||
<poi.version>3.17</poi.version>
|
||||
|
|
Loading…
Reference in New Issue