提交 b57e71ce authored 作者: taojinlong's avatar taojinlong

Merge branch 'dev' into pr@dev@oracle

......@@ -355,7 +355,7 @@
https://github.com/dataease/dataease-plugins-->
<dependency>
<groupId>io.dataease</groupId>
<artifactId>dataease-plugin-xpack</artifactId>
<artifactId>dataease-plugin-interface</artifactId>
<version>1.0</version>
</dependency>
......
......@@ -2,9 +2,18 @@ package io.dataease.base.mapper.ext;
import io.dataease.controller.request.chart.ChartViewRequest;
import io.dataease.dto.chart.ChartViewDTO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import java.util.List;
@Mapper
public interface ExtChartViewMapper {
List<ChartViewDTO> search(ChartViewRequest request);
void chartCopy(@Param("newChartId")String newChartId,@Param("oldChartId")String oldChartId);
@Select("select id from chart_view where table_id = #{tableId}")
List<String> allViewIds(@Param("tableId") String tableId);
}
......@@ -27,4 +27,45 @@
</select>
<insert id="chartCopy">
INSERT INTO chart_view (
`id`,
`name`,
`scene_id`,
`table_id`,
`type`,
`title`,
`x_axis`,
`y_axis`,
`custom_attr`,
`custom_style`,
`custom_filter`,
`create_by`,
`create_time`,
`update_time`,
`snapshot`,
`style_priority`
) SELECT
#{newChartId},
GET_CHART_VIEW_COPY_NAME ( #{oldChartId} ),
`scene_id`,
`table_id`,
`type`,
`title`,
`x_axis`,
`y_axis`,
`custom_attr`,
`custom_style`,
`custom_filter`,
`create_by`,
`create_time`,
`update_time`,
`snapshot`,
`style_priority`
FROM
chart_view
WHERE
id = #{oldChartId}
</insert>
</mapper>
package io.dataease.commons.constants;
public class JdbcConstants {
public final static String VIEW_CACHE_KEY = "view_cache";
}
......@@ -55,4 +55,9 @@ public class ChartViewController {
public Map<String, Object> chartDetail(@PathVariable String id) {
return chartViewService.getChartDetail(id);
}
@PostMapping("chartCopy/{id}")
public String chartCopy(@PathVariable String id) {
return chartViewService.chartCopy(id);
}
}
......@@ -11,7 +11,6 @@ import io.dataease.datasource.request.DatasourceRequest;
import io.dataease.exception.DataEaseException;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import java.beans.PropertyVetoException;
import java.sql.*;
import java.util.*;
......@@ -23,14 +22,29 @@ public class JdbcProvider extends DatasourceProvider {
private static int initPoolSize = 1;
private static int maxConnections = 1;
/**
* 增加缓存机制 key 由 'provider_sql_' dsr.datasource.id dsr.table dsr.query共4部分组成,命中则使用缓存直接返回不再执行sql逻辑
* @param dsr
* @return
* @throws Exception
*/
/**
* 这里使用声明式缓存不是很妥当
* 改为chartViewService中使用编程式缓存
@Cacheable(
value = JdbcConstants.JDBC_PROVIDER_KEY,
key = "'provider_sql_' + #dsr.datasource.id + '_' + #dsr.table + '_' + #dsr.query",
condition = "#dsr.pageSize == null || #dsr.pageSize == 0L"
)
*/
@Override
public List<String[]> getData(DatasourceRequest datasourceRequest) throws Exception {
public List<String[]> getData(DatasourceRequest dsr) throws Exception {
List<String[]> list = new LinkedList<>();
Connection connection = null;
try {
connection = getConnectionFromPool(datasourceRequest);
connection = getConnectionFromPool(dsr);
Statement stat = connection.createStatement();
ResultSet rs = stat.executeQuery(datasourceRequest.getQuery());
ResultSet rs = stat.executeQuery(dsr.getQuery());
list = fetchResult(rs);
} catch (SQLException e) {
DataEaseException.throwException(e);
......
......@@ -24,18 +24,19 @@ public class CacheUtils {
return element.getObjectValue();
}
private static void put(String cacheName, Object key, Object value, Integer ttl, Integer tti) {
public static void put(String cacheName, Object key, Object value, Integer ttl, Integer tti) {
Element e = new Element(key, value);
//不设置则使用xml配置
if (ttl != null)
if (ttl != null) {
e.setEternal(false);
e.setTimeToLive(ttl);
}
if (tti != null)
e.setTimeToIdle(tti);
cache(cacheName).put(e);
}
private static boolean remove(String cacheName, Object key) {
public static boolean remove(String cacheName, Object key) {
return cache(cacheName).remove(key);
}
......
......@@ -237,7 +237,7 @@ public class DorisQueryProvider extends QueryProvider {
String filterSql = MessageFormat.format("SELECT * FROM {0} WHERE 1=1 {1} ORDER BY {2}",
"(" + sql + ") AS tmp",
StringUtils.join(resultFilter, " "),
StringUtils.join(yOrder, ","));
ObjectUtils.isNotEmpty(yOrder) ? StringUtils.join(yOrder, ",") : "null");
return filterSql;
}
}
......@@ -318,7 +318,7 @@ public class DorisQueryProvider extends QueryProvider {
String filterSql = MessageFormat.format("SELECT * FROM {0} WHERE 1=1 {1} ORDER BY {2}",
"(" + sql + ") AS tmp",
StringUtils.join(resultFilter, " "),
StringUtils.join(order, ","));
ObjectUtils.isNotEmpty(order) ? StringUtils.join(order, ",") : "null");
return filterSql;
}
}
......
......@@ -245,7 +245,7 @@ public class MysqlQueryProvider extends QueryProvider {
String filterSql = MessageFormat.format("SELECT * FROM {0} WHERE 1=1 {1} ORDER BY {2}",
"(" + sql + ") AS tmp",
StringUtils.join(resultFilter, " "),
StringUtils.join(yOrder, ","));
ObjectUtils.isNotEmpty(yOrder) ? StringUtils.join(yOrder, ",") : "null");
return filterSql;
}
}
......@@ -326,7 +326,7 @@ public class MysqlQueryProvider extends QueryProvider {
String filterSql = MessageFormat.format("SELECT * FROM {0} WHERE 1=1 {1} ORDER BY {2}",
"(" + sql + ") AS tmp",
StringUtils.join(resultFilter, " "),
StringUtils.join(order, ","));
ObjectUtils.isNotEmpty(order) ? StringUtils.join(order, ",") : "null");
return filterSql;
}
}
......
......@@ -6,6 +6,7 @@ import io.dataease.base.domain.*;
import io.dataease.base.mapper.ChartViewMapper;
import io.dataease.base.mapper.ext.ExtChartGroupMapper;
import io.dataease.base.mapper.ext.ExtChartViewMapper;
import io.dataease.commons.constants.JdbcConstants;
import io.dataease.commons.utils.AuthUtils;
import io.dataease.commons.utils.BeanUtils;
import io.dataease.commons.utils.CommonBeanFactory;
......@@ -20,6 +21,7 @@ import io.dataease.datasource.service.DatasourceService;
import io.dataease.dto.chart.*;
import io.dataease.dto.dataset.DataTableInfoDTO;
import io.dataease.i18n.Translator;
import io.dataease.listener.util.CacheUtils;
import io.dataease.provider.QueryProvider;
import io.dataease.service.dataset.DataSetTableFieldsService;
import io.dataease.service.dataset.DataSetTableService;
......@@ -32,6 +34,7 @@ import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.concurrent.locks.ReentrantLock;
import java.util.stream.Collectors;
/**
......@@ -53,6 +56,9 @@ public class ChartViewService {
@Resource
private ExtChartGroupMapper extChartGroupMapper;
//默认使用非公平
private ReentrantLock lock = new ReentrantLock();
public ChartViewWithBLOBs save(ChartViewWithBLOBs chartView) {
checkName(chartView);
long timestamp = System.currentTimeMillis();
......@@ -65,6 +71,10 @@ public class ChartViewService {
chartView.setUpdateTime(timestamp);
chartViewMapper.insertSelective(chartView);
}
Optional.ofNullable(chartView.getId()).ifPresent(id -> {
CacheUtils.remove(JdbcConstants.VIEW_CACHE_KEY, id);
});
return chartView;
}
......@@ -188,6 +198,17 @@ public class ChartViewService {
}
}
data = datasourceProvider.getData(datasourceRequest);
/**
* 直连不实用缓存
String key = "provider_sql_"+datasourceRequest.getDatasource().getId() + "_" + datasourceRequest.getTable() + "_" +datasourceRequest.getQuery();
Object cache;
if ((cache = CacheUtils.get(JdbcConstants.JDBC_PROVIDER_KEY, key)) == null) {
data = datasourceProvider.getData(datasourceRequest);
CacheUtils.put(JdbcConstants.JDBC_PROVIDER_KEY,key ,data, null, null);
}else {
data = (List<String[]>) cache;
}
*/
} else if (table.getMode() == 1) {// 抽取
// 连接doris,构建doris数据源查询
Datasource ds = (Datasource) CommonBeanFactory.getBean("DorisDatasource");
......@@ -202,7 +223,23 @@ public class ChartViewService {
} else {
datasourceRequest.setQuery(qp.getSQL(tableName, xAxis, yAxis, customFilter, extFilterList));
}
data = datasourceProvider.getData(datasourceRequest);
/*// 定时抽取使用缓存
Object cache;
// 仪表板有参数不实用缓存
if (CollectionUtils.isNotEmpty(requestList.getFilter())) {
data = datasourceProvider.getData(datasourceRequest);
}
// 仪表板无参数 且 未缓存过该视图 则查询后缓存
else if ((cache = CacheUtils.get(JdbcConstants.VIEW_CACHE_KEY, id)) == null) {
lock.lock();
data = datasourceProvider.getData(datasourceRequest);
CacheUtils.put(JdbcConstants.VIEW_CACHE_KEY, id, data, null, null);
}
// 仪表板有缓存 使用缓存
else {
data = (List<String[]>) cache;
}*/
data = cacheViewData(datasourceProvider, datasourceRequest, id);
}
if (StringUtils.containsIgnoreCase(view.getType(), "pie") && data.size() > 1000) {
data = data.subList(0, 1000);
......@@ -269,6 +306,35 @@ public class ChartViewService {
return dto;
}
/**
* 避免缓存击穿
* 虽然流量不一定能够达到击穿的水平
* @param datasourceProvider
* @param datasourceRequest
* @param viewId
* @return
* @throws Exception
*/
public List<String[]> cacheViewData(DatasourceProvider datasourceProvider, DatasourceRequest datasourceRequest, String viewId) throws Exception{
List<String[]> result ;
Object cache = CacheUtils.get(JdbcConstants.VIEW_CACHE_KEY, viewId);
if (cache == null) {
if (lock.tryLock()) {// 获取锁成功
result = datasourceProvider.getData(datasourceRequest);
if (result != null) {
CacheUtils.put(JdbcConstants.VIEW_CACHE_KEY, viewId, result, null, null);
}
lock.unlock();
}else {//获取锁失败
Thread.sleep(100);//避免CAS自旋频率过大 占用cpu资源过高
result = cacheViewData(datasourceProvider, datasourceRequest, viewId);
}
}else {
result = (List<String[]>)cache;
}
return result;
}
private void checkName(ChartViewWithBLOBs chartView) {
// if (StringUtils.isEmpty(chartView.getId())) {
// return;
......@@ -310,4 +376,10 @@ public class ChartViewService {
public ChartViewWithBLOBs findOne(String id) {
return chartViewMapper.selectByPrimaryKey(id);
}
public String chartCopy(String id) {
String newChartId = UUID.randomUUID().toString();
extChartViewMapper.chartCopy(newChartId,id);
return newChartId;
}
}
......@@ -5,11 +5,14 @@ import io.dataease.base.domain.*;
import io.dataease.base.mapper.DatasetTableMapper;
import io.dataease.base.mapper.DatasetTableTaskMapper;
import io.dataease.base.mapper.DatasourceMapper;
import io.dataease.base.mapper.ext.ExtChartViewMapper;
import io.dataease.commons.constants.JdbcConstants;
import io.dataease.commons.constants.JobStatus;
import io.dataease.commons.constants.ScheduleType;
import io.dataease.commons.constants.UpdateType;
import io.dataease.commons.utils.CommonBeanFactory;
import io.dataease.commons.utils.DorisTableUtils;
import io.dataease.commons.utils.HttpClientUtil;
import io.dataease.commons.utils.LogUtil;
import io.dataease.datasource.constants.DatasourceTypes;
import io.dataease.datasource.dto.*;
......@@ -19,6 +22,7 @@ import io.dataease.datasource.provider.ProviderFactory;
import io.dataease.datasource.request.DatasourceRequest;
import io.dataease.dto.dataset.DataTableInfoDTO;
import io.dataease.exception.DataEaseException;
import io.dataease.listener.util.CacheUtils;
import io.dataease.provider.QueryProvider;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.io.FileUtils;
......@@ -27,6 +31,7 @@ import org.apache.commons.lang3.exception.ExceptionUtils;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFSheet;
......@@ -59,6 +64,7 @@ import org.pentaho.di.trans.steps.userdefinedjavaclass.UserDefinedJavaClassDef;
import org.pentaho.di.trans.steps.userdefinedjavaclass.UserDefinedJavaClassMeta;
import org.pentaho.di.www.SlaveServerJobStatus;
import org.quartz.JobExecutionContext;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
......@@ -93,6 +99,9 @@ public class ExtractDataService {
@Resource
private DatasetTableTaskMapper datasetTableTaskMapper;
@Resource
private ExtChartViewMapper extChartViewMapper;
private static String lastUpdateTime = "${__last_update_time__}";
private static String currentUpdateTime = "${__current_update_time__}";
private static String separator = "|DE|";
......@@ -274,7 +283,15 @@ public class ExtractDataService {
}
}
break;
}
}
//侵入式清除下属视图缓存
List<String> viewIds = extChartViewMapper.allViewIds(datasetTableId);
if (CollectionUtils.isNotEmpty(viewIds)){
viewIds.forEach(viewId -> {
CacheUtils.remove(JdbcConstants.VIEW_CACHE_KEY, viewId);
});
}
}
private void updateTableStatus(String datasetTableId, DatasetTable datasetTable, JobStatus completed, Long execTime) {
......@@ -840,16 +857,19 @@ public class ExtractDataService {
}
public boolean isKettleRunning() {
try {
if (!InetAddress.getByName(carte).isReachable(1000)) {
return false;
}
}catch (Exception e){
return false;
}
HttpGet getMethod = new HttpGet("http://" + carte + ":" + port);
HttpClientManager.HttpClientBuilderFacade clientBuilder = HttpClientManager.getInstance().createBuilder();
clientBuilder.setConnectionTimeout(1);
clientBuilder.setCredentials(user, passwd);
CloseableHttpClient httpClient = clientBuilder.build();
try {
if (!InetAddress.getByName(carte).isReachable(1000)) {
return false;
}
HttpClient httpClient;
HttpGet getMethod = new HttpGet("http://" + carte + ":" + port);
HttpClientManager.HttpClientBuilderFacade clientBuilder = HttpClientManager.getInstance().createBuilder();
clientBuilder.setConnectionTimeout(1);
clientBuilder.setCredentials(user, passwd);
httpClient = clientBuilder.build();
HttpResponse httpResponse = httpClient.execute(getMethod);
int statusCode = httpResponse.getStatusLine().getStatusCode();
if (statusCode != -1 && statusCode < 400) {
......@@ -859,6 +879,12 @@ public class ExtractDataService {
}
} catch (Exception e) {
return false;
}finally {
try {
httpClient.close();
} catch (Exception e) {
LoggerFactory.getLogger(HttpClientUtil.class).error("HttpClient关闭连接失败", e);
}
}
}
......
DROP FUNCTION IF EXISTS `GET_CHART_VIEW_COPY_NAME`;
delimiter ;;
CREATE DEFINER=`root`@`%` FUNCTION `GET_CHART_VIEW_COPY_NAME`(chartId varchar(255)) RETURNS varchar(255) CHARSET utf8
READS SQL DATA
BEGIN
DECLARE chartName varchar(255);
DECLARE pid varchar(255);
DECLARE regexpInfo varchar(255);
DECLARE chartNameCount INTEGER;
select `name` ,`scene_id` into chartName, pid from chart_view where id =chartId;
set regexpInfo = concat('^',chartName,'-copy','\\(([0-9])+\\)$');
select (count(1)+1) into chartNameCount from chart_view where name REGEXP regexpInfo;
RETURN concat(chartName,'-copy(',chartNameCount,')');
END
;;
delimiter ;
......@@ -82,5 +82,17 @@
<cacheEventListenerFactory class="io.dataease.listener.LicCacheEventListener" />
</cache>
<cache
name="jdbc_provider_cache"
eternal="false"
maxElementsInMemory="100"
maxElementsOnDisk="10000"
overflowToDisk="true"
diskPersistent="true"
timeToIdleSeconds="28800"
timeToLiveSeconds="86400"
memoryStoreEvictionPolicy="LRU"
/>
</ehcache>
\ No newline at end of file
......@@ -27,3 +27,11 @@ export function getChartTree(data) {
data
})
}
export function chartCopy(id) {
return request({
url: '/chart/view/chartCopy/' + id,
method: 'post',
loading: true
})
}
......@@ -4,7 +4,7 @@
<template v-if="curComponent">
<template v-if="!curComponent.isLock">
<li v-if="editFilter.includes(curComponent.type)" @click="edit"> {{ $t('panel.edit') }}</li>
<!-- <li @click="copy"> {{ $t('panel.copy') }}</li>-->
<li @click="copy"> {{ $t('panel.copy') }}</li>
<li @click="paste"> {{ $t('panel.paste') }}</li>
<li @click="cut"> {{ $t('panel.cut') }}</li>
<li @click="deleteComponent"> {{ $t('panel.delete') }}</li>
......
......@@ -2,6 +2,7 @@ import store from '@/store/index'
import toast from '@/components/canvas/utils/toast'
import generateID from '@/components/canvas/utils/generateID'
import { deepCopy } from '@/components/canvas/utils/utils'
import { chartCopy } from '@/api/chart/chart'
export default {
state: {
......@@ -36,7 +37,18 @@ export default {
}
data.id = generateID()
store.commit('addComponent', { component: deepCopy(data) })
// 如果是用户视图 测先进行底层复制
debugger
if (data.type === 'view') {
chartCopy(data.propValue.viewId).then(res => {
const newView = deepCopy(data)
newView.propValue.viewId = res.data
store.commit('addComponent', { component: newView })
})
} else {
store.commit('addComponent', { component: deepCopy(data) })
}
if (state.isCut) {
state.copyData = null
}
......
......@@ -720,7 +720,21 @@ export default {
chart_error_tips: 'Please contact admin ',
title_cannot_empty: 'Title can not be empty',
table_title_height: 'Table header height',
table_item_height: 'Table row height'
table_item_height: 'Table row height',
axis_show: 'Axis Show',
axis_color: 'Axis Color',
axis_width: 'Axis Width',
axis_type: 'Axis Type',
axis_type_solid: 'Solid',
axis_type_dashed: 'Dashed',
axis_type_dotted: 'Dotted',
axis_label_show: 'Label Show',
axis_label_color: 'Label Color',
axis_label_fontsize: 'Label Fontsize',
text_style: 'Font Style',
bolder: 'Bolder',
change_ds: 'Change Dataset',
change_ds_tip: 'Tips:Change Dataset will change fields,you need rebuild chart'
},
dataset: {
sheet_warn: 'There are multiple sheet pages, and the first one is extracted by default',
......
......@@ -762,7 +762,21 @@ export default {
chart_error_tips: '如有疑問請聯系管理員',
title_cannot_empty: '標題不能為空',
table_title_height: '表頭行高',
table_item_height: '表格行高'
table_item_height: '表格行高',
axis_show: '軸線顯示',
axis_color: '軸線顏色',
axis_width: '軸線寬度',
axis_type: '軸線類型',
axis_type_solid: '實線',
axis_type_dashed: '虛線',
axis_type_dotted: '點',
axis_label_show: '標簽顯示',
axis_label_color: '標簽顏色',
axis_label_fontsize: '標簽大小',
text_style: '字體樣式',
bolder: '加粗',
change_ds: '更換數據集',
change_ds_tip: '提示:更換數據集將導致字段發生變化,需重新製作視圖'
},
dataset: {
sheet_warn: '有多個sheet頁面,默認抽取第一個',
......
......@@ -720,7 +720,21 @@ export default {
chart_error_tips: '如有疑问请联系管理员',
title_cannot_empty: '标题不能为空',
table_title_height: '表头行高',
table_item_height: '表格行高'
table_item_height: '表格行高',
axis_show: '轴线显示',
axis_color: '轴线颜色',
axis_width: '轴线宽度',
axis_type: '轴线类型',
axis_type_solid: '实线',
axis_type_dashed: '虚线',
axis_type_dotted: '点',
axis_label_show: '标签显示',
axis_label_color: '标签颜色',
axis_label_fontsize: '标签大小',
text_style: '字体样式',
bolder: '加粗',
change_ds: '更换数据集',
change_ds_tip: '提示:更换数据集将导致字段发生变化,需重新制作视图'
},
dataset: {
sheet_warn: '有多个 Sheet 页,默认抽取第一个',
......
......@@ -16,7 +16,7 @@ const LinkTokenKey = Config.LinkTokenKey
const service = axios.create({
baseURL: process.env.VUE_APP_BASE_API, // url = base url + request url
// withCredentials: true, // send cookies when cross-domain requests
timeout: 10000 // request timeout
timeout: 0 // request timeout
})
// request interceptor
......
......@@ -63,7 +63,8 @@ export const DEFAULT_TITLE_STYLE = {
color: '#303133',
hPosition: 'center',
vPosition: 'top',
isItalic: false
isItalic: false,
isBolder: false
}
export const DEFAULT_LEGEND_STYLE = {
show: true,
......@@ -81,8 +82,19 @@ export const DEFAULT_XAXIS_STYLE = {
position: 'bottom',
name: '',
axisLabel: {
show: true,
color: '#333333',
fontSize: '12',
rotate: 0,
formatter: '{value}'
},
splitLine: {
show: false,
lineStyle: {
color: '#cccccc',
width: 1,
style: 'solid'
}
}
}
export const DEFAULT_YAXIS_STYLE = {
......@@ -90,8 +102,19 @@ export const DEFAULT_YAXIS_STYLE = {
position: 'left',
name: '',
axisLabel: {
show: true,
color: '#333333',
fontSize: '12',
rotate: 0,
formatter: '{value}'
},
splitLine: {
show: true,
lineStyle: {
color: '#cccccc',
width: 1,
style: 'solid'
}
}
}
export const DEFAULT_BACKGROUND_COLOR = {
......
......@@ -11,6 +11,7 @@ export function componentStyle(chart_option, chart) {
style.fontSize = customStyle.text.fontSize
style.color = customStyle.text.color
customStyle.text.isItalic ? style.fontStyle = 'italic' : style.fontStyle = 'normal'
customStyle.text.isBolder ? style.fontWeight = 'bold' : style.fontWeight = 'normal'
chart_option.title.textStyle = style
}
if (customStyle.legend) {
......@@ -26,12 +27,14 @@ export function componentStyle(chart_option, chart) {
chart_option.xAxis.position = customStyle.xAxis.position
chart_option.xAxis.name = customStyle.xAxis.name
chart_option.xAxis.axisLabel = customStyle.xAxis.axisLabel
chart_option.xAxis.splitLine = customStyle.xAxis.splitLine
}
if (customStyle.yAxis && (chart.type.includes('bar') || chart.type.includes('line'))) {
chart_option.yAxis.show = customStyle.yAxis.show
chart_option.yAxis.position = customStyle.yAxis.position
chart_option.yAxis.name = customStyle.yAxis.name
chart_option.yAxis.axisLabel = customStyle.yAxis.axisLabel
chart_option.yAxis.splitLine = customStyle.yAxis.splitLine
}
if (customStyle.background) {
chart_option.backgroundColor = hexColorToRGBA(customStyle.background.color, customStyle.background.alpha)
......
......@@ -44,8 +44,9 @@
<el-radio-button label="bottom">{{ $t('chart.text_pos_bottom') }}</el-radio-button>
</el-radio-group>
</el-form-item>
<el-form-item :label="$t('chart.text_italic')" class="form-item">
<el-form-item :label="$t('chart.text_style')" class="form-item">
<el-checkbox v-model="titleForm.isItalic" @change="changeTitleStyle">{{ $t('chart.italic') }}</el-checkbox>
<el-checkbox v-model="titleForm.isBolder" @change="changeTitleStyle">{{ $t('chart.bolder') }}</el-checkbox>
</el-form-item>
</el-form>
</el-col>
......
......@@ -24,6 +24,40 @@
<el-form-item :label="$t('chart.rotate')" class="form-item form-item-slider">
<el-slider v-model="axisForm.axisLabel.rotate" show-input :show-input-controls="false" :min="-90" :max="90" input-size="mini" @change="changeXAxisStyle" />
</el-form-item>
<el-divider />
<el-form-item :label="$t('chart.axis_show')" class="form-item">
<el-checkbox v-model="axisForm.splitLine.show" @change="changeXAxisStyle">{{ $t('chart.axis_show') }}</el-checkbox>
</el-form-item>
<span v-show="axisForm.splitLine.show">
<el-form-item :label="$t('chart.axis_color')" class="form-item">
<colorPicker v-model="axisForm.splitLine.lineStyle.color" style="margin-top: 6px;cursor: pointer;z-index: 1004;border: solid 1px black" @change="changeXAxisStyle" />
</el-form-item>
<el-form-item :label="$t('chart.axis_width')" class="form-item form-item-slider">
<el-slider v-model="axisForm.splitLine.lineStyle.width" :min="1" :max="10" show-input :show-input-controls="false" input-size="mini" @change="changeXAxisStyle" />
</el-form-item>
<el-form-item :label="$t('chart.axis_type')" class="form-item">
<el-radio-group v-model="axisForm.splitLine.lineStyle.type" size="mini" @change="changeXAxisStyle">
<el-radio-button label="solid">{{ $t('chart.axis_type_solid') }}</el-radio-button>
<el-radio-button label="dashed">{{ $t('chart.axis_type_dashed') }}</el-radio-button>
<el-radio-button label="dotted">{{ $t('chart.axis_type_dotted') }}</el-radio-button>
</el-radio-group>
</el-form-item>
</span>
<el-divider />
<el-form-item :label="$t('chart.axis_label_show')" class="form-item">
<el-checkbox v-model="axisForm.axisLabel.show" @change="changeXAxisStyle">{{ $t('chart.axis_label_show') }}</el-checkbox>
</el-form-item>
<span v-show="axisForm.axisLabel.show">
<el-form-item :label="$t('chart.axis_label_color')" class="form-item">
<colorPicker v-model="axisForm.axisLabel.color" style="margin-top: 6px;cursor: pointer;z-index: 1004;border: solid 1px black" @change="changeXAxisStyle" />
</el-form-item>
<el-form-item :label="$t('chart.axis_label_fontsize')" class="form-item form-item-slider">
<el-select v-model="axisForm.axisLabel.fontSize" :placeholder="$t('chart.axis_label_fontsize')" @change="changeXAxisStyle">
<el-option v-for="option in fontSize" :key="option.value" :label="option.name" :value="option.value" />
</el-select>
</el-form-item>
</span>
<el-divider />
<el-form-item :label="$t('chart.content_formatter')" class="form-item">
<el-input v-model="axisForm.axisLabel.formatter" type="textarea" :autosize="{ minRows: 4, maxRows: 4}" @blur="changeXAxisStyle" />
</el-form-item>
......@@ -58,7 +92,8 @@ export default {
data() {
return {
axisForm: JSON.parse(JSON.stringify(DEFAULT_XAXIS_STYLE)),
isSetting: false
isSetting: false,
fontSize: []
}
},
watch: {
......@@ -74,14 +109,28 @@ export default {
}
if (customStyle.xAxis) {
this.axisForm = customStyle.xAxis
if (!this.axisForm.splitLine) {
this.axisForm.splitLine = JSON.parse(JSON.stringify(DEFAULT_XAXIS_STYLE.splitLine))
}
}
}
}
}
},
mounted() {
this.init()
},
methods: {
init() {
const arr = []
for (let i = 10; i <= 40; i = i + 2) {
arr.push({
name: i + '',
value: i + ''
})
}
this.fontSize = arr
},
changeXAxisStyle() {
if (!this.axisForm.show) {
this.isSetting = false
......@@ -93,6 +142,9 @@ export default {
</script>
<style scoped>
.el-divider--horizontal {
margin: 10px 0
}
.shape-item{
padding: 6px;
border: none;
......
......@@ -24,6 +24,40 @@
<el-form-item :label="$t('chart.rotate')" class="form-item form-item-slider">
<el-slider v-model="axisForm.axisLabel.rotate" show-input :show-input-controls="false" :min="-90" :max="90" input-size="mini" @change="changeYAxisStyle" />
</el-form-item>
<el-divider />
<el-form-item :label="$t('chart.axis_show')" class="form-item">
<el-checkbox v-model="axisForm.splitLine.show" @change="changeYAxisStyle">{{ $t('chart.axis_show') }}</el-checkbox>
</el-form-item>
<span v-show="axisForm.splitLine.show">
<el-form-item :label="$t('chart.axis_color')" class="form-item">
<colorPicker v-model="axisForm.splitLine.lineStyle.color" style="margin-top: 6px;cursor: pointer;z-index: 1004;border: solid 1px black" @change="changeYAxisStyle" />
</el-form-item>
<el-form-item :label="$t('chart.axis_width')" class="form-item form-item-slider">
<el-slider v-model="axisForm.splitLine.lineStyle.width" :min="1" :max="10" show-input :show-input-controls="false" input-size="mini" @change="changeYAxisStyle" />
</el-form-item>
<el-form-item :label="$t('chart.axis_type')" class="form-item">
<el-radio-group v-model="axisForm.splitLine.lineStyle.type" size="mini" @change="changeYAxisStyle">
<el-radio-button label="solid">{{ $t('chart.axis_type_solid') }}</el-radio-button>
<el-radio-button label="dashed">{{ $t('chart.axis_type_dashed') }}</el-radio-button>
<el-radio-button label="dotted">{{ $t('chart.axis_type_dotted') }}</el-radio-button>
</el-radio-group>
</el-form-item>
</span>
<el-divider />
<el-form-item :label="$t('chart.axis_label_show')" class="form-item">
<el-checkbox v-model="axisForm.axisLabel.show" @change="changeYAxisStyle">{{ $t('chart.axis_label_show') }}</el-checkbox>
</el-form-item>
<span v-show="axisForm.axisLabel.show">
<el-form-item :label="$t('chart.axis_label_color')" class="form-item">
<colorPicker v-model="axisForm.axisLabel.color" style="margin-top: 6px;cursor: pointer;z-index: 1004;border: solid 1px black" @change="changeYAxisStyle" />
</el-form-item>
<el-form-item :label="$t('chart.axis_label_fontsize')" class="form-item form-item-slider">
<el-select v-model="axisForm.axisLabel.fontSize" :placeholder="$t('chart.axis_label_fontsize')" @change="changeYAxisStyle">
<el-option v-for="option in fontSize" :key="option.value" :label="option.name" :value="option.value" />
</el-select>
</el-form-item>
</span>
<el-divider />
<el-form-item :label="$t('chart.content_formatter')" class="form-item">
<el-input v-model="axisForm.axisLabel.formatter" type="textarea" :autosize="{ minRows: 4, maxRows: 4}" @blur="changeYAxisStyle" />
</el-form-item>
......@@ -58,7 +92,8 @@ export default {
data() {
return {
axisForm: JSON.parse(JSON.stringify(DEFAULT_YAXIS_STYLE)),
isSetting: false
isSetting: false,
fontSize: []
}
},
watch: {
......@@ -74,14 +109,28 @@ export default {
}
if (customStyle.yAxis) {
this.axisForm = customStyle.yAxis
if (!this.axisForm.splitLine) {
this.axisForm.splitLine = JSON.parse(JSON.stringify(DEFAULT_YAXIS_STYLE.splitLine))
}
}
}
}
}
},
mounted() {
this.init()
},
methods: {
init() {
const arr = []
for (let i = 10; i <= 40; i = i + 2) {
arr.push({
name: i + '',
value: i + ''
})
}
this.fontSize = arr
},
changeYAxisStyle() {
if (!this.axisForm.show) {
this.isSetting = false
......@@ -93,6 +142,9 @@ export default {
</script>
<style scoped>
.el-divider--horizontal {
margin: 10px 0
}
.shape-item{
padding: 6px;
border: none;
......
......@@ -50,7 +50,8 @@ export default {
fontSize: '18px',
color: '#303133',
textAlign: 'left',
fontStyle: 'normal'
fontStyle: 'normal',
fontWeight: 'normal'
},
content_class: {
display: 'flex',
......@@ -136,6 +137,7 @@ export default {
this.title_class.color = customStyle.text.color
this.title_class.textAlign = customStyle.text.hPosition
this.title_class.fontStyle = customStyle.text.isItalic ? 'italic' : 'normal'
this.title_class.fontWeight = customStyle.text.isBolder ? 'bold' : 'normal'
}
if (customStyle.background) {
this.bg_class.background = hexColorToRGBA(customStyle.background.color, customStyle.background.alpha)
......
......@@ -60,7 +60,8 @@ export default {
fontSize: '18px',
color: '#303133',
textAlign: 'left',
fontStyle: 'normal'
fontStyle: 'normal',
fontWeight: 'normal'
},
bg_class: {
background: hexColorToRGBA('#ffffff', 0)
......@@ -175,6 +176,7 @@ export default {
this.title_class.color = customStyle.text.color
this.title_class.textAlign = customStyle.text.hPosition
this.title_class.fontStyle = customStyle.text.isItalic ? 'italic' : 'normal'
this.title_class.fontWeight = customStyle.text.isBolder ? 'bold' : 'normal'
}
if (customStyle.background) {
this.bg_class.background = hexColorToRGBA(customStyle.background.color, customStyle.background.alpha)
......
......@@ -129,9 +129,9 @@
/>
</span>
<el-dropdown-menu slot="dropdown">
<!-- <el-dropdown-item icon="el-icon-edit-outline" :command="beforeClickMore('renameChart',data,node)">-->
<!-- {{ $t('chart.rename') }}-->
<!-- </el-dropdown-item>-->
<el-dropdown-item icon="el-icon-edit-outline" :command="beforeClickMore('renameChart',data,node)">
{{ $t('chart.rename') }}
</el-dropdown-item>
<el-dropdown-item icon="el-icon-right" :command="beforeClickMore('moveDs',data,node)">
{{ $t('dataset.move_to') }}
</el-dropdown-item>
......@@ -544,6 +544,7 @@ export default {
saveTable(view) {
this.$refs['tableForm'].validate((valid) => {
if (valid) {
view.title = view.name
post('/chart/view/save', view).then(response => {
this.closeTable()
this.$message({
......
......@@ -13,6 +13,9 @@
<span slot="reference" style="line-height: 40px;cursor: pointer;">{{ view.name }}</span>
</el-popover>
<span style="float: right;line-height: 40px;">
<el-button size="mini" @click="changeDs">
{{ $t('chart.change_ds') }}
</el-button>
<el-button size="mini" @click="closeEdit">
{{ $t('commons.save') }}
</el-button>
......@@ -208,10 +211,10 @@
<tooltip-selector v-show="!view.type.includes('table') && !view.type.includes('text')" class="attr-selector" :chart="chart" @onTooltipChange="onTooltipChange" />
</el-tab-pane>
<el-tab-pane :label="$t('chart.module_style')" class="padding-lr">
<title-selector class="attr-selector" :chart="chart" @onTextChange="onTextChange" />
<legend-selector v-show="!view.type.includes('table') && !view.type.includes('text')" class="attr-selector" :chart="chart" @onLegendChange="onLegendChange" />
<x-axis-selector v-show="view.type.includes('bar') || view.type.includes('line')" class="attr-selector" :chart="chart" @onChangeXAxisForm="onChangeXAxisForm" />
<y-axis-selector v-show="view.type.includes('bar') || view.type.includes('line')" class="attr-selector" :chart="chart" @onChangeYAxisForm="onChangeYAxisForm" />
<title-selector class="attr-selector" :chart="chart" @onTextChange="onTextChange" />
<legend-selector v-show="!view.type.includes('table') && !view.type.includes('text')" class="attr-selector" :chart="chart" @onLegendChange="onLegendChange" />
<background-color-selector class="attr-selector" :chart="chart" @onChangeBackgroundForm="onChangeBackgroundForm" />
</el-tab-pane>
</el-tabs>
......@@ -330,6 +333,24 @@
<el-button type="primary" size="mini" @click="saveResultFilter">{{ $t('chart.confirm') }}</el-button>
</div>
</el-dialog>
<!--视图更换数据集-->
<el-dialog
v-dialogDrag
:title="$t('chart.change_ds')+'['+table.name+']'"
:visible="selectTableFlag"
:show-close="false"
width="70%"
class="dialog-css"
:destroy-on-close="true"
>
<table-selector @getTable="getTable" />
<span>{{ $t('chart.change_ds_tip') }}</span>
<div slot="footer" class="dialog-footer">
<el-button size="mini" @click="closeChangeChart">{{ $t('chart.cancel') }}</el-button>
<el-button type="primary" size="mini" :disabled="!table.id" @click="changeChart">{{ $t('chart.confirm') }}</el-button>
</div>
</el-dialog>
</el-row>
</template>
......@@ -368,10 +389,11 @@ import DimensionFilterEditor from '../components/filter/DimensionFilterEditor'
import TableNormal from '../components/table/TableNormal'
import LabelNormal from '../components/normal/LabelNormal'
import html2canvas from 'html2canvas'
import TableSelector from './TableSelector'
export default {
name: 'ChartEdit',
components: { ResultFilterEditor, LabelNormal, DimensionFilterEditor, TableNormal, DatasetChartDetail, QuotaFilterEditor, BackgroundColorSelector, XAxisSelector, YAxisSelector, TooltipSelector, LabelSelector, LegendSelector, TitleSelector, SizeSelector, ColorSelector, ChartComponent, QuotaItem, DimensionItem, draggable },
components: { TableSelector, ResultFilterEditor, LabelNormal, DimensionFilterEditor, TableNormal, DatasetChartDetail, QuotaFilterEditor, BackgroundColorSelector, XAxisSelector, YAxisSelector, TooltipSelector, LabelSelector, LegendSelector, TitleSelector, SizeSelector, ColorSelector, ChartComponent, QuotaItem, DimensionItem, draggable },
props: {
param: {
type: Object,
......@@ -430,7 +452,9 @@ export default {
httpRequest: {
status: true,
msg: ''
}
},
selectTableFlag: false,
changeTable: {}
}
},
computed: {
......@@ -556,6 +580,7 @@ export default {
if (needRefreshGroup) {
this.refreshGroup(view)
}
this.closeChangeChart()
})
},
......@@ -628,6 +653,7 @@ export default {
// 从仪表板入口关闭
bus.$emit('PanelSwitchComponent', { name: 'PanelEdit' })
// this.$emit('switchComponent', { name: '' })
this.$success(this.$t('commons.save_success'))
},
getData(id) {
if (id) {
......@@ -930,6 +956,26 @@ export default {
refreshGroup(view) {
this.$emit('saveSuccess', view)
},
getTable(table) {
this.changeTable = JSON.parse(JSON.stringify(table))
},
changeDs() {
this.selectTableFlag = true
},
closeChangeChart() {
this.selectTableFlag = false
},
changeChart() {
this.view.tableId = this.changeTable.id
this.view.xaxis = []
this.view.yaxis = []
this.view.customFilter = []
this.save(true, 'chart', false)
}
}
}
......
......@@ -30,7 +30,7 @@
<el-form-item class="form-item">
<el-input v-model="name" size="mini" :placeholder="$t('commons.name')" />
</el-form-item>
<el-form-item class="form-item">
<el-form-item v-if="!param.tableId" class="form-item">
<el-select v-model="mode" filterable :placeholder="$t('dataset.connect_mode')" size="mini">
<el-option :label="$t('dataset.direct_connect')" value="0" />
<el-option :label="$t('dataset.sync_data')" value="1" :disabled="!kettleRunning" />
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论