refactor: 冲突

This commit is contained in:
taojinlong 2022-11-15 16:07:12 +08:00
commit fa06823e44
277 changed files with 4214 additions and 8461 deletions

View File

@ -118,6 +118,7 @@ public class ShiroServiceImpl implements ShiroService {
filterChainDefinitionMap.put("/api/link/resourceDetail/**", "link");
filterChainDefinitionMap.put("/api/link/viewDetail/**", "link");
filterChainDefinitionMap.put("/api/link/viewLog", "link");
filterChainDefinitionMap.put("/panel/group/exportDetails", ANON);
filterChainDefinitionMap.put("/dataset/field/linkMultFieldValues", "link");
filterChainDefinitionMap.put("/dataset/field/linkMappingFieldValues", "link");

View File

@ -37,6 +37,7 @@ public class SysLogConstants {
UNBIND(17, "OPERATE_TYPE_UNBIND");
private Integer value;
private String name;
OPERATE_TYPE(Integer value, String name) {
this.value = value;
this.name = name;
@ -62,7 +63,7 @@ public class SysLogConstants {
DATASET(2, "SOURCE_TYPE_DATASET"),
PANEL(3, "SOURCE_TYPE_PANEL"),
VIEW(4, "SOURCE_TYPE_VIEW"),
/*LINK(5, "SOURCE_TYPE_LINK"),*/
LINK(5, "SOURCE_TYPE_LINK"),
USER(6, "SOURCE_TYPE_USER"),
DEPT(7, "SOURCE_TYPE_DEPT"),
ROLE(8, "SOURCE_TYPE_ROLE"),

View File

@ -34,14 +34,14 @@ public class DeLogUtils {
DeLogUtils.logService = logService;
}
public static SysLogDTO buildLog(OPERATE_TYPE operatetype, SOURCE_TYPE sourcetype, Object sourceIdValue, Object targetId, SOURCE_TYPE target_type ) {
public static SysLogDTO buildLog(OPERATE_TYPE operatetype, SOURCE_TYPE sourcetype, Object sourceIdValue, Object targetId, SOURCE_TYPE target_type) {
SysLogDTO sysLogDTO = buildLog(operatetype, sourcetype, sourceIdValue, null, targetId, target_type);
if (sourcetype == SysLogConstants.SOURCE_TYPE.DATASOURCE) {
FolderItem folderItem = logManager.dsTypeInfoById(sourceIdValue.toString());
List<FolderItem> items = new ArrayList<>();
items.add(folderItem);
sysLogDTO.setPositions(items);
}else {
} else {
List<FolderItem> parentsAndSelf = logManager.justParents(sourceIdValue.toString(), sourcetype);
sysLogDTO.setPositions(parentsAndSelf);
}
@ -66,7 +66,7 @@ public class DeLogUtils {
return sysLogDTO;
}
public static SysLogDTO buildLog(OPERATE_TYPE operatetype, SOURCE_TYPE sourcetype, Object sourceIdValue, Object positionId, Object targetId, SOURCE_TYPE target_type ) {
public static SysLogDTO buildLog(OPERATE_TYPE operatetype, SOURCE_TYPE sourcetype, Object sourceIdValue, Object positionId, Object targetId, SOURCE_TYPE target_type) {
SysLogDTO sysLogDTO = new SysLogDTO();
sysLogDTO.setOperateType(operatetype.getValue());
sysLogDTO.setSourceType(sourcetype.getValue());
@ -83,14 +83,14 @@ public class DeLogUtils {
List<FolderItem> items = new ArrayList<>();
items.add(folderItem);
sysLogDTO.setPositions(items);
}else {
if(sourcetype == SOURCE_TYPE.DRIVER_FILE){
} else {
if (sourcetype == SOURCE_TYPE.DRIVER_FILE) {
List<FolderItem> parentsAndSelf = logManager.parentsAndSelf(positionId.toString(), SOURCE_TYPE.DRIVER);
sysLogDTO.setPositions(parentsAndSelf);
}else if(sourcetype == SOURCE_TYPE.VIEW){
} else if (sourcetype == SOURCE_TYPE.VIEW || sourcetype == SOURCE_TYPE.LINK) {
List<FolderItem> parentsAndSelf = logManager.parentsAndSelf(positionId.toString(), SOURCE_TYPE.PANEL);
sysLogDTO.setPositions(parentsAndSelf);
}else {
} else {
List<FolderItem> parentsAndSelf = logManager.parentsAndSelf(positionId.toString(), sourcetype);
sysLogDTO.setPositions(parentsAndSelf);
}

View File

@ -0,0 +1,45 @@
package io.dataease.commons.utils;
import org.apache.commons.lang3.StringUtils;
import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;
public class IPUtils {
private static final String HEAD_KEYS = "x-forwarded-for, Proxy-Client-IP, WL-Proxy-Client-IP";
private static final String UNKNOWN = "unknown";
private static final String LOCAL_IP_KEY = "0:0:0:0:0:0:0:1";
private static final String LOCAL_IP_VAL = "127.0.0.1";
public static String get() {
String ipStr = null;
boolean isProxy = false;
HttpServletRequest request = null;
try {
request = ServletUtils.request();
} catch (Exception e) {
LogUtil.error(e.getMessage(), e);
return null;
}
String[] keyArr = HEAD_KEYS.split(",");
for (String key : keyArr) {
String header = request.getHeader(key.trim());
if (StringUtils.isNotBlank(header) && !StringUtils.equalsIgnoreCase(UNKNOWN, header)) {
ipStr = header;
isProxy = true;
break;
}
}
if (!isProxy) {
ipStr = request.getRemoteAddr();
}
ipStr = Arrays.stream(ipStr.split(",")).filter(item -> StringUtils.isNotBlank(item) && !StringUtils.equalsIgnoreCase(UNKNOWN, item.trim())).findFirst().orElse(ipStr);
return StringUtils.equals(LOCAL_IP_KEY, ipStr) ? LOCAL_IP_VAL : ipStr;
}
}

View File

@ -4,12 +4,14 @@ import com.github.xiaoymin.knife4j.annotations.ApiSupport;
import io.dataease.auth.annotation.DePermission;
import io.dataease.commons.constants.DePermissionType;
import io.dataease.controller.request.chart.ChartExtRequest;
import io.dataease.controller.request.panel.PanelViewLogRequest;
import io.dataease.controller.request.panel.link.*;
import io.dataease.dto.panel.link.GenerateDto;
import io.dataease.dto.panel.link.ValidateDto;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.*;
import springfox.documentation.annotations.ApiIgnore;
import java.util.Map;
@ -58,9 +60,15 @@ public interface LinkApi {
@ApiOperation("视图详细信息")
@PostMapping("/viewDetail/{viewId}/{panelId}")
Object viewDetail(@PathVariable("viewId") String viewId, @PathVariable("panelId") String panelId,
@RequestBody ChartExtRequest requestList) throws Exception;
@RequestBody ChartExtRequest requestList) throws Exception;
@ApiOperation("压缩链接")
@PostMapping("/shortUrl")
String shortUrl(@RequestBody Map<String, String> param);
@ApiIgnore
@PostMapping("/viewLog")
void viewLinkLog(@RequestBody LinkViewLogRequest request);
}

View File

@ -3,6 +3,9 @@ package io.dataease.controller.panel.server;
import com.auth0.jwt.JWT;
import com.auth0.jwt.interfaces.DecodedJWT;
import io.dataease.auth.filter.F2CLinkFilter;
import io.dataease.commons.constants.SysLogConstants;
import io.dataease.commons.utils.DeLogUtils;
import io.dataease.plugins.common.base.domain.PanelGroupWithBLOBs;
import io.dataease.plugins.common.base.domain.PanelLink;
import io.dataease.controller.panel.api.LinkApi;
import io.dataease.controller.request.chart.ChartExtRequest;
@ -111,4 +114,19 @@ public class LinkServer implements LinkApi {
String resourceId = param.get("resourceId");
return panelLinkService.getShortUrl(resourceId);
}
@Override
public void viewLinkLog(LinkViewLogRequest request) {
String panelId = request.getPanelId();
Boolean mobile = request.getMobile();
Long userId = request.getUserId();
SysLogConstants.OPERATE_TYPE operateType = SysLogConstants.OPERATE_TYPE.PC_VIEW;
if (ObjectUtils.isNotEmpty(mobile) && mobile) {
operateType = SysLogConstants.OPERATE_TYPE.MB_VIEW;
}
if (ObjectUtils.isEmpty(userId)) return;
PanelGroupWithBLOBs panelGroupWithBLOBs = panelLinkService.resourceInfo(panelId);
String pid = panelGroupWithBLOBs.getPid();
DeLogUtils.save(operateType, SysLogConstants.SOURCE_TYPE.LINK, panelId, pid, userId, SysLogConstants.SOURCE_TYPE.USER);
}
}

View File

@ -0,0 +1,12 @@
package io.dataease.controller.request.panel.link;
import io.dataease.controller.request.panel.PanelViewLogRequest;
import lombok.Data;
import java.io.Serializable;
@Data
public class LinkViewLogRequest extends PanelViewLogRequest implements Serializable {
private Long userId;
}

View File

@ -0,0 +1,24 @@
package io.dataease.controller.sys;
import io.dataease.dto.UserLoginInfoDTO;
import io.dataease.service.SystemInfoService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import springfox.documentation.annotations.ApiIgnore;
import javax.annotation.Resource;
import java.io.IOException;
@ApiIgnore
@RestController
@RequestMapping("systemInfo")
public class SystemInfoController {
@Resource
private SystemInfoService systemInfoService;
@GetMapping("userLoginInfo")
public UserLoginInfoDTO userLoginInfo() throws IOException {
return systemInfoService.getUserLoginInfo();
}
}

View File

@ -22,4 +22,7 @@ public class SysLogGridDTO implements Serializable {
@ApiModelProperty("操作时间")
private Long time;
@ApiModelProperty("IP地址")
private String ip;
}

View File

@ -0,0 +1,25 @@
package io.dataease.dto;
import io.dataease.auth.api.dto.CurrentUserDto;
import lombok.Data;
/**
* Author: wangjiahao
* Date: 2022/11/10
* Description:
*/
@Data
public class UserLoginInfoDTO {
private CurrentUserDto userInfo;
private String ip;
public UserLoginInfoDTO() {
}
public UserLoginInfoDTO(CurrentUserDto userInfo, String ip) {
this.userInfo = userInfo;
this.ip = ip;
}
}

View File

@ -18,12 +18,13 @@ public class VAuthModelDTO extends VAuthModelWithBLOBs implements ITreeBase<VAut
private List<VAuthModelDTO> children;
private long allLeafs = 0l;
private long allLeafs = 0L;
private String innerId;
private Boolean isPlugin = false;
@Override
public String toString(){
return this.getName();
}

View File

@ -2,9 +2,11 @@ package io.dataease.dto.panel;
import io.dataease.dto.chart.ChartViewDTO;
import io.dataease.plugins.common.base.domain.PanelGroupWithBLOBs;
import io.dataease.plugins.common.base.domain.PanelWatermark;
import io.dataease.plugins.common.model.ITreeBase;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.List;
import java.util.Map;
@ -43,4 +45,7 @@ public class PanelGroupDTO extends PanelGroupWithBLOBs implements ITreeBase<Pane
private String requestId;
@ApiModelProperty("数据返回来源")
private String responseSource;
@ApiModelProperty("水印信息")
private PanelWatermark watermarkInfo;
}

View File

@ -1,6 +1,8 @@
package io.dataease.job.sechedule;
import com.fit2cloud.quartz.anno.QuartzScheduled;
import io.dataease.commons.utils.LogUtil;
import io.dataease.service.CleaningRebotService;
import io.dataease.service.datasource.DatasourceService;
import io.dataease.service.dataset.DataSetTableService;
import io.dataease.service.kettle.KettleService;
@ -17,6 +19,9 @@ public class Schedular {
@Resource
private KettleService kettleService;
@Resource
private CleaningRebotService cleaningRebotService;
@QuartzScheduled(cron = "0 0/3 * * * ?")
public void updateDatasetTableStatus() {
dataSetTableService.updateDatasetTableStatus();
@ -32,4 +37,10 @@ public class Schedular {
kettleService.updateKettleStatus();
}
@QuartzScheduled(cron = "0 0 0 ? * *")
public void cheanDisusedData() {
LogUtil.info("start execute clean task...");
cleaningRebotService.execute();
}
}

View File

@ -11,6 +11,7 @@ import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import springfox.documentation.annotations.ApiIgnore;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedInputStream;
import java.io.IOException;
@ -40,20 +41,20 @@ public class PluginCommonServer {
BufferedInputStream bis = null;
InputStream inputStream = null;
OutputStream os = null; //输出流
try{
try {
inputStream = service.vueResource(jsName);
byte[] buffer = new byte[1024];
os = response.getOutputStream();
bis = new BufferedInputStream(inputStream);
int i = bis.read(buffer);
while(i != -1){
while (i != -1) {
os.write(buffer, 0, i);
i = bis.read(buffer);
}
os.flush();
}catch (Exception e) {
} catch (Exception e) {
e.printStackTrace();
}finally {
} finally {
try {
bis.close();
inputStream.close();
@ -69,28 +70,28 @@ public class PluginCommonServer {
@GetMapping("/component/{componentName}")
public void componentInfo(@PathVariable String componentName) {
Map<String, PluginComponentService> beansOfType = SpringContextUtil.getApplicationContext().getBeansOfType(PluginComponentService.class);
beansOfType.values().stream().forEach(service -> {
Map<String, PluginComponentService> beansOfType = SpringContextUtil.getApplicationContext().getBeansOfType(PluginComponentService.class);
beansOfType.values().stream().forEach(service -> {
List<String> components = service.components();
if (components.contains(componentName)) {
HttpServletResponse response = ServletUtils.response();
BufferedInputStream bis = null;
InputStream inputStream = null;
OutputStream os = null; //输出流
try{
try {
inputStream = service.vueResource(componentName);
byte[] buffer = new byte[1024];
os = response.getOutputStream();
bis = new BufferedInputStream(inputStream);
int i = bis.read(buffer);
while(i != -1){
while (i != -1) {
os.write(buffer, 0, i);
i = bis.read(buffer);
}
os.flush();
}catch (Exception e) {
} catch (Exception e) {
e.printStackTrace();
}finally {
} finally {
try {
bis.close();
inputStream.close();
@ -101,7 +102,7 @@ public class PluginCommonServer {
}
return;
}
});
});
}
@GetMapping("/staticInfo/{name}/{suffix}")
@ -115,22 +116,24 @@ public class PluginCommonServer {
BufferedInputStream bis = null;
InputStream inputStream = null;
OutputStream os = null; //输出流
try{
try {
inputStream = service.vueResource(name, suffix);
byte[] buffer = new byte[1024];
os = response.getOutputStream();
bis = new BufferedInputStream(inputStream);
int i = bis.read(buffer);
while(i != -1){
while (i != -1) {
os.write(buffer, 0, i);
i = bis.read(buffer);
}
if (suffix.indexOf("svg") != -1)
response.setContentType("image/svg+xml");
if (suffix.indexOf("png") != -1)
response.setContentType("image/png");
os.flush();
}catch (Exception e) {
} catch (Exception e) {
e.printStackTrace();
}finally {
} finally {
try {
bis.close();
inputStream.close();

View File

@ -0,0 +1,33 @@
package io.dataease.plugins.server;
import io.dataease.plugins.config.SpringContextUtil;
import io.dataease.plugins.xpack.watermark.WatermarkService;
import io.dataease.plugins.xpack.watermark.dto.PanelWatermarkDTO;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.*;
import springfox.documentation.annotations.ApiIgnore;
/**
* Author: wangjiahao
* Date: 2022/11/11
* Description:
*/
@ApiIgnore
@RequestMapping("/plugin/watermark")
@RestController
public class XWatermarkServer {
@ApiOperation("查询水印配置")
@GetMapping("/find")
public PanelWatermarkDTO find() {
WatermarkService userXpackService = SpringContextUtil.getBean(WatermarkService.class);
return userXpackService.getWatermarkInfo();
}
@ApiOperation("保存水印配置")
@PostMapping("/save")
public void save(@RequestBody PanelWatermarkDTO panelWatermark) {
WatermarkService userXpackService = SpringContextUtil.getBean(WatermarkService.class);
userXpackService.saveWatermarkInfo(panelWatermark);
}
}

View File

@ -1,6 +1,7 @@
package io.dataease.service;
import io.dataease.ext.CleaningRebotMapper;
import io.dataease.service.message.SysMsgService;
import io.dataease.service.sys.log.LogService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
@ -20,6 +21,9 @@ public class CleaningRebotService {
@Resource
private LogService logService;
@Resource
private SysMsgService sysMsgService;
public void execute() {
int floatDept = 0;
do {
@ -38,5 +42,6 @@ public class CleaningRebotService {
cleaningRebotMapper.delFloatingCreatorLinkMapping();
}
logService.cleanDisusedLog();
sysMsgService.cleanDisusedMsg();
}
}

View File

@ -0,0 +1,16 @@
package io.dataease.service;
import io.dataease.commons.utils.AuthUtils;
import io.dataease.commons.utils.IPUtils;
import io.dataease.dto.UserLoginInfoDTO;
import org.springframework.stereotype.Service;
@Service
public class SystemInfoService {
public UserLoginInfoDTO getUserLoginInfo() {
return new UserLoginInfoDTO(AuthUtils.getUser(), IPUtils.get());
}
}

View File

@ -45,13 +45,10 @@ public class VAuthModelService {
return result;
}
if (request.getPrivileges() != null) {
result = result.stream().filter(vAuthModelDTO -> {
if (vAuthModelDTO.getNodeType().equalsIgnoreCase("spine") || (vAuthModelDTO.getNodeType().equalsIgnoreCase("leaf") && vAuthModelDTO.getPrivileges() != null && vAuthModelDTO.getPrivileges().contains(request.getPrivileges()))) {
return true;
} else {
return false;
}
}).collect(Collectors.toList());
result = result.stream().filter(vAuthModelDTO -> "spine".equalsIgnoreCase(vAuthModelDTO.getNodeType())
|| ("leaf".equalsIgnoreCase(vAuthModelDTO.getNodeType())
&& vAuthModelDTO.getPrivileges() != null
&& vAuthModelDTO.getPrivileges().contains(request.getPrivileges()))).collect(Collectors.toList());
}
return result;
}
@ -60,10 +57,10 @@ public class VAuthModelService {
if (CollectionUtils.isEmpty(result)) {
return;
}
Iterator iterator = result.listIterator();
Iterator<VAuthModelDTO> iterator = result.listIterator();
while (iterator.hasNext()) {
VAuthModelDTO tmp = (VAuthModelDTO) iterator.next();
if (tmp.getNodeType().equalsIgnoreCase("spine") && tmp.getAllLeafs() == 0) {
VAuthModelDTO tmp = iterator.next();
if ("spine".equalsIgnoreCase(tmp.getNodeType()) && tmp.getAllLeafs() == 0) {
iterator.remove();
} else {
removeEmptyDir(tmp.getChildren());
@ -77,9 +74,9 @@ public class VAuthModelService {
vAuthModelDTO.setAllLeafs(0);
continue;
}
long leafs = 0l;
long leafs = 0L;
for (VAuthModelDTO child : vAuthModelDTO.getChildren()) {
if (child.getNodeType().equalsIgnoreCase("leaf")) {
if ("leaf".equalsIgnoreCase(child.getNodeType())) {
leafs = leafs + 1;
} else {
leafs = +leafs + getLeafs(child);
@ -90,13 +87,13 @@ public class VAuthModelService {
}
private long getLeafs(VAuthModelDTO child) {
long leafs = 0l;
long leafs = 0L;
if (CollectionUtils.isEmpty(child.getChildren())) {
child.setAllLeafs(0);
return leafs;
}
for (VAuthModelDTO childChild : child.getChildren()) {
if (childChild.getNodeType().equalsIgnoreCase("leaf")) {
if ("leaf".equalsIgnoreCase(childChild.getNodeType())) {
leafs = leafs + 1;
} else {
leafs = +leafs + getLeafs(childChild);

View File

@ -577,7 +577,9 @@ public class ChartViewService {
List<ChartViewFieldDTO> xAxisBase = gson.fromJson(view.getXAxis(), tokenType);
List<ChartViewFieldDTO> xAxis = gson.fromJson(view.getXAxis(), tokenType);
List<ChartViewFieldDTO> xAxisExt = gson.fromJson(view.getXAxisExt(), tokenType);
if (StringUtils.equalsIgnoreCase(view.getType(), "table-pivot") || StringUtils.containsIgnoreCase(view.getType(), "group")) {
if (StringUtils.equalsIgnoreCase(view.getType(), "table-pivot")
|| StringUtils.containsIgnoreCase(view.getType(), "group")
|| ("antv".equalsIgnoreCase(view.getRender()) && "line".equalsIgnoreCase(view.getType()))) {
xAxis.addAll(xAxisExt);
}
List<ChartViewFieldDTO> yAxis = gson.fromJson(view.getYAxis(), tokenType);
@ -698,7 +700,13 @@ public class ChartViewService {
if (sqlVariables.stream().map(SqlVariableDetails::getVariableName).collect(Collectors.toList()).contains(parameter)) {
hasParameters = true;
}
if (parameter.contains("|DE|") && table.getId().equals(parameter.split("\\|DE\\|")[0]) && sqlVariables.stream().map(SqlVariableDetails::getVariableName).collect(Collectors.toList()).contains(parameter.split("\\|DE\\|")[1])) {
if (parameter.contains("|DE|")
&& table.getId().equals(parameter.split("\\|DE\\|")[0])
&& sqlVariables
.stream()
.map(SqlVariableDetails::getVariableName)
.collect(Collectors.toList())
.contains(parameter.split("\\|DE\\|")[1])) {
hasParameters = true;
}
}
@ -890,7 +898,7 @@ public class ChartViewService {
if (ObjectUtils.isEmpty(ds)) {
throw new RuntimeException(Translator.get("i18n_datasource_delete"));
}
if (StringUtils.isNotEmpty(ds.getStatus()) && ds.getStatus().equalsIgnoreCase("Error")) {
if (StringUtils.isNotEmpty(ds.getStatus()) && "Error".equalsIgnoreCase(ds.getStatus())) {
throw new Exception(Translator.get("i18n_invalid_ds"));
}
pageInfo.setDsVersion(datasourceProvider.dsVersion(ds));
@ -899,8 +907,8 @@ public class ChartViewService {
QueryProvider qp = ProviderFactory.getQueryProvider(ds.getType());
if (StringUtils.equalsIgnoreCase(table.getType(), DatasetType.DB.name())) {
datasourceRequest.setTable(dataTableInfoDTO.getTable());
if (StringUtils.equalsIgnoreCase("text", view.getType()) || StringUtils.equalsIgnoreCase("gauge", view.getType()) || StringUtils.equalsIgnoreCase("liquid", view.getType())) {
querySql = qp.getSQLSummary(dataTableInfoDTO.getTable(), yAxis, fieldCustomFilter, rowPermissionsTree, extFilterList, view, ds);
if (StringUtils.equalsAnyIgnoreCase(view.getType(), "text", "gauge", "liquid")) {
datasourceRequest.setQuery(qp.getSQLSummary(dataTableInfoDTO.getTable(), yAxis, fieldCustomFilter, rowPermissionsTree, extFilterList, view, ds));
} else if (StringUtils.containsIgnoreCase(view.getType(), "stack")) {
querySql = qp.getSQLStack(dataTableInfoDTO.getTable(), xAxis, yAxis, fieldCustomFilter, rowPermissionsTree, extFilterList, extStack, ds, view);
} else if (StringUtils.containsIgnoreCase(view.getType(), "scatter")) {
@ -914,7 +922,7 @@ public class ChartViewService {
} else if (StringUtils.equalsIgnoreCase(table.getType(), DatasetType.SQL.name())) {
String sql = dataTableInfoDTO.isBase64Encryption() ? new String(java.util.Base64.getDecoder().decode(dataTableInfoDTO.getSql())) : dataTableInfoDTO.getSql();
sql = handleVariable(sql, chartExtRequest, qp, table, ds);
if (StringUtils.equalsIgnoreCase("text", view.getType()) || StringUtils.equalsIgnoreCase("gauge", view.getType()) || StringUtils.equalsIgnoreCase("liquid", view.getType())) {
if (StringUtils.equalsAnyIgnoreCase(view.getType(), "text", "gauge", "liquid")) {
querySql = qp.getSQLSummaryAsTmp(sql, yAxis, fieldCustomFilter, rowPermissionsTree, extFilterList, view);
} else if (StringUtils.containsIgnoreCase(view.getType(), "stack")) {
querySql = qp.getSQLAsTmpStack(sql, xAxis, yAxis, fieldCustomFilter, rowPermissionsTree, extFilterList, extStack, view);
@ -930,7 +938,7 @@ public class ChartViewService {
DataTableInfoDTO dt = gson.fromJson(table.getInfo(), DataTableInfoDTO.class);
List<DataSetTableUnionDTO> list = dataSetTableUnionService.listByTableId(dt.getList().get(0).getTableId());
String sql = dataSetTableService.getCustomSQLDatasource(dt, list, ds);
if (StringUtils.equalsIgnoreCase("text", view.getType()) || StringUtils.equalsIgnoreCase("gauge", view.getType()) || StringUtils.equalsIgnoreCase("liquid", view.getType())) {
if (StringUtils.equalsAnyIgnoreCase(view.getType(), "text", "gauge", "liquid")) {
querySql = qp.getSQLSummaryAsTmp(sql, yAxis, fieldCustomFilter, rowPermissionsTree, extFilterList, view);
} else if (StringUtils.containsIgnoreCase(view.getType(), "stack")) {
querySql = qp.getSQLAsTmpStack(sql, xAxis, yAxis, fieldCustomFilter, rowPermissionsTree, extFilterList, extStack, view);
@ -946,8 +954,7 @@ public class ChartViewService {
DataTableInfoDTO dt = gson.fromJson(table.getInfo(), DataTableInfoDTO.class);
Map<String, Object> sqlMap = dataSetTableService.getUnionSQLDatasource(dt, ds);
String sql = (String) sqlMap.get("sql");
if (StringUtils.equalsIgnoreCase("text", view.getType()) || StringUtils.equalsIgnoreCase("gauge", view.getType()) || StringUtils.equalsIgnoreCase("liquid", view.getType())) {
if (StringUtils.equalsAnyIgnoreCase(view.getType(), "text", "gauge", "liquid")) {
querySql = qp.getSQLSummaryAsTmp(sql, yAxis, fieldCustomFilter, rowPermissionsTree, extFilterList, view);
} else if (StringUtils.containsIgnoreCase(view.getType(), "stack")) {
querySql = qp.getSQLAsTmpStack(sql, xAxis, yAxis, fieldCustomFilter, rowPermissionsTree, extFilterList, extStack, view);
@ -979,7 +986,7 @@ public class ChartViewService {
String tableName = "ds_" + table.getId().replaceAll("-", "_");
datasourceRequest.setTable(tableName);
QueryProvider qp = ProviderFactory.getQueryProvider(ds.getType());
if (StringUtils.equalsIgnoreCase("text", view.getType()) || StringUtils.equalsIgnoreCase("gauge", view.getType()) || StringUtils.equalsIgnoreCase("liquid", view.getType())) {
if (StringUtils.equalsAnyIgnoreCase(view.getType(), "text", "gauge", "liquid")) {
datasourceRequest.setQuery(qp.getSQLSummary(tableName, yAxis, fieldCustomFilter, rowPermissionsTree, extFilterList, view, ds));
} else if (StringUtils.containsIgnoreCase(view.getType(), "stack")) {
datasourceRequest.setQuery(qp.getSQLStack(tableName, xAxis, yAxis, fieldCustomFilter, rowPermissionsTree, extFilterList, extStack, ds, view));
@ -999,7 +1006,9 @@ public class ChartViewService {
if (!cache || CollectionUtils.isNotEmpty(chartExtRequest.getFilter())
|| CollectionUtils.isNotEmpty(chartExtRequest.getLinkageFilters())
|| CollectionUtils.isNotEmpty(chartExtRequest.getOuterParamsFilters())
|| CollectionUtils.isNotEmpty(chartExtRequest.getDrill()) || CollectionUtils.isNotEmpty(rowPermissionsTree) || fields.size() != columnPermissionFields.size()) {
|| CollectionUtils.isNotEmpty(chartExtRequest.getDrill())
|| CollectionUtils.isNotEmpty(rowPermissionsTree)
|| fields.size() != columnPermissionFields.size()) {
data = datasourceProvider.getData(datasourceRequest);
} else {
try {
@ -1151,7 +1160,7 @@ public class ChartViewService {
mapChart = ChartDataBuild.transChartData(xAxis, yAxis, view, data, isDrill);
}
} else if (StringUtils.equalsIgnoreCase(view.getRender(), "antv")) {
if (StringUtils.equalsIgnoreCase(view.getType(), "bar-group")) {
if (StringUtils.equalsAnyIgnoreCase(view.getType(), "bar-group","line")) {
mapChart = ChartDataBuild.transBaseGroupDataAntV(xAxisBase, xAxis, xAxisExt, yAxis, view, data, isDrill);
} else if (StringUtils.equalsIgnoreCase(view.getType(), "bar-group-stack")) {
mapChart = ChartDataBuild.transGroupStackDataAntV(xAxisBase, xAxis, xAxisExt, yAxis, extStack, data, view, isDrill);

View File

@ -158,7 +158,11 @@ public class ChartDataBuild {
} catch (Exception e) {
axisChartDataDTO.setValue(new BigDecimal(0));
}
axisChartDataDTO.setCategory(b.toString());
if ("line".equals(view.getType()) && CollectionUtils.isEmpty(xAxisExt)) {
axisChartDataDTO.setCategory(yAxis.get(j).getName());
} else {
axisChartDataDTO.setCategory(b.toString());
}
dataList.add(axisChartDataDTO);
}
}

View File

@ -149,7 +149,7 @@ public class DataSetTableService {
@Value("${upload.file.path}")
private String path;
private static Logger logger = LoggerFactory.getLogger(ClassloaderResponsity.class);
private static final Logger logger = LoggerFactory.getLogger(ClassloaderResponsity.class);
@DeCleaner(value = DePermissionType.DATASET, key = "sceneId")
public List<DatasetTable> batchInsert(List<DataSetTableRequest> datasetTable) throws Exception {
@ -185,7 +185,7 @@ public class DataSetTableService {
@Transactional(propagation = Propagation.NOT_SUPPORTED)
@DeCleaner(value = DePermissionType.DATASET, key = "sceneId")
public List<DatasetTable> saveExcel(DataSetTableRequest datasetTable) throws Exception {
public List<DatasetTable> saveExcel(DataSetTableRequest datasetTable) {
List<String> datasetIdList = new ArrayList<>();
if (StringUtils.isEmpty(datasetTable.getId())) {
@ -234,10 +234,9 @@ public class DataSetTableService {
list.add(sheetTable);
DeLogUtils.save(SysLogConstants.OPERATE_TYPE.CREATE, SysLogConstants.SOURCE_TYPE.DATASET, datasetTable.getId(), datasetTable.getSceneId(), null, null);
}
datasetIdList.forEach(datasetId -> {
commonThreadPool.addTask(() -> extractDataService.extractExcelData(datasetId, "all_scope", "初始导入",
null, datasetIdList));
});
datasetIdList.forEach(datasetId -> commonThreadPool.addTask(() ->
extractDataService.extractExcelData(datasetId, "all_scope", "初始导入",
null, datasetIdList)));
} else {
for (ExcelSheetData sheet : datasetTable.getSheets()) {
String[] fieldArray = sheet.getFields().stream().map(TableField::getFieldName)
@ -269,10 +268,9 @@ public class DataSetTableService {
list.add(sheetTable);
DeLogUtils.save(SysLogConstants.OPERATE_TYPE.MODIFY, SysLogConstants.SOURCE_TYPE.DATASET, datasetTable.getId(), datasetTable.getSceneId(), null, null);
}
datasetIdList.forEach(datasetId -> {
commonThreadPool.addTask(() -> extractDataService.extractExcelData(datasetId, "all_scope", "初始导入",
null, datasetIdList));
});
datasetIdList.forEach(datasetId -> commonThreadPool.addTask(() ->
extractDataService.extractExcelData(datasetId, "all_scope", "初始导入",
null, datasetIdList)));
}
return list;
@ -303,15 +301,15 @@ public class DataSetTableService {
DataTableInfoDTO info = new DataTableInfoDTO();
info.setExcelSheetDataList(excelSheetDataList);
datasetTable.setInfo(new Gson().toJson(info));
int update = datasetTableMapper.updateByPrimaryKeySelective(datasetTable);
datasetTableMapper.updateByPrimaryKeySelective(datasetTable);
// 替換時先不刪除旧字段同步成功后再删除
if (datasetTable.getEditType() == 0) {
commonThreadPool.addTask(() -> extractDataService.extractExcelData(datasetTable.getId(), "all_scope", "替换",
saveExcelTableField(datasetTable.getId(), datasetTable.getSheets().get(0).getFields(), false),
Arrays.asList(datasetTable.getId())));
Collections.singletonList(datasetTable.getId())));
} else if (datasetTable.getEditType() == 1) {
commonThreadPool.addTask(() -> extractDataService.extractExcelData(datasetTable.getId(), "add_scope", "追加",
null, Arrays.asList(datasetTable.getId())));
null, Collections.singletonList(datasetTable.getId())));
}
DeLogUtils.save(SysLogConstants.OPERATE_TYPE.MODIFY, SysLogConstants.SOURCE_TYPE.DATASET, datasetTable.getId(), datasetTable.getSceneId(), null, null);
return Collections.singletonList(datasetTable);
@ -362,12 +360,12 @@ public class DataSetTableService {
return datasetTable;
}
public void alter(DataSetTableRequest request) throws Exception {
public void alter(DataSetTableRequest request) {
checkName(request);
datasetTableMapper.updateByPrimaryKeySelective(request);
}
public void delete(String id) throws Exception {
public void delete(String id) {
DatasetTable table = datasetTableMapper.selectByPrimaryKey(id);
SysLogDTO sysLogDTO = DeLogUtils.buildLog(SysLogConstants.OPERATE_TYPE.DELETE, SysLogConstants.SOURCE_TYPE.DATASET, table.getId(), table.getSceneId(), null, null);
datasetTableMapper.deleteByPrimaryKey(id);
@ -489,9 +487,8 @@ public class DataSetTableService {
List<DataSetTableDTO> res = new ArrayList<>();
Map<String, DataSetTableDTO> map = new TreeMap<>();
group.forEach(ele -> map.put(ele.getId(), ele));
Iterator<Map.Entry<String, DataSetTableDTO>> iterator = map.entrySet().iterator();
while (iterator.hasNext()) {
res.add(iterator.next().getValue());
for (Map.Entry<String, DataSetTableDTO> stringDataSetTableDTOEntry : map.entrySet()) {
res.add(stringDataSetTableDTOEntry.getValue());
}
res.sort(Comparator.comparing(DatasetTable::getName));
res.addAll(ds);
@ -521,8 +518,7 @@ public class DataSetTableService {
return datasourceProvider.getTableFields(datasourceRequest);
}
public Map<String, List<DatasetTableField>> getFieldsFromDE(DataSetTableRequest dataSetTableRequest)
throws Exception {
public Map<String, List<DatasetTableField>> getFieldsFromDE(DataSetTableRequest dataSetTableRequest) {
DatasetTableField datasetTableField = DatasetTableField.builder().build();
datasetTableField.setTableId(dataSetTableRequest.getId());
datasetTableField.setChecked(Boolean.TRUE);
@ -1015,15 +1011,11 @@ public class DataSetTableService {
break;
case "TEXT":
sqlVariableDetails = sqlVariableDetails.stream().filter(item -> item.getType().get(0).contains("TEXT")).collect(Collectors.toList());
sqlVariableDetails.forEach(item -> {
item.setAlias(item.getVariableName());
});
sqlVariableDetails.forEach(item -> item.setAlias(item.getVariableName()));
break;
case "NUM":
sqlVariableDetails = sqlVariableDetails.stream().filter(item -> item.getType().get(0).contains("LONG") || item.getType().get(0).contains("DOUBLE")).collect(Collectors.toList());
sqlVariableDetails.forEach(item -> {
item.setAlias(item.getVariableName());
});
sqlVariableDetails.forEach(item -> item.setAlias(item.getVariableName()));
break;
}
return sqlVariableDetails;
@ -1087,15 +1079,15 @@ public class DataSetTableService {
if (select.getSelectBody() instanceof PlainSelect) {
return handlePlainSelect((PlainSelect) select.getSelectBody(), select, dsType);
} else {
String result = "";
StringBuilder result = new StringBuilder();
SetOperationList setOperationList = (SetOperationList) select.getSelectBody();
for (int i = 0; i < setOperationList.getSelects().size(); i++) {
result = result + handlePlainSelect((PlainSelect) setOperationList.getSelects().get(i), null, dsType);
result.append(handlePlainSelect((PlainSelect) setOperationList.getSelects().get(i), null, dsType));
if (i < setOperationList.getSelects().size() - 1) {
result = result + " " + setOperationList.getOperations().get(i).toString() + " ";
result.append(" ").append(setOperationList.getOperations().get(i).toString()).append(" ");
}
}
return result;
return result.toString();
}
}
@ -1140,14 +1132,14 @@ public class DataSetTableService {
builder.append(" ");
for (Iterator<WithItem> iter = select.getWithItemsList().iterator(); iter.hasNext(); ) {
WithItem withItem = iter.next();
builder.append(withItem.getName() + " AS ( " + removeVariables(withItem.getSubSelect().toString(), dsType) + " ) ");
builder.append(withItem.getName()).append(" AS ( ").append(removeVariables(withItem.getSubSelect().toString(), dsType)).append(" ) ");
if (iter.hasNext()) {
builder.append(",");
}
}
}
builder.append(" " + plainSelect);
builder.append(" ").append(plainSelect);
return builder.toString();
}
@ -1230,7 +1222,7 @@ public class DataSetTableService {
String sqlAsTable = qp.createSQLPreview(sql, null);
datasourceRequest.setQuery(sqlAsTable);
Map<String, List> result = new HashMap<>();
Map<String, List> result;
try {
datasetSqlLog.setStartTime(System.currentTimeMillis());
result = datasourceProvider.fetchResultAndField(datasourceRequest);
@ -1275,7 +1267,7 @@ public class DataSetTableService {
public Map<String, Object> getUnionPreview(DataSetTableRequest dataSetTableRequest) throws Exception {
DataTableInfoDTO dataTableInfoDTO = new Gson().fromJson(dataSetTableRequest.getInfo(), DataTableInfoDTO.class);
Map<String, Object> sqlMap = new HashMap<>();
Map<String, Object> sqlMap;
DatasourceRequest datasourceRequest = new DatasourceRequest();
Datasource ds;
if (dataSetTableRequest.getMode() == 0) {
@ -1289,7 +1281,6 @@ public class DataSetTableService {
}
String sql = (String) sqlMap.get("sql");
List<DatasetTableField> fieldList = (List<DatasetTableField>) sqlMap.get("field");
List<UnionParamDTO> join = (List<UnionParamDTO>) sqlMap.get("join");
Map<String, Object> res = new HashMap<>();
// 处理结果
@ -1423,9 +1414,7 @@ public class DataSetTableService {
DataTableInfoCustomUnion first = dataTableInfoDTO.getList().get(0);
if (CollectionUtils.isNotEmpty(list)) {
StringBuilder field = new StringBuilder();
Iterator<Map.Entry<String, String[]>> iterator = customInfo.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<String, String[]> next = iterator.next();
for (Map.Entry<String, String[]> next : customInfo.entrySet()) {
field.append(StringUtils.join(next.getValue(), ",")).append(",");
}
String f = field.substring(0, field.length() - 1);
@ -1493,9 +1482,7 @@ public class DataSetTableService {
String tableName = new Gson().fromJson(table.getInfo(), DataTableInfoDTO.class).getTable();
if (CollectionUtils.isNotEmpty(list)) {
StringBuilder field = new StringBuilder();
Iterator<Map.Entry<String, String[]>> iterator = customInfo.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<String, String[]> next = iterator.next();
for (Map.Entry<String, String[]> next : customInfo.entrySet()) {
field.append(StringUtils.join(next.getValue(), ",")).append(",");
}
String f = field.substring(0, field.length() - 1);
@ -1601,9 +1588,7 @@ public class DataSetTableService {
if (CollectionUtils.isNotEmpty(unionList)) {
// field
StringBuilder field = new StringBuilder();
Iterator<Map.Entry<String, String[]>> iterator = checkedInfo.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<String, String[]> next = iterator.next();
for (Map.Entry<String, String[]> next : checkedInfo.entrySet()) {
field.append(StringUtils.join(next.getValue(), ",")).append(",");
}
String f = subPrefixSuffixChar(field.toString());
@ -1664,8 +1649,7 @@ public class DataSetTableService {
// 递归计算出所有子级的checkedFields和unionParam
private void getUnionSQLDorisJoin(List<UnionDTO> childrenDs, Map<String, String[]> checkedInfo,
List<UnionParamDTO> unionList, List<DatasetTableField> checkedFields) {
for (int i = 0; i < childrenDs.size(); i++) {
UnionDTO unionDTO = childrenDs.get(i);
for (UnionDTO unionDTO : childrenDs) {
String tableId = unionDTO.getCurrentDs().getId();
String table = TableUtils.tableName(tableId);
DatasetTable datasetTable = datasetTableMapper.selectByPrimaryKey(tableId);
@ -1752,9 +1736,7 @@ public class DataSetTableService {
if (CollectionUtils.isNotEmpty(unionList)) {
// field
StringBuilder field = new StringBuilder();
Iterator<Map.Entry<String, String[]>> iterator = checkedInfo.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<String, String[]> next = iterator.next();
for (Map.Entry<String, String[]> next : checkedInfo.entrySet()) {
field.append(StringUtils.join(next.getValue(), ",")).append(",");
}
String f = subPrefixSuffixChar(field.toString());
@ -1825,9 +1807,7 @@ public class DataSetTableService {
// 递归计算出所有子级的checkedFields和unionParam
private void getUnionSQLDatasourceJoin(List<UnionDTO> childrenDs, Map<String, String[]> checkedInfo,
List<UnionParamDTO> unionList, String keyword, List<DatasetTableField> checkedFields) {
for (int i = 0; i < childrenDs.size(); i++) {
UnionDTO unionDTO = childrenDs.get(i);
for (UnionDTO unionDTO : childrenDs) {
DatasetTable datasetTable = datasetTableMapper.selectByPrimaryKey(unionDTO.getCurrentDs().getId());
String tableId = unionDTO.getCurrentDs().getId();
if (ObjectUtils.isEmpty(datasetTable)) {
@ -1976,7 +1956,7 @@ public class DataSetTableService {
Map<String, Object> sqlMap = getUnionSQLDoris(dataTableInfoDTO);
String sql = (String) sqlMap.get("sql");
List<DatasetTableField> fieldList = (List<DatasetTableField>) sqlMap.get("field");
List<UnionParamDTO> join = (List<UnionParamDTO>) sqlMap.get("join");
// custom 创建doris视图
createDorisView(TableUtils.tableName(datasetTable.getId()), sql);
@ -2003,7 +1983,7 @@ public class DataSetTableService {
Map<String, Object> sqlMap = getUnionSQLDatasource(dt, ds);
String sql = (String) sqlMap.get("sql");
List<DatasetTableField> fieldList = (List<DatasetTableField>) sqlMap.get("field");
List<UnionParamDTO> join = (List<UnionParamDTO>) sqlMap.get("join");
datasourceRequest.setQuery(sql);
fields = datasourceProvider.fetchResultField(datasourceRequest);
@ -2157,16 +2137,15 @@ public class DataSetTableService {
private void checkColumes(DatasetTableIncrementalConfig datasetTableIncrementalConfig) throws Exception {
DatasetTable datasetTable = datasetTableMapper.selectByPrimaryKey(datasetTableIncrementalConfig.getTableId());
List<DatasetTableField> datasetTableFields = dataSetTableFieldsService.getFieldsByTableId(datasetTable.getId())
.stream().filter(datasetTableField -> datasetTableField.getExtField() == 0).collect(Collectors.toList());
datasetTableFields.sort((o1, o2) -> {
if (o1.getColumnIndex() == null) {
return -1;
}
if (o2.getColumnIndex() == null) {
return 1;
}
return o1.getColumnIndex().compareTo(o2.getColumnIndex());
});
.stream().filter(datasetTableField -> datasetTableField.getExtField() == 0).sorted((o1, o2) -> {
if (o1.getColumnIndex() == null) {
return -1;
}
if (o2.getColumnIndex() == null) {
return 1;
}
return o1.getColumnIndex().compareTo(o2.getColumnIndex());
}).collect(Collectors.toList());
List<String> originNameFields = datasetTableFields.stream().map(DatasetTableField::getOriginName)
.collect(Collectors.toList());
@ -2184,9 +2163,7 @@ public class DataSetTableService {
List<String> sqlFields = new ArrayList<>();
try {
datasourceProvider.fetchResultField(datasourceRequest).stream().map(TableField::getFieldName)
.forEach(field -> {
sqlFields.add(field);
});
.forEach(sqlFields::add);
} catch (Exception e) {
DataEaseException.throwException(Translator.get("i18n_check_sql_error") + e.getMessage());
}
@ -2204,7 +2181,7 @@ public class DataSetTableService {
List<String> sqlFields = new ArrayList<>();
try {
datasourceProvider.fetchResultField(datasourceRequest).stream().map(TableField::getFieldName)
.forEach(field -> sqlFields.add(field));
.forEach(sqlFields::add);
} catch (Exception e) {
DataEaseException.throwException(Translator.get("i18n_check_sql_error") + e.getMessage());
}
@ -2228,7 +2205,7 @@ public class DataSetTableService {
criteria.andNameEqualTo(datasetTable.getName());
}
List<DatasetTable> list = datasetTableMapper.selectByExample(datasetTableExample);
if (list.size() > 0) {
if (!list.isEmpty()) {
throw new RuntimeException(Translator.get("i18n_name_cant_repeat_same_group"));
}
}
@ -2253,7 +2230,7 @@ public class DataSetTableService {
criteria.andNameIn(new ArrayList<>(nameSet));
}
List<DatasetTable> list = datasetTableMapper.selectByExample(datasetTableExample);
if (list.size() > 0) {
if (!list.isEmpty()) {
throw new RuntimeException(Translator.get("i18n_name_cant_repeat_same_group"));
}
}
@ -2278,8 +2255,7 @@ public class DataSetTableService {
if (StringUtils.isNotEmpty(tableId)) {
List<DatasetTableField> fields = dataSetTableFieldsService.getFieldsByTableId(tableId);
List<DatasetTableField> datasetTableFields = fields.stream().filter(datasetTableField -> datasetTableField.getExtField() == 0).collect(Collectors.toList());
datasetTableFields.sort((o1, o2) -> {
List<DatasetTableField> datasetTableFields = fields.stream().filter(datasetTableField -> datasetTableField.getExtField() == 0).sorted((o1, o2) -> {
if (o1.getColumnIndex() == null) {
return -1;
}
@ -2287,7 +2263,7 @@ public class DataSetTableService {
return 1;
}
return o1.getColumnIndex().compareTo(o2.getColumnIndex());
});
}).collect(Collectors.toList());
List<String> oldFields = datasetTableFields.stream().map(DatasetTableField::getOriginName).collect(Collectors.toList());
@ -2299,7 +2275,7 @@ public class DataSetTableService {
returnSheetDataList.add(excelSheetData);
}
}
if (returnSheetDataList.size() == 0) {
if (returnSheetDataList.isEmpty()) {
DataEaseException.throwException(Translator.get("i18n_excel_column_change"));
}
} else {
@ -2321,22 +2297,19 @@ public class DataSetTableService {
for (ExcelSheetData excelSheetData : excelSheetDataList) {
List<TableField> tableFields = excelSheetData.getFields();
List<String> newFields = tableFields.stream().map(TableField::getRemarks).collect(Collectors.toList());
if (oldFields.equals(newFields)) {
excelSheetData.setChangeFiled(false);
} else {
excelSheetData.setChangeFiled(true);
}
excelSheetData.setChangeFiled(!oldFields.equals(newFields));
boolean effectExtField = false;
for (String extFieldsRefName : extFieldsRefNames) {
if (!newFields.contains(extFieldsRefName)) {
effectExtField = true;
break;
}
}
excelSheetData.setEffectExtField(effectExtField);
returnSheetDataList.add(excelSheetData);
}
if (returnSheetDataList.size() == 0) {
if (returnSheetDataList.isEmpty()) {
DataEaseException.throwException(Translator.get("i18n_excel_column_change"));
}
}
@ -2403,7 +2376,7 @@ public class DataSetTableService {
}
List<List<String>> data = new ArrayList<>();
int num = 1;
String line = null;
String line;
while ((line = reader.readLine()) != null) {
if (num > 100) {
break;
@ -2450,7 +2423,7 @@ public class DataSetTableService {
try {
double d = cell.getNumericCellValue();
try {
Double value = new Double(d);
Double value = d;
double eps = 1e-10;
if (value - Math.floor(value) < eps) {
if (cellType) {
@ -2469,7 +2442,7 @@ public class DataSetTableService {
return nf.format(value);
}
} catch (Exception e) {
BigDecimal b = new BigDecimal(d);
BigDecimal b = BigDecimal.valueOf(d);
return b.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue() + "";
}
} catch (IllegalStateException e) {
@ -2502,7 +2475,7 @@ public class DataSetTableService {
} else {
double d = cell.getNumericCellValue();
try {
Double value = new Double(d);
Double value = d;
double eps = 1e-10;
if (value - Math.floor(value) < eps) {
if (cellType) {
@ -2521,7 +2494,7 @@ public class DataSetTableService {
return nf.format(value);
}
} catch (Exception e) {
BigDecimal b = new BigDecimal(d);
BigDecimal b = BigDecimal.valueOf(d);
return b.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue() + "";
}
}
@ -2655,18 +2628,14 @@ public class DataSetTableService {
* 判断数组中是否有重复的值
*/
public static boolean checkIsRepeat(String[] array) {
HashSet<String> hashSet = new HashSet<String>();
for (int i = 0; i < array.length; i++) {
if (StringUtils.isEmpty(array[i])) {
HashSet<String> hashSet = new HashSet<>();
for (String s : array) {
if (StringUtils.isEmpty(s)) {
throw new RuntimeException(Translator.get("i18n_excel_empty_column"));
}
hashSet.add(array[i]);
}
if (hashSet.size() == array.length) {
return false;
} else {
return true;
hashSet.add(s);
}
return hashSet.size() != array.length;
}
public DatasetTable syncDatasetTableField(String id) throws Exception {
@ -2857,7 +2826,7 @@ public class DataSetTableService {
return expressionDeParser;
}
static private boolean hasVariable(String sql) {
private static boolean hasVariable(String sql) {
return sql.contains(SubstitutedParams);
}
@ -2886,6 +2855,7 @@ public class DataSetTableService {
if (StringUtils.isNotEmpty(request.getExpressionTree())) {
Gson gson = new Gson();
tree = gson.fromJson(request.getExpressionTree(), DatasetRowPermissionsTreeObj.class);
permissionsTreeService.getField(tree);
}
Map<String, Object> previewData = getPreviewData(request, 1, 100000, null, tree);
List<DatasetTableField> fields = (List<DatasetTableField>) previewData.get("fields");
@ -2935,7 +2905,7 @@ public class DataSetTableService {
//设置列的宽度
detailsSheet.setColumnWidth(j, 255 * 20);
} else {
if ((fields.get(j).getDeType() == DeTypeConstants.DE_INT || fields.get(j).getDeType() == DeTypeConstants.DE_FLOAT) && StringUtils.isNotEmpty(rowData.get(j))) {
if ((fields.get(j).getDeType().equals(DeTypeConstants.DE_INT) || fields.get(j).getDeType() == DeTypeConstants.DE_FLOAT) && StringUtils.isNotEmpty(rowData.get(j))) {
try {
cell.setCellValue(Double.valueOf(rowData.get(j)));
} catch (Exception e) {

View File

@ -153,7 +153,7 @@ public class PermissionsTreeService {
return result;
}
private void getField(DatasetRowPermissionsTreeObj tree) {
public void getField(DatasetRowPermissionsTreeObj tree) {
if (ObjectUtils.isNotEmpty(tree)) {
if (ObjectUtils.isNotEmpty(tree.getItems())) {
for (DatasetRowPermissionsTreeItem item : tree.getItems()) {

View File

@ -55,6 +55,13 @@ public class SysMsgService {
@Autowired
private SystemParameterService systemParameterService;
public void cleanDisusedMsg() {
Long overTime = overTime();
SysMsgExample example = new SysMsgExample();
example.createCriteria().andCreateTimeLessThan(overTime);
sysMsgMapper.deleteByExample(example);
}
public List<MsgGridDto> queryGrid(Long userId, MsgRequest msgRequest, List<Long> typeIds, Long startTime) {
String orderClause = " create_time desc";
SysMsgExample example = new SysMsgExample();

View File

@ -29,6 +29,7 @@ import io.dataease.listener.util.CacheUtils;
import io.dataease.plugins.common.base.domain.*;
import io.dataease.plugins.common.base.mapper.*;
import io.dataease.plugins.common.constants.DeTypeConstants;
import io.dataease.service.SystemInfoService;
import io.dataease.service.chart.ChartViewService;
import io.dataease.service.dataset.DataSetGroupService;
import io.dataease.service.dataset.DataSetTableService;
@ -131,6 +132,10 @@ public class PanelGroupService {
private DataSetGroupService dataSetGroupService;
@Resource
private DatasetGroupMapper datasetGroupMapper;
@Resource
private PanelWatermarkMapper panelWatermarkMapper;
@Resource
private SystemInfoService systemInfoService;
public List<PanelGroupDTO> tree(PanelGroupRequest panelGroupRequest) {
String userId = String.valueOf(AuthUtils.getUser().getUserId());
@ -304,6 +309,7 @@ public class PanelGroupService {
panelGroup.setPanelStyle(sourcePanel.getPanelStyle());
panelGroup.setSourcePanelName(sourcePanel.getName());
}
panelGroup.setWatermarkInfo(panelWatermarkMapper.selectByPrimaryKey("system_default"));
return panelGroup;
}
@ -750,7 +756,9 @@ public class PanelGroupService {
if (cache == null) {
return null;
} else {
return (PanelGroupRequest) cache;
PanelGroupDTO result = (PanelGroupRequest) cache;
result.setWatermarkInfo(panelWatermarkMapper.selectByPrimaryKey("system_default"));
return result;
}
}

View File

@ -4,26 +4,26 @@ import io.dataease.auth.config.RsaProperties;
import io.dataease.auth.util.JWTUtils;
import io.dataease.auth.util.RsaUtil;
import io.dataease.commons.constants.SysLogConstants;
import io.dataease.commons.utils.AuthUtils;
import io.dataease.commons.utils.CodingUtil;
import io.dataease.commons.utils.DeLogUtils;
import io.dataease.commons.utils.ServletUtils;
import io.dataease.commons.utils.*;
import io.dataease.controller.request.panel.link.EnablePwdRequest;
import io.dataease.controller.request.panel.link.LinkRequest;
import io.dataease.controller.request.panel.link.OverTimeRequest;
import io.dataease.controller.request.panel.link.PasswordRequest;
import io.dataease.dto.panel.PanelGroupDTO;
import io.dataease.dto.panel.link.GenerateDto;
import io.dataease.ext.ExtPanelLinkMapper;
import io.dataease.plugins.common.base.domain.*;
import io.dataease.plugins.common.base.mapper.PanelGroupMapper;
import io.dataease.plugins.common.base.mapper.PanelLinkMapper;
import io.dataease.plugins.common.base.mapper.PanelLinkMappingMapper;
import io.dataease.plugins.common.base.mapper.PanelWatermarkMapper;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import io.dataease.ext.ExtPanelLinkMapper;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@ -47,6 +47,8 @@ public class PanelLinkService {
private ExtPanelLinkMapper extPanelLinkMapper;
@Resource
private PanelLinkMappingMapper panelLinkMappingMapper;
@Resource
private PanelWatermarkMapper panelWatermarkMapper;
@Transactional
public void changeValid(LinkRequest request) {
@ -67,7 +69,7 @@ public class PanelLinkService {
if (!request.isValid()) {
operateType = SysLogConstants.OPERATE_TYPE.DELETELINK;
}
DeLogUtils.save(operateType, SysLogConstants.SOURCE_TYPE.PANEL, panel.getId(), panel.getPid(), null, null) ;
DeLogUtils.save(operateType, SysLogConstants.SOURCE_TYPE.PANEL, panel.getId(), panel.getPid(), null, null);
}
private PanelLinkExample example(String panelLinkId, Long userId) {
@ -82,7 +84,7 @@ public class PanelLinkService {
po.setEnablePwd(request.isEnablePwd());
mapper.updateByExampleSelective(po, example(request.getResourceId(), AuthUtils.getUser().getUserId()));
PanelGroupWithBLOBs panel = panelGroupMapper.selectByPrimaryKey(request.getResourceId());
DeLogUtils.save(SysLogConstants.OPERATE_TYPE.MODIFYLINK, SysLogConstants.SOURCE_TYPE.PANEL, panel.getId(), panel.getPid(), null, null) ;
DeLogUtils.save(SysLogConstants.OPERATE_TYPE.MODIFYLINK, SysLogConstants.SOURCE_TYPE.PANEL, panel.getId(), panel.getPid(), null, null);
}
public void password(PasswordRequest request) {
@ -93,14 +95,14 @@ public class PanelLinkService {
PanelGroupWithBLOBs panel = panelGroupMapper.selectByPrimaryKey(request.getResourceId());
DeLogUtils.save(SysLogConstants.OPERATE_TYPE.MODIFYLINK, SysLogConstants.SOURCE_TYPE.PANEL, panel.getId(), panel.getPid(), null, null) ;
DeLogUtils.save(SysLogConstants.OPERATE_TYPE.MODIFYLINK, SysLogConstants.SOURCE_TYPE.PANEL, panel.getId(), panel.getPid(), null, null);
}
public void overTime(OverTimeRequest request) {
request.setUserId(AuthUtils.getUser().getUserId());
extPanelLinkMapper.updateOverTime(request);
PanelGroupWithBLOBs panel = panelGroupMapper.selectByPrimaryKey(request.getResourceId());
DeLogUtils.save(SysLogConstants.OPERATE_TYPE.MODIFYLINK, SysLogConstants.SOURCE_TYPE.PANEL, panel.getId(), panel.getPid(), null, null) ;
DeLogUtils.save(SysLogConstants.OPERATE_TYPE.MODIFYLINK, SysLogConstants.SOURCE_TYPE.PANEL, panel.getId(), panel.getPid(), null, null);
}
private PanelLink findOne(String resourceId) {
@ -232,8 +234,12 @@ public class PanelLinkService {
return pass;
}
public PanelGroupWithBLOBs resourceInfo(String resourceId) {
return panelGroupMapper.selectByPrimaryKey(resourceId);
public PanelGroupDTO resourceInfo(String resourceId) {
PanelGroupWithBLOBs result = panelGroupMapper.selectByPrimaryKey(resourceId);
PanelGroupDTO panelGroupDTO = new PanelGroupDTO();
BeanUtils.copyBean(panelGroupDTO, result);
panelGroupDTO.setWatermarkInfo(panelWatermarkMapper.selectByPrimaryKey("system_default"));
return panelGroupDTO;
}
public String getShortUrl(String resourceId) {

View File

@ -74,7 +74,7 @@ public class SysUserService {
List<SysUserGridResponse> lists = extSysUserMapper.query(gridExample);
lists.forEach(item -> {
List<SysUserRole> roles = item.getRoles();
List<Long> roleIds = roles.stream().map(SysUserRole::getRoleId).collect(Collectors.toList());
List<Long> roleIds = roles.stream().filter(ObjectUtils::isNotEmpty).map(SysUserRole::getRoleId).collect(Collectors.toList());
item.setRoleIds(roleIds);
});
return lists;

View File

@ -28,15 +28,12 @@ public class LogManager {
protected static final String contentFormat = "【%s】";
protected static final String positionFormat = "在【%s】";
protected static final String format = "给%s【%s】";
protected Gson gson = new Gson();
protected Type type = new TypeToken<List<FolderItem>>() {}.getType();
protected Type type = new TypeToken<List<FolderItem>>() {
}.getType();
@Resource
@ -47,26 +44,28 @@ public class LogManager {
public String detailInfo(SysLogWithBLOBs vo) {
String sourceName = vo.getSourceName();
String position = null;
String operateTypeName = SysLogConstants.operateTypeName(vo.getOperateType());
operateTypeName = Translator.get(operateTypeName);
String sourceTypeName = SysLogConstants.sourceTypeName(vo.getSourceType());
sourceTypeName = Translator.get(sourceTypeName);
String result = operateTypeName + sourceTypeName + String.format(contentFormat, sourceName) + remarkInfo(vo);
String result = operateTypeName + sourceTypeName + String.format(contentFormat, vo.getSourceName());
if (vo.getSourceType() != SysLogConstants.SOURCE_TYPE.LINK.getValue()) {
result += remarkInfo(vo, false);
}
if ((position = vo.getPosition()) != null) {
List<FolderItem> folderItems = gson.fromJson(position, type);
String template = folderItems.stream().map(folderItem -> folderItem.getName()).collect(Collectors.joining("/"));
String positionResult = String.format(positionFormat, template);
return positionResult + result;
String positionResult = String.format(Translator.get("I18N_LOG_FORMAT_POSITION"), template);
result = positionResult + result;
}
if (vo.getSourceType() == SysLogConstants.SOURCE_TYPE.LINK.getValue()) {
result = remarkInfo(vo, true) + result;
}
return result;
}
public String remarkInfo(SysLogWithBLOBs vo) {
public String remarkInfo(SysLogWithBLOBs vo, Boolean isPrefix) {
String remakrk = null;
if ((remakrk = vo.getRemark()) != null) {
String targetTypeName = null;
@ -77,14 +76,16 @@ public class LogManager {
Integer targetType = item.getType();
targetTypeName = SysLogConstants.sourceTypeName(targetType);
targetTypeName = Translator.get(targetTypeName);
return String.format(format, targetTypeName, template);
if (isPrefix) {
return String.format(Translator.get("I18N_LOG_FORMAT_PREFIX"), targetTypeName, template);
}
return String.format(Translator.get("I18N_LOG_FORMAT"), targetTypeName, template);
}
}
return "";
}
private LogTypeItem parentIds(String id, Integer value) {
LogTypeItem result = new LogTypeItem();
String typeValue = "";
@ -119,7 +120,7 @@ public class LogManager {
}
private List<FolderItem> parentInfos(List<String> ids, Integer value){
private List<FolderItem> parentInfos(List<String> ids, Integer value) {
List<FolderItem> folderItems = extSysLogMapper.idAndName(ids, value);
if (value == 3) {
folderItems.forEach(item -> {
@ -164,7 +165,7 @@ public class LogManager {
ArrayList<DataSourceType> dataSourceTypes = new ArrayList<>(datasourceService.types());
String name = null;
for (int i = 0; i < dataSourceTypes.size(); i++) {
if (dataSourceTypes.get(i).getType().equals(typeId)){
if (dataSourceTypes.get(i).getType().equals(typeId)) {
name = dataSourceTypes.get(i).getName();
break;
}

View File

@ -9,6 +9,7 @@ import io.dataease.commons.constants.ParamConstants;
import io.dataease.commons.constants.SysLogConstants;
import io.dataease.commons.utils.AuthUtils;
import io.dataease.commons.utils.BeanUtils;
import io.dataease.commons.utils.IPUtils;
import io.dataease.commons.utils.ServletUtils;
import io.dataease.controller.sys.base.ConditionEntity;
import io.dataease.controller.sys.request.KeyGridRequest;
@ -28,6 +29,7 @@ import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.*;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
@ -46,6 +48,8 @@ public class LogService {
// 仪表板的额外操作 分享以及公共链接
private static Integer[] panel_ext_ope = {4, 5, 8, 9, 10};
private static Integer[] link_ext_ope = {13, 14};
// 驱动文件操作 上传 删除
private static Integer[] driver_file_ope = {11, 3};
@ -247,6 +251,16 @@ public class LogService {
results.add(folderItem);
}
for (int i = 0; i < link_ext_ope.length; i++) {
SysLogConstants.SOURCE_TYPE sourceType = SysLogConstants.SOURCE_TYPE.LINK;
FolderItem folderItem = new FolderItem();
folderItem.setId(link_ext_ope[i] + "-" + sourceType.getValue());
String operateTypeName = SysLogConstants.operateTypeName(link_ext_ope[i]);
String sourceTypeName = sourceType.getName();
folderItem.setName(Translator.get(operateTypeName) + Translator.get(sourceTypeName));
results.add(folderItem);
}
FolderItem userLogin = new FolderItem();
SysLogConstants.OPERATE_TYPE operateTypeLogin = SysLogConstants.OPERATE_TYPE.LOGIN;
SysLogConstants.SOURCE_TYPE sourceTypeLogin = SysLogConstants.SOURCE_TYPE.USER;
@ -308,6 +322,7 @@ public class LogService {
sysLogGridDTO.setTime(vo.getTime());
sysLogGridDTO.setUser(vo.getNickName());
sysLogGridDTO.setDetail(logManager.detailInfo(vo));
sysLogGridDTO.setIp(vo.getIp());
return sysLogGridDTO;
}
@ -330,12 +345,14 @@ public class LogService {
sysLogWithBLOBs.setLoginName(sysLogDTO.getSourceName());
sysLogWithBLOBs.setNickName(sysLogDTO.getSourceName());
}
sysLogWithBLOBs.setIp(IPUtils.get());
sysLogMapper.insert(sysLogWithBLOBs);
}
public void exportExcel(KeyGridRequest request) throws Exception {
request = logRetentionProxy(request);
request = detailRequest(request);
String keyWord = request.getKeyWord();
List<String> ids = null;
@ -355,24 +372,25 @@ public class LogService {
List<String[]> details = lists.stream().map(item -> {
String operateTypeName = SysLogConstants.operateTypeName(item.getOperateType());
String sourceTypeName = SysLogConstants.sourceTypeName(item.getSourceType());
String[] row = new String[4];
String[] row = new String[5];
row[0] = Translator.get(operateTypeName) + " " + Translator.get(sourceTypeName);
row[1] = logManager.detailInfo(item);
row[2] = item.getNickName();
row[3] = DateUtil.formatDateTime(new Date(item.getTime()));
row[3] = item.getIp();
row[4] = DateUtil.formatDateTime(new Date(item.getTime()));
return row;
}).collect(Collectors.toList());
String[] headArr = {"操作类型", "详情", "用户", "时间"};
String[] headArr = {"操作类型", "详情", "用户", "IP地址", "时间"};
details.add(0, headArr);
HSSFWorkbook wb = new HSSFWorkbook();
XSSFWorkbook wb = new XSSFWorkbook();
//明细sheet
HSSFSheet detailsSheet = wb.createSheet("数据");
XSSFSheet detailsSheet = wb.createSheet("数据");
//给单元格设置样式
CellStyle cellStyle = wb.createCellStyle();
Font font = wb.createFont();
XSSFCellStyle cellStyle = wb.createCellStyle();
XSSFFont font = wb.createFont();
//设置字体大小
font.setFontHeightInPoints((short) 12);
//设置字体加粗
@ -386,11 +404,11 @@ public class LogService {
if (CollectionUtils.isNotEmpty(details)) {
for (int i = 0; i < details.size(); i++) {
HSSFRow row = detailsSheet.createRow(i);
XSSFRow row = detailsSheet.createRow(i);
String[] rowData = details.get(i);
if (rowData != null) {
for (int j = 0; j < rowData.length; j++) {
HSSFCell cell = row.createCell(j);
XSSFCell cell = row.createCell(j);
cell.setCellValue(rowData[j]);
if (i == 0) {// 头部
cell.setCellStyle(cellStyle);
@ -406,7 +424,7 @@ public class LogService {
//文件名称
String fileName = "DataEase操作日志";
String encodeFileName = URLEncoder.encode(fileName, "UTF-8");
response.setHeader("Content-disposition", "attachment;filename=" + encodeFileName + ".xls");
response.setHeader("Content-disposition", "attachment;filename=" + encodeFileName + ".xlsx");
wb.write(outputStream);
outputStream.flush();
outputStream.close();

View File

@ -0,0 +1,38 @@
ALTER TABLE `sys_log`
CHANGE COLUMN `user_id` `user_id` BIGINT NULL COMMENT '操作人',
CHANGE COLUMN `login_name` `login_name` VARCHAR (255) NULL COMMENT '登录账号',
CHANGE COLUMN `nick_name` `nick_name` VARCHAR (255) NULL COMMENT '姓名';
ALTER TABLE `panel_group`
ADD COLUMN `watermark_open` tinyint(1) NULL DEFAULT 1 COMMENT '是否单独打开水印' AFTER `update_time`;
DROP TABLE IF EXISTS `panel_watermark`;
CREATE TABLE `panel_watermark`
(
`id` varchar(50) NOT NULL,
`version` varchar(255) DEFAULT NULL COMMENT '版本号',
`setting_content` longtext COMMENT '设置内容',
`create_by` varchar(255) DEFAULT NULL,
`create_time` bigint(13) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE utf8mb4_general_ci;
INSERT INTO `panel_watermark` (`id`, `version`, `setting_content`, `create_by`, `create_time`)
VALUES ('system_default', '1.0',
'{\"enable\":false,\"enablePanelCustom\":true,\"type\":\"custom\",\"content\":\"${time}-${nickName}\",\"watermark_color\":\"#999999\",\"watermark_x_space\":20,\"watermark_y_space\":100,\"watermark_fontsize\":20}',
'admin', NULL);
SET
FOREIGN_KEY_CHECKS = 1;
UPDATE `sys_menu`
SET `component` = 'dataset/Form'
WHERE (`menu_id` = '800');
UPDATE `sys_menu`
SET `component` = 'msg/All'
WHERE (`component` = 'msg/all');
UPDATE `sys_menu`
SET `component` = 'msg/Setting'
WHERE (`component` = 'msg/setting');

View File

@ -167,6 +167,7 @@ SOURCE_TYPE_ROLE=ROLE
SOURCE_TYPE_DRIVER=DRIVER
SOURCE_TYPE_DRIVER_FILE=DRIVER FILE
SOURCE_TYPE_MENU=MENU
SOURCE_TYPE_LINK=PUBLIC LINK
I18N_OPERATE_TYPE=Operation type
I18N_DETAIL=Operation details
I18N_USER=Operator
@ -241,3 +242,7 @@ I18N_APP_NO_DATASOURCE=This panel don't have datasource
I18N_APP_ONE_DATASOURCE_TIPS=This panel should have only one datasource
I18N_PROHIBIT_SCANNING_TO_CREATE_USER=Prohibit scanning code to create user
I18N_LOG_FORMAT_POSITION=IN\u3010%s\u3011
I18N_LOG_FORMAT=TO %s\u3010%s\u3011
I18N_LOG_FORMAT_PREFIX=With authority of %s\u3010%s\u3011

View File

@ -167,6 +167,7 @@ SOURCE_TYPE_ROLE=\u89D2\u8272
SOURCE_TYPE_DRIVER=\u9A71\u52A8
SOURCE_TYPE_DRIVER_FILE=\u9A71\u52A8\u6587\u4EF6
SOURCE_TYPE_MENU=\u83DC\u5355
SOURCE_TYPE_LINK=\u516C\u5171\u94FE\u63A5
I18N_OPERATE_TYPE=\u64CD\u4F5C\u7C7B\u578B
I18N_DETAIL=\u64CD\u4F5C\u8BE6\u60C5
I18N_USER=\u64CD\u4F5C\u4EBA
@ -241,3 +242,7 @@ I18N_APP_NO_DATASOURCE=\u6CA1\u6709\u627E\u5230\u6570\u636E\u6E90
I18N_APP_ONE_DATASOURCE_TIPS=\u8BE5\u4EEA\u8868\u677F\u53EA\u80FD\u5B58\u5728\u4E00\u4E2A\u6570\u636E\u6E90
I18N_PROHIBIT_SCANNING_TO_CREATE_USER=\u7981\u6B62\u626B\u7801\u521B\u5EFA\u7528\u6237\uFF0C\u8BF7\u8054\u7CFB\u7BA1\u7406\u5458\uFF01
I18N_LOG_FORMAT_POSITION=\u5728\u3010%s\u3011
I18N_LOG_FORMAT=\u7ED9%s\u3010%s\u3011
I18N_LOG_FORMAT_PREFIX=\u4EE5%s\u3010%s\u3011\u6743\u9650

View File

@ -167,6 +167,7 @@ SOURCE_TYPE_ROLE=\u89D2\u8272
SOURCE_TYPE_DRIVER=\u9A45\u52D5
SOURCE_TYPE_DRIVER_FILE=\u9A45\u52D5\u6587\u4EF6
SOURCE_TYPE_MENU=\u83DC\u55AE
SOURCE_TYPE_LINK=\u516C\u5171\u93C8\u63A5
I18N_DRIVER_NOT_DELETE=\u4F7F\u7528\u4E2D\u7684\u9A45\u52D5\u4E0D\u5141\u8A31\u5220\u9664
I18N_DRIVER_REPEAT_NAME=\u540D\u7A31\u91CD\u8907
I18N_DRIVER_NOT_FOUND=\u672A\u627E\u5230\u9A45\u52D5
@ -236,3 +237,7 @@ I18N_APP_ERROR_DATASET=\u5100\u8868\u677F\u4E2D\u4E0D\u80FD\u5B58\u5728API\u6578
I18N_APP_NO_DATASOURCE=\u6C92\u6709\u627E\u5230\u6578\u64DA\u6E90
I18N_APP_ONE_DATASOURCE_TIPS=\u8A72\u5100\u8868\u677F\u53EA\u80FD\u5B58\u5728\u4E00\u500B\u6578\u64DA\u6E90
I18N_PROHIBIT_SCANNING_TO_CREATE_USER=\u7981\u6B62\u6383\u78BC\u5275\u5EFA\u7528\u6236\uFF0C\u8ACB\u806F\u7CFB\u7BA1\u7406\u54E1\uFF01
I18N_LOG_FORMAT_POSITION=\u5728\u3010%s\u3011
I18N_LOG_FORMAT=\u7D66%s\u3010%s\u3011
I18N_LOG_FORMAT_PREFIX=\u4EE5%s\u3010%s\u3011\u6B0A\u9650

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>dataease-server</artifactId>
@ -44,7 +44,7 @@
</goals>
<!-- Optional configuration which provides for running any npm command -->
<configuration>
<arguments>install --force</arguments>
<arguments>install</arguments>
</configuration>
</execution>
@ -62,4 +62,4 @@
</plugins>
</build>
</project>
</project>

View File

@ -1,38 +0,0 @@
import request from '@/utils/request'
export function post(url, data) {
return request({
url: url,
method: 'post',
loading: true,
data
})
}
export function get(url) {
return request({
url: url,
method: 'get',
loading: true
})
}
export function fileUpload(url, file, files, param) {
const formData = new FormData()
if (file) {
formData.append('file', file)
}
if (files) {
files.forEach(f => {
formData.append('files', f)
})
}
formData.append('request', new Blob([JSON.stringify(param)], { type: 'application/json' }))
return request({
method: 'POST',
loading: true,
url: url,
data: formData
})
}
export default { fileUpload }

View File

@ -50,6 +50,15 @@ export function switchEnablePwd(data) {
})
}
export function viewLinkLog(data) {
return request({
url: 'api/link/viewLog',
method: 'post',
loading: true,
data
})
}
export function loadGenerate(resourceId) {
return request({
url: 'api/link/currentGenerate/' + resourceId,

View File

@ -66,6 +66,7 @@ export function viewData(id, panelId, data) {
data
})
}
export function panelSave(data) {
return request({
url: 'panel/group/save',
@ -162,6 +163,10 @@ export function initPanelData(panelId, useCache = false, callback) {
if (response.data) {
// 初始化视图data和style 数据
panelInit(JSON.parse(response.data.panelData), JSON.parse(response.data.panelStyle))
const watermarkInfo = {
...response.data.watermarkInfo,
settingContent: JSON.parse(response.data.watermarkInfo.settingContent)
}
// 设置当前仪表板全局信息
store.dispatch('panel/setPanelInfo', {
id: response.data.id,
@ -174,7 +179,9 @@ export function initPanelData(panelId, useCache = false, callback) {
creatorName: response.data.creatorName,
updateBy: response.data.updateBy,
updateName: response.data.updateName,
updateTime: response.data.updateTime
updateTime: response.data.updateTime,
watermarkOpen: response.data.watermarkOpen,
watermarkInfo: watermarkInfo
})
// 刷新联动信息
getPanelAllLinkageInfo(panelId).then(rsp => {
@ -230,6 +237,7 @@ export function initViewCache(panelId) {
loading: false
})
}
export function exportDetails(data) {
// 初始化仪表板视图缓存
return request({
@ -268,6 +276,7 @@ export function saveCache(data) {
data
})
}
export function findUserCacheRequest(panelId) {
return request({
url: 'panel/group/findUserCache/' + panelId,

View File

@ -10,6 +10,10 @@ export function proxyInitPanelData(panelId, proxy, callback) {
if (response.data) {
// 初始化视图data和style 数据
panelInit(JSON.parse(response.data.panelData), JSON.parse(response.data.panelStyle))
const watermarkInfo = {
...response.data.watermarkInfo,
settingContent: JSON.parse(response.data.watermarkInfo.settingContent)
}
// 设置当前仪表板全局信息
store.dispatch('panel/setPanelInfo', {
id: response.data.id,
@ -23,7 +27,9 @@ export function proxyInitPanelData(panelId, proxy, callback) {
creatorName: response.data.creatorName,
updateBy: response.data.updateBy,
updateName: response.data.updateName,
updateTime: response.data.updateTime
updateTime: response.data.updateTime,
watermarkOpen: response.data.watermarkOpen,
watermarkInfo: watermarkInfo
})
// 刷新联动信息
getPanelAllLinkageInfo(panelId, proxy).then(rsp => {

View File

@ -0,0 +1,13 @@
import request from '@/utils/request'
export function userLoginInfo() {
return request({
url: '/systemInfo/userLoginInfo',
method: 'get',
loading: false
})
}
export default {
userLoginInfo
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 262 KiB

After

Width:  |  Height:  |  Size: 272 KiB

View File

@ -1,85 +0,0 @@
<!-- @author zhengjie -->
<template>
<div class="icon-body">
<el-input
v-model="name"
style="position: relative;"
clearable
placeholder="请输入图标名称"
@clear="filterIcons"
@input.native="filterIcons"
>
<i
slot="suffix"
class="el-icon-search el-input__icon"
/>
</el-input>
<div class="icon-list">
<div
v-for="(item, index) in iconList"
:key="index"
@click="selectedIcon(item)"
>
<svg-icon
:icon-class="item"
style="height: 30px;width: 16px;"
/>
<span>{{ item }}</span>
</div>
</div>
</div>
</template>
<script>
import icons from './requireIcons'
export default {
name: 'IconSelect',
data() {
return {
name: '',
iconList: icons
}
},
methods: {
filterIcons() {
this.iconList = icons
if (this.name) {
this.iconList = this.iconList.filter(item => item.includes(this.name))
}
},
selectedIcon(name) {
this.$emit('selected', name)
document.body.click()
},
reset() {
this.name = ''
this.iconList = icons
}
}
}
</script>
<style rel="stylesheet/scss" lang="scss" scoped>
.icon-body {
width: 100%;
padding: 10px;
.icon-list {
height: 200px;
overflow-y: scroll;
div {
height: 30px;
line-height: 30px;
margin-bottom: -5px;
cursor: pointer;
width: 33%;
float: left;
}
span {
display: inline-block;
vertical-align: -0.15em;
fill: currentColor;
overflow: hidden;
}
}
}
</style>

View File

@ -1,11 +0,0 @@
const req = require.context('@/icons/svg', false, /\.svg$/)
const requireAll = requireContext => requireContext.keys()
const re = /\.\/(.*)\.svg/
const icons = requireAll(req).map(i => {
return i.match(re)[1]
})
export default icons

View File

@ -1,76 +0,0 @@
<template>
<component
:is="mode"
:ref="refId"
v-bind="$attrs"
v-on="$listeners"
>
<template #default>
<slot name="default" />
</template>
</component>
</template>
<script>
import { uuid } from 'vue-uuid'
import { get } from '@/api/system/dynamic'
export default {
name: 'AsyncComponent',
inheritAttrs: true,
props: {
//
url: {
type: String,
default: ''
}
},
data() {
return {
resData: '',
mode: '',
refId: null
}
},
watch: {
url: {
immediate: true,
async handler(val, oldVal) {
if (!this.url) return
// Cache url
if (!window.SyncComponentCache) {
window.SyncComponentCache = {}
}
let res
if (!window.SyncComponentCache[this.url]) {
window.SyncComponentCache[this.url] = get(this.url)
// window.SyncComponentCache[this.url] = Axios.get(this.url)
res = await window.SyncComponentCache[this.url]
} else {
res = await window.SyncComponentCache[this.url]
}
const Fn = Function
this.mode = new Fn(`return ${res.data || res}`)()
/* if (res && res.data) {
const Fn = Function
this.mode = new Fn(`return ${res.data || res}`)()
} */
}
}
},
created() {
this.refId = uuid.v1
},
methods: {
/* chartResize() {
this.$refs[this.refId] && this.$refs[this.refId].chartResize && this.$refs[this.refId].chartResize()
}, */
callPluginInner(param) {
const { methodName, methodParam } = param
this.$refs[this.refId] && this.$refs[this.refId][methodName] && this.$refs[this.refId][methodName](methodParam)
}
}
}
</script>

View File

@ -1,92 +0,0 @@
<template>
<el-breadcrumb
class="app-breadcrumb"
separator="/"
>
<transition-group name="breadcrumb">
<el-breadcrumb-item
v-for="(item,index) in levelList"
:key="item.path"
>
<span v-if="index === 0">当前位置</span>
<span
v-if="item.redirect==='noRedirect'||index==levelList.length-1"
class="no-redirect"
>{{ item.meta.title }}</span>
<a
v-else
@click.prevent="handleLink(item)"
>{{ item.meta.title }}</a>
</el-breadcrumb-item>
</transition-group>
</el-breadcrumb>
</template>
<script>
import pathToRegexp from 'path-to-regexp'
export default {
data() {
return {
levelList: null
}
},
watch: {
$route() {
this.getBreadcrumb()
}
},
created() {
this.getBreadcrumb()
},
methods: {
getBreadcrumb() {
// only show routes with meta.title
let matched = this.$route.matched.filter(item => item.meta && item.meta.title)
const first = matched[0]
if (!this.isDashboard(first)) {
matched = [{ path: '/panel', meta: { title: '仪表板' }}].concat(matched)
}
this.levelList = matched.filter(item => item.meta && item.meta.title && item.meta.breadcrumb !== false)
},
isDashboard(route) {
const name = route && route.name
if (!name) {
return false
}
// return name.trim().toLocaleLowerCase() === 'Dashboard'.toLocaleLowerCase()
return name.trim().toLocaleLowerCase() === 'panel'.toLocaleLowerCase()
},
pathCompile(path) {
// To solve this problem https://github.com/PanJiaChen/vue-element-admin/issues/561
const { params } = this.$route
var toPath = pathToRegexp.compile(path)
return toPath(params)
},
handleLink(item) {
const { redirect, path } = item
if (redirect) {
this.$router.push(redirect)
return
}
this.$router.push(this.pathCompile(path))
}
}
}
</script>
<style lang="scss" scoped>
.app-breadcrumb.el-breadcrumb {
display: inline-block;
font-size: 14px;
line-height: 50px;
margin-left: 8px;
.no-redirect {
color: #97a8be;
cursor: text;
}
}
</style>

View File

@ -1,128 +0,0 @@
<template>
<el-select
v-model="selected"
multiple
v-bind="$attrsAll"
v-on="$listenserAll"
@change="onChange"
>
<el-option
v-for="item in mdoptionsList"
:key="item.key"
:label="item.label"
:value="item.value"
/>
<slot name="default" />
</el-select>
</template>
<script>
export default {
name: 'ElSelectAll',
props: {
value: {
type: Array,
default: () => {
return []
}
},
options: {
type: Array,
default: () => {
return []
}
}
},
data() {
const selected = this.value || []
return {
selected,
mdoptionsValue: [],
oldMdoptionsValue: [],
mdoptionsList: []
}
},
computed: {
$attrsAll() {
// const val = this.$vnode.data.model && this.$vnode.data.model.value;
const result = {
// value: val,
...this.$attrs
}
return result
},
$listenserAll() {
const _this = this
return Object.assign({}, this.$listeners, {
change: () => {
this.$emit('change', (_this.selected || []).filter(v => {
return v !== 'all'
}))
},
input: () => {
this.$emit('input', (_this.selected || []).filter(v => {
return v !== 'all'
}))
}
})
}
},
watch: {
selected: {
immediate: true,
deep: true,
handler(val) {
this.$emit('input', (val || []).filter(v => {
return v !== 'all'
}))
}
},
options: {
immediate: true,
deep: true,
handler(val) {
if ((!val || val.length === 0) && !this.$slots) {
this.mdoptionsList = []
} else {
this.mdoptionsList = [{
key: 'all',
value: 'all',
label: '全部'
}, ...val]
}
}
}
},
mounted() {
},
methods: {
onChange(val) {
// eslint-disable-next-line no-debugger
const allValues = []
//
for (const item of this.mdoptionsList) {
allValues.push(item.value)
}
//
const oldVal = this.oldMdoptionsValue.length === 1 ? [] : this.oldMdoptionsValue[1] || []
//
if (val.includes('all')) this.selected = allValues
//
if (oldVal.includes('all') && !val.includes('all')) this.selected = []
//
//
if (oldVal.includes('all') && val.includes('all')) {
const index = val.indexOf('all')
val.splice(index, 1) //
this.selected = val
}
//
if (!oldVal.includes('all') && !val.includes('all')) {
if (val.length === allValues.length - 1) this.selected = ['all'].concat(val)
}
//
this.oldMdoptionsValue[1] = this.selected
}
}
}
</script>

View File

@ -1,131 +0,0 @@
<template>
<div class="complex-table">
<div
v-if="$slots.header || header"
class="complex-table__header"
>
<slot name="header">{{ header }}</slot>
</div>
<div
v-if="$slots.toolbar || searchConfig"
class="complex-table__toolbar"
>
<div>
<slot name="toolbar" />
</div>
<fu-search-bar
ref="search"
v-bind="searchConfig"
@exec="search"
>
<template #complex>
<slot name="complex" />
</template>
<slot name="buttons" />
<fu-table-column-select
v-if="!hideColumns"
:columns="columns"
/>
</fu-search-bar>
</div>
<div class="complex-table__body">
<fu-table
v-bind="$attrs"
:columns="columns"
:local-key="localKey"
v-on="$listeners"
>
<slot />
</fu-table>
</div>
<div
v-if="$slots.pagination || paginationConfig"
class="complex-table__pagination"
>
<slot name="pagination">
<fu-table-pagination
:current-page.sync="paginationConfig.currentPage"
:page-size.sync="paginationConfig.pageSize"
v-bind="paginationConfig"
@change="search"
/>
</slot>
</div>
</div>
</template>
<script>
export default {
name: 'ComplexTable',
props: {
columns: {
type: Array,
default: () => []
},
hideColumns: {
type: Boolean,
default: false
},
// eslint-disable-next-line vue/require-default-prop
localKey: String, // Key
// eslint-disable-next-line vue/require-default-prop
header: String,
// eslint-disable-next-line vue/require-default-prop
searchConfig: Object,
// eslint-disable-next-line vue/require-default-prop
paginationConfig: Object,
transCondition: {
type: Object,
default: null
}
},
data() {
return {
condition: {}
}
},
mounted() {
if (this.transCondition !== null) {
this.$refs.search.setConditions(this.transCondition)
}
},
methods: {
search(condition, e) {
if (condition) {
this.condition = condition
}
this.$emit('search', this.condition, e)
}
}
}
</script>
<style lang="scss">
@import "~@/styles/mixin.scss";
.complex-table {
.complex-table__header {
@include flex-row(flex-start, center);
line-height: 60px;
font-size: 18px;
}
.complex-table__toolbar {
@include flex-row(space-between, center);
.fu-search-bar {
width: auto;
}
}
.complex-table__pagination {
margin-top: 20px;
@include flex-row(flex-end);
}
}
</style>

View File

@ -1,98 +0,0 @@
<template>
<div>
<!-- <el-switch v-model="value" active-text="当前用户" /> -->
<treeselect
v-model="value"
:options="options"
:load-options="loadData"
style="width: 200px"
:no-children-text="$t('commons.treeselect.no_children_text')"
:no-options-text="$t('commons.treeselect.no_options_text')"
:no-results-text="$t('commons.treeselect.no_results_text')"
/>
</div>
</template>
<script>
import { ComplexCondition } from 'fit2cloud-ui/src/components/search-bar/model'
import { getDeptTree } from '@/api/system/dept'
import { LOAD_CHILDREN_OPTIONS, LOAD_ROOT_OPTIONS } from '@riophae/vue-treeselect'
import Treeselect from '@riophae/vue-treeselect'
import '@riophae/vue-treeselect/dist/vue-treeselect.css'
export default {
components: { Treeselect },
props: {
// eslint-disable-next-line vue/require-default-prop
field: String,
// eslint-disable-next-line vue/require-default-prop
label: String,
// eslint-disable-next-line vue/require-default-prop
defaultOperator: String
// eslint-disable-next-line vue/require-default-prop
// options: Array
// eslint-disable-next-line vue/require-default-prop
// loadData: Function
},
data() {
return {
value: undefined,
operator: 'dept',
operatorLabel: '组织',
options: null
}
},
computed: {
valueLabel() {
return this.value
}
},
// 2
methods: {
init() { //
//
this.value = undefined
},
getCondition() { //
const { field, label, operator, operatorLabel, value, valueLabel } = this
// ComplexCondition
return new ComplexCondition({ field, label, operator, operatorLabel, value, valueLabel })
},
//
loadData({ action, parentNode, callback }) {
if (action === LOAD_ROOT_OPTIONS) {
const _self = this
!this.options && getDeptTree('0').then(res => {
_self.options = res.data.map(node => _self.normalizer(node))
callback()
})
}
if (action === LOAD_CHILDREN_OPTIONS) {
const _self = this
getDeptTree(parentNode.id).then(res => {
parentNode.children = res.data.map(function(obj) {
return _self.normalizer(obj)
})
callback()
})
}
},
normalizer(node) {
if (node.hasChildren) {
node.children = null
}
return {
id: node.deptId,
label: node.name,
children: node.children
}
}
}
}
</script>
<style scoped>
</style>

View File

@ -1,115 +0,0 @@
<template>
<div class="complex-table">
<div
v-if="$slots.header || header"
class="complex-table__header"
>
<slot name="header">{{ header }}</slot>
</div>
<div
v-if="$slots.toolbar || searchConfig"
class="complex-table__toolbar"
>
<!-- <slot name="toolbar">
<fu-search-bar v-bind="searchConfig" @exec="search">
<slot name="buttons" />
<fu-table-column-select :columns="columns" />
</fu-search-bar>
</slot> -->
<div>
<slot name="toolbar" />
</div>
<fu-search-bar
v-bind="searchConfig"
@exec="search"
>
<template #complex>
<slot name="complex" />
</template>
<slot name="buttons" />
<fu-table-column-select :columns="columns" />
</fu-search-bar>
</div>
<div class="complex-table__body">
<slot />
<!-- <fu-table ref="table" v-bind="$attrs" :columns="columns" :local-key="localKey" v-on="$listeners">
<slot />
</fu-table> -->
</div>
<div
v-if="$slots.pagination || paginationConfig"
class="complex-table__pagination"
>
<slot name="pagination">
<fu-table-pagination
:current-page.sync="paginationConfig.currentPage"
:page-size.sync="paginationConfig.pageSize"
v-bind="paginationConfig"
@change="search"
/>
</slot>
</div>
</div>
</template>
<script>
export default {
name: 'TreeTable',
props: {
columns: {
type: Array,
default: () => []
},
// eslint-disable-next-line vue/require-default-prop
localKey: String, // Key
// eslint-disable-next-line vue/require-default-prop
header: String,
// eslint-disable-next-line vue/require-default-prop
searchConfig: Object,
// eslint-disable-next-line vue/require-default-prop
paginationConfig: Object
},
data() {
return {
condition: {}
}
},
methods: {
search(condition, e) {
if (condition) {
this.condition = condition
}
this.$emit('search', this.condition, e)
}
}
}
</script>
<style lang="scss">
@import "~@/styles/mixin.scss";
.complex-table {
.complex-table__header {
@include flex-row(flex-start, center);
line-height: 60px;
font-size: 18px;
}
.complex-table__toolbar {
@include flex-row(space-between, center);
.fu-search-bar {
width: auto;
}
}
.complex-table__pagination {
margin-top: 20px;
@include flex-row(flex-end);
}
}
</style>

View File

@ -112,7 +112,9 @@ import toast from '@/components/canvas/utils/toast'
import generateID from '@/components/canvas/utils/generateID'
import ButtonDialog from '@/views/panel/filter/ButtonDialog'
import ButtonResetDialog from '@/views/panel/filter/ButtonResetDialog'
import FilterDialog from '@/views/panel/filter/filterDialog'
import FilterDialog from '@/views/panel/filter/FilterDialog'
import { userLoginInfo } from '@/api/systemInfo/userLogin'
import { activeWatermark } from '@/components/canvas/tools/watermark'
export default {
components: { FilterDialog, ButtonResetDialog, ButtonDialog, DeEditor },
@ -233,12 +235,19 @@ export default {
watch: {
mobileLayoutStatus() {
this.restore()
},
panelInfo: {
handler(newVal, oldVla) {
this.initWatermark()
},
deep: true
}
},
created() {
},
mounted() {
const _this = this
this.initWatermark()
// div
const erd = elementResizeDetectorMaker()
erd.listenTo(document.getElementById(this.canvasDomId), element => {
@ -252,6 +261,14 @@ export default {
bus.$off('button-dialog-edit', this.editButtonDialog)
},
methods: {
initWatermark() {
if (this.panelInfo.watermarkInfo) {
userLoginInfo().then(res => {
const userInfo = res.data
activeWatermark(this.panelInfo.watermarkInfo.settingContent, userInfo, this.canvasDomId, this.canvasId, this.panelInfo.watermarkOpen)
})
}
},
initEvents() {
bus.$on('component-dialog-edit', this.editDialog)
bus.$on('button-dialog-edit', this.editButtonDialog)
@ -289,6 +306,7 @@ export default {
}
},
canvasScroll(e) {
this.scrollTop = e.target.scrollTop
this.$emit('canvasScroll', { scrollLeft: e.target.scrollLeft, scrollTop: e.target.scrollTop })
bus.$emit('onScroll')
},

View File

@ -1,539 +0,0 @@
/* Logo 字体 */
@font-face {
font-family: "iconfont logo";
src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834');
src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834#iefix') format('embedded-opentype'),
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.woff?t=1545807318834') format('woff'),
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.ttf?t=1545807318834') format('truetype'),
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.svg?t=1545807318834#iconfont') format('svg');
}
.logo {
font-family: "iconfont logo";
font-size: 160px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
/* tabs */
.nav-tabs {
position: relative;
}
.nav-tabs .nav-more {
position: absolute;
right: 0;
bottom: 0;
height: 42px;
line-height: 42px;
color: #666;
}
#tabs {
border-bottom: 1px solid #eee;
}
#tabs li {
cursor: pointer;
width: 100px;
height: 40px;
line-height: 40px;
text-align: center;
font-size: 16px;
border-bottom: 2px solid transparent;
position: relative;
z-index: 1;
margin-bottom: -1px;
color: #666;
}
#tabs .active {
border-bottom-color: #f00;
color: #222;
}
.tab-container .content {
display: none;
}
/* 页面布局 */
.main {
padding: 30px 100px;
width: 960px;
margin: 0 auto;
}
.main .logo {
color: #333;
text-align: left;
margin-bottom: 30px;
line-height: 1;
height: 110px;
margin-top: -50px;
overflow: hidden;
*zoom: 1;
}
.main .logo a {
font-size: 160px;
color: #333;
}
.helps {
margin-top: 40px;
}
.helps pre {
padding: 20px;
margin: 10px 0;
border: solid 1px #e7e1cd;
background-color: #fffdef;
overflow: auto;
}
.icon_lists {
width: 100% !important;
overflow: hidden;
*zoom: 1;
}
.icon_lists li {
width: 100px;
margin-bottom: 10px;
margin-right: 20px;
text-align: center;
list-style: none !important;
cursor: default;
}
.icon_lists li .code-name {
line-height: 1.2;
}
.icon_lists .icon {
display: block;
height: 100px;
line-height: 100px;
font-size: 42px;
margin: 10px auto;
color: #333;
-webkit-transition: font-size 0.25s linear, width 0.25s linear;
-moz-transition: font-size 0.25s linear, width 0.25s linear;
transition: font-size 0.25s linear, width 0.25s linear;
}
.icon_lists .icon:hover {
font-size: 100px;
}
.icon_lists .svg-icon {
/* 通过设置 font-size 来改变图标大小 */
width: 1em;
/* 图标和文字相邻时,垂直对齐 */
vertical-align: -0.15em;
/* 通过设置 color 来改变 SVG 的颜色/fill */
fill: currentColor;
/* path stroke 溢出 viewBox 部分在 IE 下会显示
normalize.css 中也包含这行 */
overflow: hidden;
}
.icon_lists li .name,
.icon_lists li .code-name {
color: #666;
}
/* markdown 样式 */
.markdown {
color: #666;
font-size: 14px;
line-height: 1.8;
}
.highlight {
line-height: 1.5;
}
.markdown img {
vertical-align: middle;
max-width: 100%;
}
.markdown h1 {
color: #404040;
font-weight: 500;
line-height: 40px;
margin-bottom: 24px;
}
.markdown h2,
.markdown h3,
.markdown h4,
.markdown h5,
.markdown h6 {
color: #404040;
margin: 1.6em 0 0.6em 0;
font-weight: 500;
clear: both;
}
.markdown h1 {
font-size: 28px;
}
.markdown h2 {
font-size: 22px;
}
.markdown h3 {
font-size: 16px;
}
.markdown h4 {
font-size: 14px;
}
.markdown h5 {
font-size: 12px;
}
.markdown h6 {
font-size: 12px;
}
.markdown hr {
height: 1px;
border: 0;
background: #e9e9e9;
margin: 16px 0;
clear: both;
}
.markdown p {
margin: 1em 0;
}
.markdown > p,
.markdown > blockquote,
.markdown > .highlight,
.markdown > ol,
.markdown > ul {
width: 80%;
}
.markdown ul > li {
list-style: circle;
}
.markdown > ul li,
.markdown blockquote ul > li {
margin-left: 20px;
padding-left: 4px;
}
.markdown > ul li p,
.markdown > ol li p {
margin: 0.6em 0;
}
.markdown ol > li {
list-style: decimal;
}
.markdown > ol li,
.markdown blockquote ol > li {
margin-left: 20px;
padding-left: 4px;
}
.markdown code {
margin: 0 3px;
padding: 0 5px;
background: #eee;
border-radius: 3px;
}
.markdown strong,
.markdown b {
font-weight: 600;
}
.markdown > table {
border-collapse: collapse;
border-spacing: 0px;
empty-cells: show;
border: 1px solid #e9e9e9;
width: 95%;
margin-bottom: 24px;
}
.markdown > table th {
white-space: nowrap;
color: #333;
font-weight: 600;
}
.markdown > table th,
.markdown > table td {
border: 1px solid #e9e9e9;
padding: 8px 16px;
text-align: left;
}
.markdown > table th {
background: #F7F7F7;
}
.markdown blockquote {
font-size: 90%;
color: #999;
border-left: 4px solid #e9e9e9;
padding-left: 0.8em;
margin: 1em 0;
}
.markdown blockquote p {
margin: 0;
}
.markdown .anchor {
opacity: 0;
transition: opacity 0.3s ease;
margin-left: 8px;
}
.markdown .waiting {
color: #ccc;
}
.markdown h1:hover .anchor,
.markdown h2:hover .anchor,
.markdown h3:hover .anchor,
.markdown h4:hover .anchor,
.markdown h5:hover .anchor,
.markdown h6:hover .anchor {
opacity: 1;
display: inline-block;
}
.markdown > br,
.markdown > p > br {
clear: both;
}
.hljs {
display: block;
background: white;
padding: 0.5em;
color: #333333;
overflow-x: auto;
}
.hljs-comment,
.hljs-meta {
color: #969896;
}
.hljs-string,
.hljs-variable,
.hljs-template-variable,
.hljs-strong,
.hljs-emphasis,
.hljs-quote {
color: #df5000;
}
.hljs-keyword,
.hljs-selector-tag,
.hljs-type {
color: #a71d5d;
}
.hljs-literal,
.hljs-symbol,
.hljs-bullet,
.hljs-attribute {
color: #0086b3;
}
.hljs-section,
.hljs-name {
color: #63a35c;
}
.hljs-tag {
color: #333333;
}
.hljs-title,
.hljs-attr,
.hljs-selector-id,
.hljs-selector-class,
.hljs-selector-attr,
.hljs-selector-pseudo {
color: #795da3;
}
.hljs-addition {
color: #55a532;
background-color: #eaffea;
}
.hljs-deletion {
color: #bd2c00;
background-color: #ffecec;
}
.hljs-link {
text-decoration: underline;
}
/* 代码高亮 */
/* PrismJS 1.15.0
https://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript */
/**
* prism.js default theme for JavaScript, CSS and HTML
* Based on dabblet (http://dabblet.com)
* @author Lea Verou
*/
code[class*="language-"],
pre[class*="language-"] {
color: black;
background: none;
text-shadow: 0 1px white;
font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
text-align: left;
white-space: pre;
word-spacing: normal;
word-break: normal;
word-wrap: normal;
line-height: 1.5;
-moz-tab-size: 4;
-o-tab-size: 4;
tab-size: 4;
-webkit-hyphens: none;
-moz-hyphens: none;
-ms-hyphens: none;
hyphens: none;
}
pre[class*="language-"]::-moz-selection,
pre[class*="language-"] ::-moz-selection,
code[class*="language-"]::-moz-selection,
code[class*="language-"] ::-moz-selection {
text-shadow: none;
background: #b3d4fc;
}
pre[class*="language-"]::selection,
pre[class*="language-"] ::selection,
code[class*="language-"]::selection,
code[class*="language-"] ::selection {
text-shadow: none;
background: #b3d4fc;
}
@media print {
code[class*="language-"],
pre[class*="language-"] {
text-shadow: none;
}
}
/* Code blocks */
pre[class*="language-"] {
padding: 1em;
margin: .5em 0;
overflow: auto;
}
:not(pre) > code[class*="language-"],
pre[class*="language-"] {
background: #f5f2f0;
}
/* Inline code */
:not(pre) > code[class*="language-"] {
padding: .1em;
border-radius: .3em;
white-space: normal;
}
.token.comment,
.token.prolog,
.token.doctype,
.token.cdata {
color: slategray;
}
.token.punctuation {
color: #999;
}
.namespace {
opacity: .7;
}
.token.property,
.token.tag,
.token.boolean,
.token.number,
.token.constant,
.token.symbol,
.token.deleted {
color: #905;
}
.token.selector,
.token.attr-name,
.token.string,
.token.char,
.token.builtin,
.token.inserted {
color: #690;
}
.token.operator,
.token.entity,
.token.url,
.language-css .token.string,
.style .token.string {
color: #9a6e3a;
background: hsla(0, 0%, 100%, .5);
}
.token.atrule,
.token.attr-value,
.token.keyword {
color: #07a;
}
.token.function,
.token.class-name {
color: #DD4A68;
}
.token.regex,
.token.important,
.token.variable {
color: #e90;
}
.token.important,
.token.bold {
font-weight: bold;
}
.token.italic {
font-style: italic;
}
.token.entity {
cursor: help;
}

View File

@ -1,307 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title>IconFont Demo</title>
<link rel="shortcut icon" href="https://img.alicdn.com/tps/i4/TB1_oz6GVXXXXaFXpXXJDFnIXXX-64-64.ico" type="image/x-icon"/>
<link rel="stylesheet" href="https://g.alicdn.com/thx/cube/1.3.2/cube.min.css">
<link rel="stylesheet" href="demo.css">
<link rel="stylesheet" href="iconfont.css">
<script src="iconfont.js"></script>
<!-- jQuery -->
<script src="https://a1.alicdn.com/oss/uploads/2018/12/26/7bfddb60-08e8-11e9-9b04-53e73bb6408b.js"></script>
<!-- 代码高亮 -->
<script src="https://a1.alicdn.com/oss/uploads/2018/12/26/a3f714d0-08e6-11e9-8a15-ebf944d7534c.js"></script>
</head>
<body>
<div class="main">
<h1 class="logo"><a href="https://www.iconfont.cn/" title="iconfont 首页" target="_blank">&#xe86b;</a></h1>
<div class="nav-tabs">
<ul id="tabs" class="dib-box">
<li class="dib active"><span>Unicode</span></li>
<li class="dib"><span>Font class</span></li>
<li class="dib"><span>Symbol</span></li>
</ul>
<a href="https://www.iconfont.cn/manage/index?manage_type=myprojects&projectId=2373406" target="_blank" class="nav-more">查看项目</a>
</div>
<div class="tab-container">
<div class="content unicode" style="display: block;">
<ul class="icon_lists dib-box">
<li class="dib">
<span class="icon iconfont">&#xe66a;</span>
<div class="name">向右旋转</div>
<div class="code-name">&amp;#xe66a;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe616;</span>
<div class="name">图片</div>
<div class="code-name">&amp;#xe616;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe672;</span>
<div class="name"></div>
<div class="code-name">&amp;#xe672;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe790;</span>
<div class="name">矩形</div>
<div class="code-name">&amp;#xe790;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe652;</span>
<div class="name">文本</div>
<div class="code-name">&amp;#xe652;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe648;</span>
<div class="name">按钮</div>
<div class="code-name">&amp;#xe648;</div>
</li>
</ul>
<div class="article markdown">
<h2 id="unicode-">Unicode 引用</h2>
<hr>
<p>Unicode 是字体在网页端最原始的应用方式,特点是:</p>
<ul>
<li>兼容性最好,支持 IE6+,及所有现代浏览器。</li>
<li>支持按字体的方式去动态调整图标大小,颜色等等。</li>
<li>但是因为是字体,所以不支持多色。只能使用平台里单色的图标,就算项目里有多色图标也会自动去色。</li>
</ul>
<blockquote>
<p>注意:新版 iconfont 支持多色图标,这些多色图标在 Unicode 模式下将不能使用如果有需求建议使用symbol 的引用方式</p>
</blockquote>
<p>Unicode 使用步骤如下:</p>
<h3 id="-font-face">第一步:拷贝项目下面生成的 <code>@font-face</code></h3>
<pre><code class="language-css"
>@font-face {
font-family: 'iconfont';
src: url('iconfont.eot');
src: url('iconfont.eot?#iefix') format('embedded-opentype'),
url('iconfont.woff2') format('woff2'),
url('iconfont.woff') format('woff'),
url('iconfont.ttf') format('truetype');
}
</code></pre>
<h3 id="-iconfont-">第二步:定义使用 iconfont 的样式</h3>
<pre><code class="language-css"
>.iconfont {
font-family: "iconfont" !important;
font-size: 16px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
</code></pre>
<h3 id="-">第三步:挑选相应图标并获取字体编码,应用于页面</h3>
<pre>
<code class="language-html"
>&lt;span class="iconfont"&gt;&amp;#x33;&lt;/span&gt;
</code></pre>
<blockquote>
<p>"iconfont" 是你项目下的 font-family。可以通过编辑项目查看默认是 "iconfont"。</p>
</blockquote>
</div>
</div>
<div class="content font-class">
<ul class="icon_lists dib-box">
<li class="dib">
<span class="icon iconfont icon-xiangyouxuanzhuan"></span>
<div class="name">
向右旋转
</div>
<div class="code-name">.icon-xiangyouxuanzhuan
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-tupian"></span>
<div class="name">
图片
</div>
<div class="code-name">.icon-tupian
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-suo"></span>
<div class="name">
</div>
<div class="code-name">.icon-suo
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-juxing"></span>
<div class="name">
矩形
</div>
<div class="code-name">.icon-juxing
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-wenben"></span>
<div class="name">
文本
</div>
<div class="code-name">.icon-wenben
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-button"></span>
<div class="name">
按钮
</div>
<div class="code-name">.icon-button
</div>
</li>
</ul>
<div class="article markdown">
<h2 id="font-class-">font-class 引用</h2>
<hr>
<p>font-class 是 Unicode 使用方式的一种变种,主要是解决 Unicode 书写不直观,语意不明确的问题。</p>
<p>与 Unicode 使用方式相比,具有如下特点:</p>
<ul>
<li>兼容性良好,支持 IE8+,及所有现代浏览器。</li>
<li>相比于 Unicode 语意明确,书写更直观。可以很容易分辨这个 icon 是什么。</li>
<li>因为使用 class 来定义图标,所以当要替换图标时,只需要修改 class 里面的 Unicode 引用。</li>
<li>不过因为本质上还是使用的字体,所以多色图标还是不支持的。</li>
</ul>
<p>使用步骤如下:</p>
<h3 id="-fontclass-">第一步:引入项目下面生成的 fontclass 代码:</h3>
<pre><code class="language-html">&lt;link rel="stylesheet" href="./iconfont.css"&gt;
</code></pre>
<h3 id="-">第二步:挑选相应图标并获取类名,应用于页面:</h3>
<pre><code class="language-html">&lt;span class="iconfont icon-xxx"&gt;&lt;/span&gt;
</code></pre>
<blockquote>
<p>"
iconfont" 是你项目下的 font-family。可以通过编辑项目查看默认是 "iconfont"。</p>
</blockquote>
</div>
</div>
<div class="content symbol">
<ul class="icon_lists dib-box">
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-xiangyouxuanzhuan"></use>
</svg>
<div class="name">向右旋转</div>
<div class="code-name">#icon-xiangyouxuanzhuan</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-tupian"></use>
</svg>
<div class="name">图片</div>
<div class="code-name">#icon-tupian</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-suo"></use>
</svg>
<div class="name"></div>
<div class="code-name">#icon-suo</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-juxing"></use>
</svg>
<div class="name">矩形</div>
<div class="code-name">#icon-juxing</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-wenben"></use>
</svg>
<div class="name">文本</div>
<div class="code-name">#icon-wenben</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-button"></use>
</svg>
<div class="name">按钮</div>
<div class="code-name">#icon-button</div>
</li>
</ul>
<div class="article markdown">
<h2 id="symbol-">Symbol 引用</h2>
<hr>
<p>这是一种全新的使用方式,应该说这才是未来的主流,也是平台目前推荐的用法。相关介绍可以参考这篇<a href="">文章</a>
这种用法其实是做了一个 SVG 的集合,与另外两种相比具有如下特点:</p>
<ul>
<li>支持多色图标了,不再受单色限制。</li>
<li>通过一些技巧,支持像字体那样,通过 <code>font-size</code>, <code>color</code> 来调整样式。</li>
<li>兼容性较差,支持 IE9+,及现代浏览器。</li>
<li>浏览器渲染 SVG 的性能一般,还不如 png。</li>
</ul>
<p>使用步骤如下:</p>
<h3 id="-symbol-">第一步:引入项目下面生成的 symbol 代码:</h3>
<pre><code class="language-html">&lt;script src="./iconfont.js"&gt;&lt;/script&gt;
</code></pre>
<h3 id="-css-">第二步:加入通用 CSS 代码(引入一次就行):</h3>
<pre><code class="language-html">&lt;style&gt;
.icon {
width: 1em;
height: 1em;
vertical-align: -0.15em;
fill: currentColor;
overflow: hidden;
}
&lt;/style&gt;
</code></pre>
<h3 id="-">第三步:挑选相应图标并获取类名,应用于页面:</h3>
<pre><code class="language-html">&lt;svg class="icon" aria-hidden="true"&gt;
&lt;use xlink:href="#icon-xxx"&gt;&lt;/use&gt;
&lt;/svg&gt;
</code></pre>
</div>
</div>
</div>
</div>
<script>
$(document).ready(function () {
$('.tab-container .content:first').show()
$('#tabs li').click(function (e) {
var tabContent = $('.tab-container .content')
var index = $(this).index()
if ($(this).hasClass('active')) {
return
} else {
$('#tabs li').removeClass('active')
$(this).addClass('active')
tabContent.hide().eq(index).fadeIn()
}
})
})
</script>
</body>
</html>

View File

@ -1,123 +0,0 @@
<template>
<div class="animation-list">
<div class="div-animation">
<el-button @click="isShowAnimation = true">添加动画</el-button>
<el-button @click="previewAnimate">预览动画</el-button>
<div>
<el-tag
v-for="(tag, index) in curComponent.animations"
:key="index"
closable
@close="removeAnimation(index)"
>
{{ tag.label }}
</el-tag>
</div>
</div>
<!-- 选择动画 -->
<Modal v-model="isShowAnimation">
<el-tabs v-model="animationActiveName">
<el-tab-pane
v-for="item in animationClassData"
:key="item.label"
:label="item.label"
:name="item.label"
>
<el-scrollbar class="animate-container">
<div
v-for="(animate, index) in item.children"
:key="index"
class="animate"
@mouseover="hoverPreviewAnimate = animate.value"
@click="addAnimation(animate)"
>
<div :class="[hoverPreviewAnimate === animate.value && animate.value + ' animated']">
{{ animate.label }}
</div>
</div>
</el-scrollbar>
</el-tab-pane>
</el-tabs>
</Modal>
</div>
</template>
<script>
import Modal from '@/components/canvas/components/Modal'
import eventBus from '@/components/canvas/utils/eventBus'
import animationClassData from '@/components/canvas/utils/animationClassData'
import { mapState } from 'vuex'
export default {
components: { Modal },
data() {
return {
isShowAnimation: false,
hoverPreviewAnimate: '',
animationActiveName: '进入',
animationClassData,
showAnimatePanel: false
}
},
computed: mapState([
'curComponent'
]),
methods: {
addAnimation(animate) {
this.$store.commit('addAnimation', animate)
this.isShowAnimation = false
},
previewAnimate() {
eventBus.$emit('runAnimation')
},
removeAnimation(index) {
this.$store.commit('removeAnimation', index)
}
}
}
</script>
<style lang="scss">
.animation-list {
.div-animation {
text-align: center;
& > div {
margin-top: 20px;
}
.el-tag {
display: block;
width: 50%;
margin: auto;
margin-bottom: 10px;
}
}
.el-scrollbar__view {
display: flex;
align-items: center;
flex-wrap: wrap;
padding-left: 10px;
.animate > div {
width: 100px;
height: 60px;
background: #f5f8fb;
display: flex;
align-items: center;
justify-content: center;
margin: 0 12px;
margin-bottom: 10px;
font-size: 12px;
color: #333;
border-radius: 3px;
user-select: none;
cursor: pointer;
}
}
}
</style>

View File

@ -1,153 +0,0 @@
<!-- TODO: 这个页面后续将用 JSX 重构 -->
<template>
<div class="attr-list">
<el-form>
<el-form-item
v-for="(key, index) in styleKeys.filter(item => item != 'rotate')"
:key="index"
:label="map[key]"
>
<el-color-picker
v-if="key == 'borderColor'"
v-model="curComponent.style[key]"
/>
<el-color-picker
v-else-if="key == 'color'"
v-model="curComponent.style[key]"
/>
<el-color-picker
v-else-if="key == 'backgroundColor'"
v-model="curComponent.style[key]"
/>
<el-select
v-else-if="selectKey.includes(key)"
v-model="curComponent.style[key]"
>
<template v-if="key == 'textAlign'">
<el-option
v-for="item in textAlignOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</template>
<template v-else-if="key == 'borderStyle'">
<el-option
v-for="item in borderStyleOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</template>
<template v-else>
<el-option
v-for="item in verticalAlignOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</template>
</el-select>
<el-input
v-else
v-model="curComponent.style[key]"
type="number"
/>
</el-form-item>
<el-form-item
v-if="curComponent && !excludes.includes(curComponent.component)"
:label="$t('panel.content')"
>
<el-input
v-model="curComponent.propValue"
type="textarea"
/>
</el-form-item>
</el-form>
</div>
</template>
<script>
export default {
data() {
return {
excludes: ['Picture', 'Group', 'user-view'], //
textAlignOptions: [
{
label: this.$t('panel.text_align_left'),
value: 'left'
},
{
label: this.$t('panel.text_align_center'),
value: 'center'
},
{
label: this.$t('panel.text_align_right'),
value: 'right'
}
],
borderStyleOptions: [
{
label: this.$t('panel.border_style_solid'),
value: 'solid'
},
{
label: this.$t('panel.border_style_dashed'),
value: 'dashed'
}
],
verticalAlignOptions: [
{
label: this.$t('panel.vertical_align_top'),
value: 'top'
},
{
label: this.$t('panel.vertical_align_middle'),
value: 'middle'
},
{
label: this.$t('panel.vertical_align_bottom'),
value: 'bottom'
}
],
selectKey: ['textAlign', 'borderStyle', 'verticalAlign'],
map: {
left: this.$t('panel.left'),
top: this.$t('panel.top'),
height: this.$t('panel.height'),
width: this.$t('panel.width'),
color: this.$t('panel.color'),
backgroundColor: this.$t('panel.backgroundColor'),
borderStyle: this.$t('panel.borderStyle'),
borderWidth: this.$t('panel.borderWidth'),
borderColor: this.$t('panel.borderColor'),
borderRadius: this.$t('panel.borderRadius'),
fontSize: this.$t('panel.fontSize'),
fontWeight: this.$t('panel.fontWeight'),
lineHeight: this.$t('panel.lineHeight'),
letterSpacing: this.$t('panel.letterSpacing'),
textAlign: this.$t('panel.textAlign'),
opacity: this.$t('panel.opacity'),
verticalAlign: this.$t('panel.verticalAlign')
}
}
},
computed: {
styleKeys() {
return this.$store.state.curComponent ? Object.keys(this.$store.state.curComponent.style) : []
},
curComponent() {
return this.$store.state.curComponent
}
}
}
</script>
<style lang="scss" scoped>
.attr-list {
overflow: auto;
padding: 20px;
padding-top: 0;
height: 100%;
}
</style>

View File

@ -1,204 +0,0 @@
<!-- TODO: 这个页面后续将用 JSX 重构 -->
<template>
<div class="attr-list">
<el-form
label-width="80px"
size="mini"
>
<el-form-item
v-for="(key, index) in styleKeys.filter(item => styleFilter.includes(item))"
:key="index"
:label="map[key]+':'"
>
<el-color-picker
v-if="key == 'borderColor'"
v-model="curComponent.style[key]"
/>
<el-color-picker
v-else-if="key == 'color'"
v-model="curComponent.style[key]"
/>
<el-color-picker
v-else-if="key == 'backgroundColor'"
v-model="curComponent.style[key]"
/>
<el-select
v-else-if="selectKey.includes(key)"
v-model="curComponent.style[key]"
>
<template v-if="key == 'textAlign'">
<el-option
v-for="item in textAlignOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</template>
<template v-else-if="key == 'borderStyle'">
<el-option
v-for="item in borderStyleOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</template>
<template v-else>
<el-option
v-for="item in verticalAlignOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</template>
</el-select>
<el-input
v-else
v-model="curComponent.style[key]"
type="number"
/>
</el-form-item>
<el-form-item :label="$t('panel.content_style')+':'">
<div
v-if="curComponent.type==='v-text'"
style="width: 100%;max-height: 400px;overflow: auto"
>
<VText
style="border: 1px solid #dcdfe6;border-radius:4px;background-color: #f7f8fa;"
:prop-value="curComponent.propValue"
:element="curComponent"
:edit-mode="'edit'"
:style="getComponentStyleDefault(curComponent.style)"
/>
</div>
<rect-shape
v-if="curComponent.type==='rect-shape'"
style="width: 200px!important;height: 100px!important;"
:prop-value="curComponent.propValue"
:element="curComponent"
:style="getComponentStyleDefault(curComponent.style)"
/>
</el-form-item>
</el-form>
</div>
</template>
<script>
import VText from '@/components/canvas/customComponent/VText'
import RectShape from '@/components/canvas/customComponent/RectShape'
import { getStyle } from '@/components/canvas/utils/style'
export default {
components: { VText, RectShape },
data() {
return {
excludes: ['Picture', 'Group', 'view'], //
textAlignOptions: [
{
label: this.$t('panel.text_align_left'),
value: 'left'
},
{
label: this.$t('panel.text_align_center'),
value: 'center'
},
{
label: this.$t('panel.text_align_right'),
value: 'right'
}
],
borderStyleOptions: [
{
label: this.$t('panel.border_style_solid'),
value: 'solid'
},
{
label: this.$t('panel.border_style_dashed'),
value: 'dashed'
}
],
verticalAlignOptions: [
{
label: this.$t('panel.vertical_align_top'),
value: 'top'
},
{
label: this.$t('panel.vertical_align_middle'),
value: 'middle'
},
{
label: this.$t('panel.vertical_align_bottom'),
value: 'bottom'
}
],
selectKey: ['textAlign', 'borderStyle', 'verticalAlign'],
map: {
left: this.$t('panel.left'),
top: this.$t('panel.top'),
height: this.$t('panel.height'),
width: this.$t('panel.width'),
color: this.$t('panel.color'),
backgroundColor: this.$t('panel.backgroundColor'),
borderStyle: this.$t('panel.borderStyle'),
borderWidth: this.$t('panel.borderWidth'),
borderColor: this.$t('panel.borderColor'),
borderRadius: this.$t('panel.borderRadius'),
fontSize: this.$t('panel.fontSize'),
fontWeight: this.$t('panel.fontWeight'),
lineHeight: this.$t('panel.lineHeight'),
letterSpacing: this.$t('panel.letterSpacing'),
textAlign: this.$t('panel.textAlign'),
opacity: this.$t('panel.opacity'),
verticalAlign: this.$t('panel.verticalAlign')
}
}
},
computed: {
styleKeys() {
return this.$store.state.curComponent ? Object.keys(this.$store.state.curComponent.style) : []
},
curComponent() {
return this.$store.state.curComponent
},
styleFilter() {
const filter = [
'fontSize',
'fontWeight',
'lineHeight',
'letterSpacing',
'textAlign',
'color',
'borderColor',
'borderWidth',
'backgroundColor',
'borderStyle',
'verticalAlign'
]
if (this.$store.state.curComponent.type === 'v-text') {
filter.push('width', 'height')
}
return filter
}
},
methods: {
getComponentStyleDefault(style) {
if (this.$store.state.curComponent.type === 'v-text') {
return getStyle(style, ['top', 'left', 'rotate'])
} else {
return getStyle(style, ['top', 'left', 'rotate', 'height', 'width'])
}
// return style
}
}
}
</script>
<style lang="scss" scoped>
.attr-list {
overflow: auto;
padding: 5px;
padding-top: 0;
height: 100%;
}
</style>

View File

@ -1,73 +0,0 @@
<template>
<div
class="component-list"
@dragstart="handleDragStart"
>
<div
v-for="(item, index) in componentList"
:key="index"
class="list"
draggable
:data-index="index"
>
<span
class="iconfont"
:class="'icon-' + item.icon"
/>
<span>{{ item.label }}</span>
</div>
</div>
</template>
<script>
import componentList from '@/components/canvas/customComponent/component-list'
export default {
data() {
return {
componentList
}
},
methods: {
handleDragStart(e) {
e.dataTransfer.setData('index', e.target.dataset.index)
}
}
}
</script>
<style lang="scss" scoped>
.component-list {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
padding: 10px;
.list {
width: 45%;
border: 1px solid #ddd;
cursor: grab;
margin-bottom: 10px;
text-align: center;
color: #333;
padding: 2px 5px;
display: flex;
align-items: center;
justify-content: center;
&:active {
cursor: grabbing;
}
.iconfont {
margin-right: 4px;
font-size: 20px;
}
.icon-wenben,
.icon-tupian {
font-size: 18px;
}
}
}
</style>

View File

@ -1,99 +0,0 @@
<template>
<div class="event-list">
<div class="div-events">
<el-button @click="isShowEvent = true">添加事件</el-button>
<div>
<el-tag
v-for="event in Object.keys(curComponent.events)"
:key="event"
closable
@close="removeEvent(event)"
>
{{ event }}
</el-tag>
</div>
</div>
<!-- 选择事件 -->
<Modal v-model="isShowEvent">
<el-tabs v-model="eventActiveName">
<el-tab-pane
v-for="item in eventList"
:key="item.key"
:label="item.label"
:name="item.key"
style="padding: 0 20px"
>
<el-input
v-if="item.key == 'redirect'"
v-model="item.param"
type="textarea"
placeholder="请输入完整的 URL"
/>
<el-input
v-if="item.key == 'alert'"
v-model="item.param"
type="textarea"
placeholder="请输入要 alert 的内容"
/>
<el-button
style="margin-top: 20px;"
@click="addEvent(item.key, item.param)"
>确定</el-button>
</el-tab-pane>
</el-tabs>
</Modal>
</div>
</template>
<script>
import { mapState } from 'vuex'
import Modal from '@/components/canvas/components/Modal'
import { eventList } from '@/components/canvas/utils/events'
export default {
components: { Modal },
data() {
return {
isShowEvent: false,
eventURL: '',
eventActiveName: 'redirect',
eventList
}
},
computed: mapState([
'curComponent'
]),
methods: {
addEvent(event, param) {
this.isShowEvent = false
this.$store.commit('addEvent', { event, param })
},
removeEvent(event) {
this.$store.commit('removeEvent', event)
}
}
}
</script>
<style lang="scss" scoped>
.event-list {
.div-events {
text-align: center;
padding: 0 20px;
.el-button {
display: inline-block;
margin-bottom: 10px;
}
.el-tag {
display: block;
width: 50%;
margin: auto;
margin-bottom: 10px;
}
}
}
</style>

View File

@ -1,56 +0,0 @@
<template>
<div
v-if="show"
class="modal-bg"
@click="hide"
>
<div
class="fadeInLeft animated modal"
@click="stopPropagation"
>
<slot />
</div>
</div>
</template>
<script>
export default {
model: {
prop: 'show',
event: 'change'
},
props: {
show: {
type: Boolean,
default: false
}
},
methods: {
hide() {
this.$emit('change')
},
stopPropagation(e) {
e.stopPropagation()
}
}
}
</script>
<style lang="scss" scoped>
.modal-bg {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0,0,0,.5);
z-index: 1001;
.modal {
width: 400px;
background: #fff;
height: 100%;
}
}
</style>

View File

@ -138,6 +138,18 @@
<span class="icon iconfont icon-icon_clear_outlined icon16" />
<span class="text14 margin-left8">{{ $t('panel.clean_canvas') }}</span>
</el-dropdown-item>
<el-dropdown-item
v-if="showWatermarkSetting"
>
<span class="icon iconfont icon-WATERMARK icon16" />
<span class="text14 margin-left8">{{ $t('panel.watermark') }}</span>
<el-switch
v-model="panelInfo.watermarkOpen"
:class="[{['grid-active']: panelInfo.watermarkOpen},'margin-left8']"
size="mini"
@change="styleChange"
/>
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</span>
@ -250,6 +262,9 @@ export default {
}
},
computed: {
showWatermarkSetting() {
return this.panelInfo.watermarkInfo && this.panelInfo.watermarkInfo.settingContent.enable && this.panelInfo.watermarkInfo.settingContent.enablePanelCustom
},
panelInfo() {
return this.$store.state.panel.panelInfo
},
@ -428,9 +443,10 @@ export default {
if (_this.$store.state.cacheStyleChangeTimes > 0) {
const requestInfo = _this.savePrepare()
const cacheRequest = {
...this.panelInfo,
...deepCopy(this.panelInfo),
...requestInfo
}
cacheRequest.watermarkInfo.settingContent = JSON.stringify(this.panelInfo.watermarkInfo.settingContent)
saveCache(cacheRequest)
_this.$store.state.cacheStyleChangeTimes = 0
}
@ -440,6 +456,7 @@ export default {
//
const requestInfo = {
id: this.panelInfo.id,
watermarkOpen: this.panelInfo.watermarkOpen,
panelStyle: JSON.stringify(this.canvasStyleData),
panelData: JSON.stringify(this.componentData)
}
@ -610,6 +627,9 @@ export default {
}
})
this.cancelMobileLayoutStatue(sourceComponentData)
},
styleChange() {
this.$store.commit('canvasChange')
}
}
}

View File

@ -3,7 +3,16 @@
v-show="existLinkage"
class="bar-main"
>
<div>
<div
v-show="isPublicLink && !isNewBlank"
class="bar-main-left"
>
<el-button
size="mini"
@click="back2Last"
><i class="icon iconfont el-icon-back" />{{ $t('chart.back') }}</el-button>
</div>
<div class="bar-main-right">
<el-button
size="mini"
type="warning"
@ -28,6 +37,12 @@ export default {
})
return linkageFiltersCount
},
isPublicLink() {
return this.$router.currentRoute.path === '/delink'
},
isNewBlank() {
return window.history.length === 1
},
...mapState([
'componentData'
])
@ -36,23 +51,39 @@ export default {
clearAllLinkage() {
this.$store.commit('clearPanelLinkageInfo')
bus.$emit('clear_panel_linkage', { viewId: 'all' })
},
back2Last() {
this.$router.back(-1)
}
}
}
</script>
<style lang="scss" scoped>
.bar-main{
position: absolute;
.bar-main {
display: flex;
div {
position: absolute;
z-index: 10;
height: 20px;
border-radius:2px;
padding-left: 3px;
padding-right: 0px;
cursor:pointer!important;
}
}
.bar-main-right{
right: 0px;
z-index: 10;
height: 20px;
border-radius:2px;
padding-left: 3px;
padding-right: 0px;
cursor:pointer!important;
opacity: 0.8;
/*background-color: #0a7be0;*/
}
.bar-main-left {
left: 0px;
opacity: 0;
height: fit-content;
&:hover {
opacity: 0.8;
}
}
</style>

View File

@ -11,6 +11,7 @@
:terminal="terminal"
:element="config"
:canvas-id="canvasId"
:chart="chart"
:show-position="showPosition"
@showViewDetails="showViewDetails"
/>
@ -65,6 +66,7 @@
:screen-shot="screenShot"
:canvas-style-data="canvasStyleData"
:show-position="showPosition"
@fill-chart-2-parent="setChartData"
/>
</div>
</div>
@ -146,7 +148,8 @@ export default {
},
data() {
return {
previewVisible: false
previewVisible: false,
chart: null
}
},
computed: {
@ -211,6 +214,9 @@ export default {
runAnimation(this.$el, this.config.animations)
},
methods: {
setChartData(chart) {
this.chart = chart
},
getStyle,
getShapeStyleIntDeDrag(style, prop) {
if (prop === 'rotate') {
@ -342,7 +348,7 @@ export default {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
width: 100% !important;
height: 100% !important;
}
</style>

View File

@ -107,6 +107,7 @@
:canvas-style-data="canvasStyleData"
@input="handleInput"
@trigger-plugin-edit="pluginEditHandler"
@fill-chart-2-parent="setChartData"
/>
</de-drag>
<!--拖拽阴影部分-->
@ -162,7 +163,7 @@ import UserViewDialog from '@/components/canvas/customComponent/UserViewDialog'
import DeOutWidget from '@/components/dataease/DeOutWidget'
import DragShadow from '@/components/deDrag/Shadow'
import bus from '@/utils/bus'
import LinkJumpSet from '@/views/panel/LinkJumpSet'
import LinkJumpSet from '@/views/panel/linkJumpSet'
import { buildFilterMap, buildViewKeyMap, formatCondition, valueValid, viewIdMatch } from '@/utils/conditionUtil'
//
import _ from 'lodash'
@ -931,7 +932,7 @@ export default {
return !this.linkageSettingStatus && !this.batchOptStatus
},
showGrid() {
if (this.canvasStyleData && this.canvasStyleData.aidedDesign) {
if (this.canvasStyleData && this.canvasStyleData.aidedDesign && this.canvasId === 'canvas-main') {
return this.canvasStyleData.aidedDesign.showGrid
} else {
return false
@ -1096,6 +1097,13 @@ export default {
created() {
},
methods: {
setChartData(chart) {
this.componentData.forEach((item, index) => {
if (item.type === 'view' && item.component === 'user-view' && item.propValue.viewId === chart.id) {
this.$refs['deDragRef'][index].setChartData(chart)
}
})
},
triggerResetButton() {
this.triggerSearchButton(true)
},

View File

@ -94,7 +94,7 @@
>
<i
class="icon iconfont icon-shezhi"
style="margin-top:2px"
style="margin-top:2px; width: 16px;"
/>
</span>
</setting-menu>
@ -140,6 +140,11 @@
<i class="icon iconfont icon-com-jump" />
</a>
</span>
<map-layer-controller
v-if="chart && showMapLayerController"
:chart="chart"
/>
</div>
<!--跳转设置-->
@ -182,12 +187,13 @@ import bus from '@/utils/bus'
import SettingMenu from '@/components/canvas/components/editor/SettingMenu'
import LinkageField from '@/components/canvas/components/editor/LinkageField'
import toast from '@/components/canvas/utils/toast'
import FieldsList from '@/components/canvas/components/editor/fieldsList'
import LinkJumpSet from '@/views/panel/LinkJumpSet'
import FieldsList from '@/components/canvas/components/editor/FieldsList'
import LinkJumpSet from '@/views/panel/linkJumpSet'
import Background from '@/views/background/index'
import MapLayerController from '@/views/chart/components/map/MapLayerController'
export default {
components: { Background, LinkJumpSet, FieldsList, SettingMenu, LinkageField },
components: { Background, LinkJumpSet, FieldsList, SettingMenu, LinkageField, MapLayerController },
props: {
canvasId: {
@ -226,6 +232,10 @@ export default {
type: String,
required: false,
default: 'NotProvided'
},
chart: {
type: Object,
default: null
}
},
data() {
@ -249,6 +259,13 @@ export default {
},
computed: {
yaxis() {
if (!this.chart) return []
return JSON.parse(this.chart.yaxis)
},
showMapLayerController() {
return this.curComponent.type === 'view' && this.terminal === 'pc' && this.curComponent.propValue.innerType === 'map' && this.yaxis.length > 1
},
detailsShow() {
return this.curComponent.type === 'view' && this.terminal === 'pc' && this.curComponent.propValue.innerType !== 'richTextView'
},
@ -519,7 +536,7 @@ export default {
background-color: var(--primary, #3370ff);
}
.bar-main i {
.bar-main ::v-deep i {
color: white;
float: right;
margin-right: 3px;

View File

@ -1,148 +0,0 @@
<template>
<el-popover
ref="popover"
width="340"
trigger="click"
>
<el-row>
<el-form
ref="form"
size="mini"
label-width="70px"
>
<el-form-item :label="$t('panel.enable_jump')">
<el-switch
v-model="linkInfo.enable"
size="mini"
/>
<span
v-show="linkInfo.enable"
style="color: #909399; font-size: 8px;margin-left: 3px"
>
Tips:{{ $t('panel.link_open_tips') }}
</span>
</el-form-item>
<el-form-item :label="$t('panel.open_mode')">
<el-radio-group
v-model="linkInfo.openMode"
:disabled="!linkInfo.enable"
>
<el-radio label="_blank">{{ $t('panel.new_window') }}</el-radio>
<el-radio label="_self">{{ $t('panel.now_window') }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item :label="$t('panel.hyperLinks')">
<el-input
v-model="linkInfo.content"
:disabled="!linkInfo.enable"
/>
</el-form-item>
<el-form-item>
<el-button
type="primary"
@click="onSubmit"
>{{ $t('panel.confirm') }}</el-button>
<el-button @click="onClose">{{ $t('panel.cancel') }}</el-button>
</el-form-item>
</el-form>
</el-row>
<i
slot="reference"
class="icon iconfont icon-font icon-chaolianjie1"
/>
</el-popover>
</template>
<script>
import { mapState } from 'vuex'
import { deepCopy } from '@/components/canvas/utils/utils'
import { checkAddHttp } from '@/utils/urlUtils'
export default {
props: {
linkInfo: {
type: Object,
required: true
}
},
data() {
return {
componentType: null,
linkageActiveStatus: false,
editFilter: [
'view',
'custom'
]
}
},
computed: {
...mapState([
'curComponent'
])
},
methods: {
onSubmit() {
this.linkInfo.content = checkAddHttp(this.linkInfo.content)
this.curComponent.hyperlinks = deepCopy(this.linkInfo)
this.$store.commit('canvasChange')
this.popoverClose()
},
onClose() {
this.$emit('close')
this.popoverClose()
},
popoverClose() {
this.$refs.popover.showPopper = false
}
}
}
</script>
<style lang="scss" scoped>
.slot-class{
color: white;
}
.bottom {
margin-top: 20px;
text-align: center;
}
.ellip{
/*width: 100%;*/
margin-left: 10px;
margin-right: 10px;
overflow: hidden;/*超出部分隐藏*/
white-space: nowrap;/*不换行*/
text-overflow:ellipsis;/*超出部分文字以...显示*/
background-color: #f7f8fa;
color: #3d4d66;
font-size: 12px;
line-height: 24px;
height: 24px;
border-radius: 3px;
}
.select-filed{
/*width: 100%;*/
margin-left: 10px;
margin-right: 10px;
overflow: hidden;/*超出部分隐藏*/
white-space: nowrap;/*不换行*/
text-overflow:ellipsis;/*超出部分文字以...显示*/
color: #3d4d66;
font-size: 12px;
line-height: 35px;
height: 35px;
border-radius: 3px;
}
::v-deep .el-popover{
height: 200px;
overflow: auto;
}
.icon-font{
color: white;
}
</style>

View File

@ -1,5 +1,6 @@
<template>
<div
:id="previewMainDomId"
class="bg"
:style="customStyle"
@scroll="canvasScroll"
@ -72,6 +73,8 @@ import CanvasOptBar from '@/components/canvas/components/editor/CanvasOptBar'
import bus from '@/utils/bus'
import { buildFilterMap, buildViewKeyMap, formatCondition, valueValid, viewIdMatch } from '@/utils/conditionUtil'
import { hasDataPermission } from '@/utils/permission'
import { activeWatermark } from '@/components/canvas/tools/watermark'
import { userLoginInfo } from '@/api/systemInfo/userLogin'
const erd = elementResizeDetectorMaker()
@ -141,6 +144,7 @@ export default {
},
data() {
return {
previewMainDomId: 'preview-main-' + this.canvasId,
previewDomId: 'preview-' + this.canvasId,
previewRefId: 'preview-ref-' + this.canvasId,
previewTempDomId: 'preview-temp-' + this.canvasId,
@ -291,6 +295,7 @@ export default {
this.$cancelRequest('/static-resource/**')
},
mounted() {
this.initWatermark()
this._isMobile()
this.initListen()
this.$store.commit('clearLinkageSettingInfo', false)
@ -309,6 +314,14 @@ export default {
bus.$off('trigger-reset-button', this.triggerResetButton)
},
methods: {
initWatermark() {
if (this.panelInfo.watermarkInfo) {
userLoginInfo().then(res => {
const userInfo = res.data
activeWatermark(this.panelInfo.watermarkInfo.settingContent, userInfo, 'preview-main-canvas-main', this.canvasId, this.panelInfo.watermarkOpen)
})
}
},
isMainCanvas() {
return this.canvasId === 'canvas-main'
},

View File

@ -1,295 +0,0 @@
<template>
<div
class="bg"
:style="customStyle"
>
<canvas-opt-bar />
<div
id="canvasInfoMain"
ref="canvasInfoMain"
style="width: 100%;height: 100%"
>
<div
id="canvasInfoTemp"
ref="canvasInfoTemp"
:style="[{height:mainHeight},screenShotStyle]"
class="main-class"
@mouseup="deselectCurComponent"
@mousedown="handleMouseDown"
>
<el-row
v-if="componentDataShow.length===0"
style="height: 100%;"
class="custom-position"
>
{{ $t('panel.panelNull') }}
</el-row>
<ComponentWrapper
v-for="(item, index) in componentDataInfo"
:key="index"
:canvas-id="canvasId"
:config="item"
:search-count="searchCount"
:canvas-style-data="canvasStyleData"
:in-screen="inScreen"
/>
</div>
</div>
</div>
</template>
<script>
import { getStyle } from '@/components/canvas/utils/style'
import { mapState } from 'vuex'
import ComponentWrapper from './ComponentWrapper'
import { changeStyleWithScale } from '@/components/canvas/utils/translate'
import { uuid } from 'vue-uuid'
import { deepCopy, imgUrlTrans } from '@/components/canvas/utils/utils'
import eventBus from '@/components/canvas/utils/eventBus'
import elementResizeDetectorMaker from 'element-resize-detector'
import CanvasOptBar from '@/components/canvas/components/editor/CanvasOptBar'
export default {
components: { ComponentWrapper, CanvasOptBar },
model: {
prop: 'show',
event: 'change'
},
props: {
canvasId: {
type: String,
required: true
},
screenShot: {
type: Boolean,
default: false
},
show: {
type: Boolean,
default: false
},
showType: {
type: String,
required: false,
default: 'full'
},
inScreen: {
type: Boolean,
required: false,
default: true
}
},
data() {
return {
isShowPreview: false,
panelId: '',
needToChangeHeight: [
'top',
'height'
],
needToChangeWidth: [
'left',
'width',
'fontSize',
'borderWidth',
'letterSpacing'
],
scaleWidth: '100',
scaleHeight: '100',
timer: null,
componentDataShow: [],
mainWidth: '100%',
mainHeight: '100%',
searchCount: 0
}
},
computed: {
customStyle() {
let style = {
width: '100%'
}
if (this.canvasStyleData.openCommonStyle) {
if (this.canvasStyleData.panel.backgroundType === 'image' && this.canvasStyleData.panel.imageUrl) {
style = {
background: `url(${imgUrlTrans(this.canvasStyleData.panel.imageUrl)}) no-repeat`,
...style
}
} else if (this.canvasStyleData.panel.backgroundType === 'color') {
style = {
background: this.canvasStyleData.panel.color,
...style
}
}
}
return style
},
screenShotStyle() {
return this.screenShot ? this.customStyle : {}
},
// componentData mapState
componentDataInfo() {
return this.componentDataShow
},
...mapState([
'isClickComponent',
'curComponent',
'componentData',
'canvasStyleData',
'componentGap'
])
},
watch: {
componentData: {
handler(newVal, oldVla) {
this.restore()
},
deep: true
},
canvasStyleData: {
handler(newVal, oldVla) {
this.canvasStyleDataInit()
},
deep: true
}
},
mounted() {
const _this = this
const erd = elementResizeDetectorMaker()
// div
const mainDom = document.getElementById('canvasInfoMain')
erd.listenTo(mainDom, element => {
_this.$nextTick(() => {
_this.restore()
})
})
// div
const tempCanvas = document.getElementById('canvasInfoTemp')
erd.listenTo(tempCanvas, element => {
_this.$nextTick(() => {
// mainHeight px html2canvas
_this.mainHeight = tempCanvas.scrollHeight + 'px!important'
})
})
eventBus.$on('openChartDetailsDialog', this.openChartDetailsDialog)
_this.$store.commit('clearLinkageSettingInfo', false)
_this.canvasStyleDataInit()
},
beforeDestroy() {
eventBus.$off('openChartDetailsDialog', this.openChartDetailsDialog)
clearInterval(this.timer)
},
methods: {
canvasStyleDataInit() {
//
this.searchCount = 0
this.timer && clearInterval(this.timer)
let refreshTime = 300000
if (this.canvasStyleData.refreshTime && this.canvasStyleData.refreshTime > 0) {
if (this.canvasStyleData.refreshUnit === 'second') {
refreshTime = this.canvasStyleData.refreshTime * 1000
} else {
refreshTime = this.canvasStyleData.refreshTime * 60000
}
}
this.timer = setInterval(() => {
this.searchCount++
}, refreshTime)
},
changeStyleWithScale,
getStyle,
restore() {
const canvasHeight = document.getElementById('canvasInfoMain').offsetHeight
const canvasWidth = document.getElementById('canvasInfoMain').offsetWidth
this.scaleWidth = canvasWidth * 100 / parseInt(this.canvasStyleData.width)//
this.scaleHeight = canvasHeight * 100 / parseInt(this.canvasStyleData.height)//
this.handleScaleChange()
},
resetID(data) {
if (data) {
data.forEach(item => {
item.type !== 'custom' && (item.id = uuid.v1())
})
}
return data
},
format(value, scale) {
return value * parseInt(scale) / 100
},
handleScaleChange() {
if (this.componentData) {
const componentData = deepCopy(this.componentData)
componentData.forEach(component => {
Object.keys(component.style).forEach(key => {
if (this.needToChangeHeight.includes(key)) {
component.style[key] = this.format(component.style[key], this.scaleHeight)
}
if (this.needToChangeWidth.includes(key)) {
component.style[key] = this.format(component.style[key], this.scaleWidth)
}
})
})
this.componentDataShow = componentData
this.$nextTick(() => (eventBus.$emit('resizing', '')))
}
},
deselectCurComponent(e) {
if (!this.isClickComponent) {
this.$store.commit('setCurComponent', { component: null, index: null })
}
},
handleMouseDown() {
this.$store.commit('setClickComponentStatus', false)
}
}
}
</script>
<style lang="scss" scoped>
.bg {
padding: 5px;
min-width: 600px;
min-height: 300px;
width: 100%;
height: 100%;
overflow-x: hidden;
background-size: 100% 100% !important;
}
.main-class {
width: 100%;
height: 100%;
background-size: 100% 100% !important;
}
.custom-position {
flex: 1;
display: flex;
align-items: center;
justify-content: space-between;
font-size: 14px;
flex-flow: row nowrap;
color: #9ea6b2;
}
.gap_class {
padding: 5px;
}
.dialog-css ::v-deep .el-dialog__title {
font-size: 14px;
}
.dialog-css ::v-deep .el-dialog__header {
padding: 40px 20px 0;
}
.dialog-css ::v-deep .el-dialog__body {
padding: 10px 20px 20px;
}
::-webkit-scrollbar {
width: 0px !important;
height: 0px !important;
}
</style>

View File

@ -1,204 +0,0 @@
<template>
<div>
<div style="width: 100%;">
<el-dropdown
trigger="click"
@mouseup="handleMouseUp"
>
<el-button
ref="trackButton"
class="icon iconfont icon-shezhi"
>TEST</el-button>
<el-dropdown-menu>
<el-dropdown-item
icon="el-icon-document-copy"
@click.native="copy"
>{{ $t('panel.copy') }}</el-dropdown-item>
<el-dropdown-item
icon="el-icon-delete"
@click.native="deleteComponent"
>{{ $t('panel.delete') }}</el-dropdown-item>
<el-dropdown-item
icon="el-icon-upload2"
@click.native="topComponent"
>{{ $t('panel.topComponent') }}</el-dropdown-item>
<el-dropdown-item
icon="el-icon-download"
@click.native="bottomComponent"
>{{ $t('panel.bottomComponent') }}</el-dropdown-item>
<el-dropdown-item
icon="el-icon-arrow-up"
@click.native="upComponent"
>{{ $t('panel.upComponent') }}</el-dropdown-item>
<el-dropdown-item
icon="el-icon-arrow-down"
@click.native="downComponent"
>{{ $t('panel.downComponent') }}</el-dropdown-item>
<el-dropdown-item
icon="el-icon-link"
@click.native="linkageSetting"
>联动设置</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</div>
</div>
</template>
<script>
import { mapState } from 'vuex'
import bus from '@/utils/bus'
import { getViewLinkageGather } from '@/api/panel/linkage'
export default {
data() {
return {
copyData: null,
editFilter: [
'view',
'custom'
]
}
},
computed: mapState([
'menuTop',
'menuLeft',
'menuShow',
'curComponent',
'componentData',
'canvasStyleData'
]),
methods: {
trackButtonClick() {
this.$refs.trackButton.click()
this.$refs.trackButton.$el.click()
},
edit() {
if (this.curComponent.type === 'view') {
this.$store.dispatch('chart/setViewId', null)
this.$store.dispatch('chart/setViewId', this.curComponent.propValue.viewId)
bus.$emit('PanelSwitchComponent', { name: 'ChartEdit', param: { 'id': this.curComponent.propValue.viewId, 'optType': 'edit' }})
}
if (this.curComponent.type === 'custom') {
bus.$emit('component-dialog-edit')
}
//
if (this.curComponent.type === 'v-text' || this.curComponent.type === 'rect-shape') {
bus.$emit('component-dialog-style')
}
},
lock() {
this.$store.commit('lock')
},
unlock() {
this.$store.commit('unlock')
},
//
handleMouseUp() {
this.$store.commit('setClickComponentStatus', true)
},
cut() {
this.deleteCurCondition()
this.$store.commit('cut')
},
copy() {
this.$store.commit('copy')
this.paste()
},
paste() {
this.$store.commit('paste', true)
this.$store.commit('recordSnapshot')
},
deleteComponent() {
this.deleteCurCondition()
this.$store.commit('deleteComponent')
this.$store.commit('recordSnapshot')
this.$store.commit('setCurComponent', { component: null, index: null })
},
deleteCurCondition() {
if (this.curComponent.type === 'custom') {
this.$store.commit('removeViewFilter', this.curComponent.id)
bus.$emit('delete-condition', { componentId: this.curComponent.id })
}
},
upComponent() {
this.$store.commit('upComponent')
this.$store.commit('recordSnapshot')
},
downComponent() {
this.$store.commit('downComponent')
this.$store.commit('recordSnapshot')
},
topComponent() {
this.$store.commit('topComponent')
this.$store.commit('recordSnapshot')
},
bottomComponent() {
this.$store.commit('bottomComponent')
this.$store.commit('recordSnapshot')
},
linkageSetting() {
// sourceViewId
const targetViewIds = this.componentData.filter(item => item.type === 'view' && item.propValue && item.propValue.viewId)
.map(item => item.propValue.viewId)
//
const requestInfo = {
'panelId': this.$store.state.panel.panelInfo.id,
'sourceViewId': this.curComponent.propValue.viewId,
'targetViewIds': targetViewIds
}
getViewLinkageGather(requestInfo).then(rsp => {
this.$store.commit('setLinkageInfo', rsp.data)
})
}
}
}
</script>
<style lang="scss" scoped>
.contextmenu {
position: absolute;
z-index: 1000;
ul {
border: 1px solid #e4e7ed;
border-radius: 4px;
background-color: #fff;
box-shadow: 0 2px 12px 0 rgba(0,0,0,.1);
box-sizing: border-box;
margin: 5px 0;
padding: 6px 0;
li {
font-size: 14px;
padding: 0 20px;
position: relative;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
color: #606266;
height: 34px;
line-height: 34px;
box-sizing: border-box;
cursor: pointer;
&:hover {
background-color: var(--background-color-base, #f5f7fa);
}
}
}
}
</style>

File diff suppressed because it is too large Load Diff

View File

@ -1,69 +0,0 @@
<template>
<de-container style="height: 500px">
<de-aside-container>
this is test
</de-aside-container>
<de-main-container>
this is test2
</de-main-container>
</de-container>
</template>
<script>
import DeMainContainer from '@/components/dataease/DeMainContainer'
import DeContainer from '@/components/dataease/DeContainer'
import DeAsideContainer from '@/components/dataease/DeAsideContainer'
import { mapState } from 'vuex'
export default {
name: 'UserView',
components: { DeMainContainer, DeContainer, DeAsideContainer },
props: {
chart: {
type: Object,
default: null
},
chartTable: {
type: Object,
default: null
}
},
data() {
return {
refId: null
}
},
computed: {
...mapState([
'isClickComponent',
'curComponent',
'componentData',
'canvasStyleData'
])
},
methods: {
}
}
</script>
<style lang="scss" scoped>
.ms-aside-container {
height: 50vh;
min-width: 400px;
max-width: 400px;
padding: 0 0;
}
.ms-main-container {
height: 50vh;
border: 1px solid #E6E6E6;
border-left: 0 solid;
}
.chart-class{
height: 100%;
}
.table-class{
height: 100%;
}
</style>

View File

@ -526,6 +526,9 @@ export default {
this.chartScale(this.changeScaleIndex)
},
deep: true
},
'chart.yaxis': function(newVal, oldVal) {
this.$emit('fill-chart-2-parent', this.chart)
}
},
mounted() {
@ -711,6 +714,7 @@ export default {
// echart
if (response.success) {
this.chart = response.data
this.$emit('fill-chart-2-parent', this.chart)
this.getDataOnly(response.data, dataBroadcast)
this.chart['position'] = this.inTab ? 'tab' : 'panel'
//

View File

@ -1,158 +0,0 @@
<template>
<div class="home">
<Toolbar />
<main>
<section class="center">
<div
class="content"
@drop="handleDrop"
@dragover="handleDragOver"
@mousedown="handleMouseDown"
@mouseup="deselectCurComponent"
>
<Editor />
</div>
</section>
</main>
</div>
</template>
<script>
import Editor from '@/components/Editor/index'
import componentList from '@/components/canvas/customComponent/component-list' //
import Toolbar from '@/components/Toolbar'
import { deepCopy } from '@/utils/utils'
import { mapState } from 'vuex'
import generateID from '@/utils/generateID'
import { uuid } from 'vue-uuid'
export default {
components: { Editor, Toolbar },
data() {
return {
activeName: 'attr',
reSelectAnimateIndex: undefined
}
},
computed: mapState([
'componentData',
'curComponent',
'isClickComponent',
'canvasStyleData'
]),
created() {
this.restore()
},
methods: {
restore() {
//
if (localStorage.getItem('canvasData')) {
this.$store.commit('setComponentData', this.resetID(JSON.parse(localStorage.getItem('canvasData'))))
}
if (localStorage.getItem('canvasStyle')) {
this.$store.commit('setCanvasStyle', JSON.parse(localStorage.getItem('canvasStyle')))
}
},
resetID(data) {
if (data) {
data.forEach(item => {
item.type !== 'custom' && (item.id = uuid.v1())
})
}
return data
},
handleDrop(e) {
e.preventDefault()
e.stopPropagation()
let component
const id = e.dataTransfer.getData('componentId')
componentList.forEach(componentTemp => {
if (id === componentTemp.id) {
component = deepCopy(componentTemp)
}
})
// const component = deepCopy(componentList[e.dataTransfer.getData('index')])
component.style.top = e.offsetY
component.style.left = e.offsetX
component.id = generateID()
this.$store.commit('addComponent', { component })
this.$store.commit('recordSnapshot', 'handleDrop')
},
handleDragOver(e) {
e.preventDefault()
e.dataTransfer.dropEffect = 'copy'
},
handleMouseDown() {
this.$store.commit('setClickComponentStatus', false)
},
deselectCurComponent(e) {
if (!this.isClickComponent) {
this.$store.commit('setCurComponent', { component: null, index: null })
}
// 0 1 2
if (e.button !== 2) {
this.$store.commit('hideContextMenu')
}
}
}
}
</script>
<style lang="scss">
.home {
height: 100vh;
background: #fff;
main {
height: calc(100% - 64px);
position: relative;
.left {
position: absolute;
height: 100%;
width: 200px;
left: 0;
top: 0;
padding-top: 10px;
}
.right {
position: absolute;
height: 100%;
width: 262px;
right: 0;
top: 0;
}
.center {
margin-left: 200px;
margin-right: 262px;
background: #f5f5f5;
height: 100%;
overflow: auto;
padding: 20px;
.content {
width: 100%;
height: 100%;
overflow: auto;
}
}
}
.placeholder {
text-align: center;
color: #333;
}
}
</style>

View File

@ -1,52 +0,0 @@
body,
button,
input,
p,
li,
ol,
ul,
div,
section,
article,
td,
th,
span,
textarea,
form,
footer,
header,
nav,
main,
address,
aside,
pre,
canvas {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
overflow: hidden;
}
li {
list-style: none;
}
#app {
/*overflow: hidden;*/
}
.el-tabs {
height: 100%;
}
.el-tabs__content {
height: calc(100% - 55px);
overflow: auto;
}
.el-tabs__nav-scroll {
padding-left: 20px;
}

View File

@ -0,0 +1,154 @@
// 动态创建水印元素的封装函数
export function watermark(settings, domId) {
const watermarkDom = document.getElementById(domId)
// 默认设置
const defaultSettings = {
watermark_txt: '',
watermark_x: 20, // 水印起始位置x轴坐标
watermark_y: 20, // 水印起始位置Y轴坐标
watermark_rows: 20, // 水印行数
watermark_cols: 20, // 水印列数
watermark_x_space: 100, // 水印x轴间隔
watermark_y_space: 50, // 水印y轴间隔
watermark_color: '#aaa', // 水印字体颜色
watermark_alpha: 0.4, // 水印透明度
watermark_fontsize: '15px', // 水印字体大小
watermark_font: '微软雅黑', // 水印字体
watermark_width: 210, // 水印宽度
watermark_height: 80, // 水印长度
watermark_angle: 20 // 水印倾斜度数
}
// 根据函数的入参调整设置
if (settings && typeof settings === 'object') {
const src = settings || {}
for (const key in src) {
if (src[key] && defaultSettings[key] && src[key] === defaultSettings[key]) {
continue
} else if (src[key]) defaultSettings[key] = src[key]
}
}
// 创建虚拟节点对象,在该节点对象中可以放元素,最后只需在页面中添加该节点对象即可。可提高性能
const oTemp = document.createElement('p')
// 获取页面最大宽度
let page_width = watermarkDom.clientWidth
const cutWidth = page_width * 0.0150
page_width = page_width - cutWidth
// 获取页面最大高度
let page_height = watermarkDom.clientHeight - 56
page_height = page_height < 400 ? 400 : page_height
// page_height = Math.max(page_height, window.innerHeight - 30)
// 如果将水印列数设置为0或水印列数设置过大超过页面最大宽度则重新计算水印列数和水印x轴间隔
if (defaultSettings.watermark_cols === 0 || (parseInt(defaultSettings.watermark_x + defaultSettings.watermark_width * defaultSettings.watermark_cols + defaultSettings.watermark_x_space * (defaultSettings.watermark_cols - 1)) > page_width)) {
defaultSettings.watermark_cols = parseInt((page_width - defaultSettings.watermark_x + defaultSettings.watermark_x_space) / (defaultSettings.watermark_width + defaultSettings.watermark_x_space))
defaultSettings.watermark_x_space = parseInt((page_width - defaultSettings.watermark_x - defaultSettings.watermark_width * defaultSettings.watermark_cols) / (defaultSettings.watermark_cols - 1))
}
// 如果将水印行数设置为0或水印行数设置过大超过页面最大长度则重新计算水印行数和水印y轴间隔
if (defaultSettings.watermark_rows === 0 || (parseInt(defaultSettings.watermark_y + defaultSettings.watermark_height * defaultSettings.watermark_rows + defaultSettings.watermark_y_space * (defaultSettings.watermark_rows - 1)) > page_height)) {
defaultSettings.watermark_rows = parseInt((defaultSettings.watermark_y_space + page_height - defaultSettings.watermark_y) / (defaultSettings.watermark_height + defaultSettings.watermark_y_space))
defaultSettings.watermark_y_space = parseInt(((page_height - defaultSettings.watermark_y) - defaultSettings.watermark_height * defaultSettings.watermark_rows) / (defaultSettings.watermark_rows - 1))
}
defaultSettings.watermark_rows = defaultSettings.watermark_rows < 2 ? 2 : defaultSettings.watermark_rows
defaultSettings.watermark_cols = defaultSettings.watermark_cols < 2 ? 2 : defaultSettings.watermark_cols
let x
let y
for (let i = 0; i < defaultSettings.watermark_rows; i++) {
y = defaultSettings.watermark_y + (defaultSettings.watermark_y_space + defaultSettings.watermark_height) * i
for (let j = 0; j < defaultSettings.watermark_cols; j++) {
x = defaultSettings.watermark_x + (defaultSettings.watermark_width + defaultSettings.watermark_x_space) * j
const mask_div = document.createElement('div')
mask_div.id = 'mask_div' + i + j
mask_div.className = 'mask_div'
mask_div.appendChild(document.createTextNode(defaultSettings.watermark_txt))
// 设置水印div倾斜显示
mask_div.style.webkitTransform = 'rotate(-' + defaultSettings.watermark_angle + 'deg)'
mask_div.style.MozTransform = 'rotate(-' + defaultSettings.watermark_angle + 'deg)'
mask_div.style.msTransform = 'rotate(-' + defaultSettings.watermark_angle + 'deg)'
mask_div.style.OTransform = 'rotate(-' + defaultSettings.watermark_angle + 'deg)'
mask_div.style.transform = 'rotate(-' + defaultSettings.watermark_angle + 'deg)'
mask_div.style.visibility = ''
mask_div.style.position = 'absolute'
mask_div.style.left = x + 'px'
mask_div.style.top = y + 'px'
mask_div.style.overflow = 'hidden'
mask_div.style.zIndex = '9999'
// 让水印不遮挡页面的点击事件
mask_div.style.pointerEvents = 'none'
mask_div.style.opacity = defaultSettings.watermark_alpha
mask_div.style.fontSize = defaultSettings.watermark_fontsize
mask_div.style.fontFamily = defaultSettings.watermark_font
mask_div.style.color = defaultSettings.watermark_color
mask_div.style.textAlign = 'center'
mask_div.style.width = defaultSettings.watermark_width + 'px'
mask_div.style.height = defaultSettings.watermark_height + 'px'
mask_div.style.display = 'block'
oTemp.appendChild(mask_div)
}
}
oTemp.setAttribute('id', 'de-watermark-server')
watermarkDom.appendChild(oTemp)
}
export function getNow() {
const d = new Date()
const year = d.getFullYear()
const month = change(d.getMonth() + 1)
const day = change(d.getDate())
const hour = change(d.getHours())
const minute = change(d.getMinutes())
function change(t) {
if (t < 10) {
return '0' + t
} else {
return t
}
}
const time = year + '-' + month + '-' + day + ' ' + hour + ':' + minute
return time
}
export function activeWatermark(watermarkForm, userLoginInfo, domId, canvasId, watermarkOpen) {
// 清理历史水印
const historyWatermarkDom = document.getElementById('de-watermark-server')
if (historyWatermarkDom) {
historyWatermarkDom.remove()
}
if (!(canvasId === 'canvas-main' && ((watermarkForm.enable && !watermarkForm.enablePanelCustom) ||
(watermarkForm.enable && watermarkOpen)))) {
return
}
let watermark_txt
let watermark_width = 120
if (watermarkForm.type === 'custom') {
watermark_txt = watermarkForm.content
watermark_txt = watermark_txt.replaceAll('${ip}', userLoginInfo.ip)
watermark_txt = watermark_txt.replaceAll('${userName}', userLoginInfo.userInfo.userName)
watermark_txt = watermark_txt.replaceAll('${nickName}', userLoginInfo.userInfo.nickName)
watermark_txt = watermark_txt.replaceAll('${time}', getNow())
watermark_width = watermark_txt.length * watermarkForm.watermark_fontsize * 0.75
watermark_width = watermark_width > 350 ? 350 : watermark_width
} else if (watermarkForm.type === 'nickName') {
watermark_txt = userLoginInfo.userInfo.nickName
} else if (watermarkForm.type === 'ip') {
watermark_txt = userLoginInfo.ip
watermark_width = 150
} else if (watermarkForm.type === 'time') {
watermark_txt = getNow()
watermark_width = 200
} else {
watermark_txt = userLoginInfo.userInfo.userName
}
const settings = {
watermark_txt: watermark_txt,
watermark_width: watermark_width,
watermark_color: watermarkForm.watermark_color,
watermark_x_space: watermarkForm.watermark_x_space,
watermark_y_space: watermarkForm.watermark_y_space,
watermark_fontsize: watermarkForm.watermark_fontsize + 'px'
}
watermark(settings, domId)
}
export default { watermark, getNow, activeWatermark }

View File

@ -1,94 +0,0 @@
export default [
{
label: '进入',
children: [
{ label: '渐显', value: 'fadeIn' },
{ label: '向右进入', value: 'fadeInLeft' },
{ label: '向左进入', value: 'fadeInRight' },
{ label: '向上进入', value: 'fadeInUp' },
{ label: '向下进入', value: 'fadeInDown' },
{ label: '向右长距进入', value: 'fadeInLeftBig' },
{ label: '向左长距进入', value: 'fadeInRightBig' },
{ label: '向上长距进入', value: 'fadeInUpBig' },
{ label: '向下长距进入', value: 'fadeInDownBig' },
{ label: '旋转进入', value: 'rotateIn' },
{ label: '左顺时针旋转', value: 'rotateInDownLeft' },
{ label: '右逆时针旋转', value: 'rotateInDownRight' },
{ label: '左逆时针旋转', value: 'rotateInUpLeft' },
{ label: '右逆时针旋转', value: 'rotateInUpRight' },
{ label: '弹入', value: 'bounceIn' },
{ label: '向右弹入', value: 'bounceInLeft' },
{ label: '向左弹入', value: 'bounceInRight' },
{ label: '向上弹入', value: 'bounceInUp' },
{ label: '向下弹入', value: 'bounceInDown' },
{ label: '光速从右进入', value: 'lightSpeedInRight' },
{ label: '光速从左进入', value: 'lightSpeedInLeft' },
{ label: '光速从右退出', value: 'lightSpeedOutRight' },
{ label: '光速从左退出', value: 'lightSpeedOutLeft' },
{ label: 'Y轴旋转', value: 'flip' },
{ label: '中心X轴旋转', value: 'flipInX' },
{ label: '中心Y轴旋转', value: 'flipInY' },
{ label: '左长半径旋转', value: 'rollIn' },
{ label: '由小变大进入', value: 'zoomIn' },
{ label: '左变大进入', value: 'zoomInLeft' },
{ label: '右变大进入', value: 'zoomInRight' },
{ label: '向上变大进入', value: 'zoomInUp' },
{ label: '向下变大进入', value: 'zoomInDown' },
{ label: '向右滑动展开', value: 'slideInLeft' },
{ label: '向左滑动展开', value: 'slideInRight' },
{ label: '向上滑动展开', value: 'slideInUp' },
{ label: '向下滑动展开', value: 'slideInDown' }
]
},
{
label: '强调',
children: [
{ label: '弹跳', value: 'bounce' },
{ label: '闪烁', value: 'flash' },
{ label: '放大缩小', value: 'pulse' },
{ label: '放大缩小弹簧', value: 'rubberBand' },
{ label: '左右晃动', value: 'headShake' },
{ label: '左右扇形摇摆', value: 'swing' },
{ label: '放大晃动缩小', value: 'tada' },
{ label: '扇形摇摆', value: 'wobble' },
{ label: '左右上下晃动', value: 'jello' },
{ label: 'Y轴旋转', value: 'flip' }
]
},
{
label: '退出',
children: [
{ label: '渐隐', value: 'fadeOut' },
{ label: '向左退出', value: 'fadeOutLeft' },
{ label: '向右退出', value: 'fadeOutRight' },
{ label: '向上退出', value: 'fadeOutUp' },
{ label: '向下退出', value: 'fadeOutDown' },
{ label: '向左长距退出', value: 'fadeOutLeftBig' },
{ label: '向右长距退出', value: 'fadeOutRightBig' },
{ label: '向上长距退出', value: 'fadeOutUpBig' },
{ label: '向下长距退出', value: 'fadeOutDownBig' },
{ label: '旋转退出', value: 'rotateOut' },
{ label: '左顺时针旋转', value: 'rotateOutDownLeft' },
{ label: '右逆时针旋转', value: 'rotateOutDownRight' },
{ label: '左逆时针旋转', value: 'rotateOutUpLeft' },
{ label: '右逆时针旋转', value: 'rotateOutUpRight' },
{ label: '弹出', value: 'bounceOut' },
{ label: '向左弹出', value: 'bounceOutLeft' },
{ label: '向右弹出', value: 'bounceOutRight' },
{ label: '向上弹出', value: 'bounceOutUp' },
{ label: '向下弹出', value: 'bounceOutDown' },
{ label: '中心X轴旋转', value: 'flipOutX' },
{ label: '中心Y轴旋转', value: 'flipOutY' },
{ label: '左长半径旋转', value: 'rollOut' },
{ label: '由小变大退出', value: 'zoomOut' },
{ label: '左变大退出', value: 'zoomOutLeft' },
{ label: '右变大退出', value: 'zoomOutRight' },
{ label: '向上变大退出', value: 'zoomOutUp' },
{ label: '向下变大退出', value: 'zoomOutDown' },
{ label: '向左滑动收起', value: 'slideOutLeft' },
{ label: '向右滑动收起', value: 'slideOutRight' },
{ label: '向上滑动收起', value: 'slideOutUp' },
{ label: '向下滑动收起', value: 'slideOutDown' }
]
}
]

View File

@ -114,12 +114,12 @@
</template>
<script>
import SecondAndMinute from './cron/secondAndMinute'
import hour from './cron/hour'
import day from './cron/day'
import month from './cron/month'
import week from './cron/week'
import year from './cron/year'
import SecondAndMinute from './cron/SecondAndMinute'
import hour from './cron/Hour'
import day from './cron/Day'
import month from './cron/Month'
import week from './cron/Week'
import year from './cron/Year'
export default {
components: {
SecondAndMinute, hour, day, month, week, year

View File

@ -60,7 +60,6 @@
<script>
import inputStyleMixin from '@/components/widget/deWidget/inputStyleMixin'
export default {
name: 'DeOutWidget',
mixins: [inputStyleMixin],

View File

@ -1,30 +0,0 @@
<template>
<div
v-bottom-to-top-drag
class="drag-bar"
/>
</template>
<script>
export default {
name: 'DeBottom2TopDragBar'
}
</script>
<style scoped>
.drag-bar {
height: 1px;
width: 100%;
z-index: 1000;
cursor: row-resize;
position: fixed;
background-color: #E6E6E6;
border: 0px;
}
.drag-bar:hover {
height: 3px;
}
</style>

View File

@ -1,31 +0,0 @@
<template>
<div
v-right-to-left-drag
class="drag-bar"
/>
</template>
<script>
export default {
name: 'DeRight2LeftDragBar'
}
</script>
<style scoped>
.drag-bar {
height: 100%;
width: 1px;
position: absolute;
left: 0px;
top: 0;
cursor: col-resize;
background-color: #E6E6E6;
border: 0px;
}
.drag-bar:hover {
width: 3px;
}
</style>

View File

@ -39,6 +39,7 @@
:active-model="'edit'"
:canvas-id="canvasId"
:element="element"
:chart="chart"
@showViewDetails="showViewDetails"
@amRemoveItem="amRemoveItem"
@amAddItem="amAddItem"
@ -384,6 +385,7 @@ export default {
},
data: function() {
return {
chart: null,
contentDisplay: true,
// tab
parentWidthTabOffset: 40,
@ -802,6 +804,9 @@ export default {
this.beforeDestroyFunction()
},
methods: {
setChartData(chart) {
this.chart = chart
},
//
resetBoundsAndMouseState() {
this.mouseClickPosition = { mouseX: 0, mouseY: 0, x: 0, y: 0, w: 0, h: 0 }
@ -1929,6 +1934,7 @@ export default {
const nodes = this.$el.parentNode.childNodes //
for (const item of nodes) {
if (
item.tagName !== 'svg' &&
item.className !== undefined &&
!item.className.split(' ').includes(this.classNameActive) &&
item.getAttribute('tab-is-check') !== null &&
@ -2114,8 +2120,8 @@ export default {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
width: 100% !important;
height: 100% !important;
}
.drag-on-tab-collision {

View File

@ -1,32 +0,0 @@
export const on = (function() {
if (document.addEventListener) {
return function(element, event, handler) {
if (element && event && handler) {
element.addEventListener(event, handler, false)
}
}
} else {
return function(element, event, handler) {
if (element && event && handler) {
element.attachEvent('on' + event, handler)
}
}
}
})()
export const off = (function() {
if (document.removeEventListener) {
return function(element, event, handler) {
if (element && event) {
element.removeEventListener(event, handler, false)
}
}
} else {
return function(element, event, handler) {
if (element && event) {
element.detachEvent('on' + event, handler)
}
}
}
})()

View File

@ -139,6 +139,10 @@ export default {
this.innerValues = this.value
this.viewLoaded = false
this.panelId && findOne(this.panelId).then(response => {
const watermarkInfo = {
...response.data.watermarkInfo,
settingContent: JSON.parse(response.data.watermarkInfo.settingContent)
}
this.panelInfo = {
id: response.data.id,
name: response.data.name,
@ -148,7 +152,9 @@ export default {
createBy: response.data.createBy,
createTime: response.data.createTime,
updateBy: response.data.updateBy,
updateTime: response.data.updateTime
updateTime: response.data.updateTime,
watermarkOpen: response.data.watermarkOpen,
watermarkInfo: watermarkInfo
}
this.$store.dispatch('panel/setPanelInfo', this.panelInfo)
panelDataPrepare(JSON.parse(response.data.panelData), JSON.parse(response.data.panelStyle), rsp => {

View File

@ -1,19 +0,0 @@
<template>
<div>
<svg-icon
icon-class="doc"
@click="click"
/>
</div>
</template>
<script>
export default {
name: 'Doc',
methods: {
click() {
window.open(process.env.VUE_APP_BASE_API + 'doc.html', '_blank')
}
}
}
</script>

View File

@ -171,7 +171,7 @@ export default {
this.options = this.newList.slice(0, this.maxLength)
},
customInputStyle() {
if (!this.$parent.$parent.handlerInputStyle) return
if (!this.$parent.$parent.handlerInputStyle || !this.$refs.visualSelect) return
handlerInputStyle(this.$refs.visualSelect.$el.querySelector('.el-input__inner'), this.$parent.element.style)
handlerInputStyle(this.$refs.visualSelect.$el.querySelector('.el-select__input'), { wordColor: this.$parent.element.style.wordColor })
},

View File

@ -1,44 +0,0 @@
<template>
<el-tooltip :content="tooltip">
<el-button
circle
class="fu-search-bar-button"
:type="type"
:size="size"
@click="click"
>
<slot>
<i :class="icon" />
</slot>
</el-button>
</el-tooltip>
</template>
<script>
export default {
name: 'GridButton',
props: {
size: {
type: String,
default: 'mini'
},
icon: {
type: String,
default: null
},
type: {
type: String,
default: null
},
tooltip: {
type: String,
default: null
}
},
methods: {
click(e) {
this.$emit('click', e)
}
}
}
</script>

View File

@ -27,7 +27,7 @@
</template>
<script>
import tableBody from './tableBody'
import tableBody from './TableBody'
export default {
components: { tableBody },
props: {

View File

@ -1,47 +0,0 @@
<template>
<div
style="padding: 0 15px;"
@click="toggleClick"
>
<svg
:class="{'is-active':isActive}"
class="hamburger"
viewBox="0 0 1024 1024"
xmlns="http://www.w3.org/2000/svg"
width="64"
height="64"
>
<path d="M408 442h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8zm-8 204c0 4.4 3.6 8 8 8h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56zm504-486H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm0 632H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zM142.4 642.1L298.7 519a8.84 8.84 0 0 0 0-13.9L142.4 381.9c-5.8-4.6-14.4-.5-14.4 6.9v246.3a8.9 8.9 0 0 0 14.4 7z" />
</svg>
</div>
</template>
<script>
export default {
name: 'Hamburger',
props: {
isActive: {
type: Boolean,
default: false
}
},
methods: {
toggleClick() {
this.$emit('toggleClick')
}
}
}
</script>
<style scoped>
.hamburger {
display: inline-block;
vertical-align: middle;
width: 20px;
height: 20px;
}
.hamburger.is-active {
transform: rotate(180deg);
}
</style>

View File

@ -1,104 +0,0 @@
<template>
<div
:class="{'hidden':hidden}"
class="pagination-container"
>
<el-pagination
:background="background"
:current-page.sync="currentPage"
:page-size.sync="pageSize"
:layout="layout"
:page-sizes="pageSizes"
:total="total"
v-bind="$attrs"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
/>
</div>
</template>
<script>
import { scrollTo } from '@/utils/scroll-to'
export default {
name: 'Pagination',
props: {
total: {
required: true,
type: Number
},
page: {
type: Number,
default: 0
},
limit: {
type: Number,
default: 10
},
pageSizes: {
type: Array,
default() {
return [10, 20, 30, 50]
}
},
layout: {
type: String,
default: 'total, sizes, prev, pager, next, jumper'
},
background: {
type: Boolean,
default: true
},
autoScroll: {
type: Boolean,
default: true
},
hidden: {
type: Boolean,
default: false
}
},
computed: {
currentPage: {
get() {
return this.page
},
set(val) {
this.$emit('update:page', val)
}
},
pageSize: {
get() {
return this.limit
},
set(val) {
this.$emit('update:limit', val)
}
}
},
methods: {
handleSizeChange(val) {
this.$emit('pagination', { page: this.currentPage, limit: val })
if (this.autoScroll) {
scrollTo(0, 800)
}
},
handleCurrentChange(val) {
this.$emit('pagination', { page: val, limit: this.pageSize })
if (this.autoScroll) {
scrollTo(0, 800)
}
}
}
}
</script>
<style scoped>
.pagination-container {
background: #fff;
padding: 32px 16px;
}
.pagination-container.hidden {
display: none;
}
</style>

View File

@ -1,63 +0,0 @@
<template>
<div>
<svg-icon
:icon-class="isFullscreen?'exit-fullscreen':'fullscreen'"
@click="click"
/>
</div>
</template>
<script>
import screenfull from 'screenfull'
export default {
name: 'Screenfull',
data() {
return {
isFullscreen: false
}
},
mounted() {
this.init()
},
beforeDestroy() {
this.destroy()
},
methods: {
click() {
if (!screenfull.enabled) {
this.$message({
message: 'you browser can not work',
type: 'warning'
})
return false
}
screenfull.toggle()
},
change() {
this.isFullscreen = screenfull.isFullscreen
},
init() {
if (screenfull.enabled) {
screenfull.on('change', this.change)
}
},
destroy() {
if (screenfull.enabled) {
screenfull.off('change', this.change)
}
}
}
}
</script>
<style scoped>
.screenfull-svg {
display: inline-block;
cursor: pointer;
fill: #5a5e66;;
width: 20px;
height: 20px;
vertical-align: 10px;
}
</style>

View File

@ -1,67 +0,0 @@
<template>
<el-dropdown
trigger="click"
@command="handleSetSize"
>
<div>
<svg-icon
class-name="size-icon"
icon-class="size"
/>
</div>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item
v-for="item of sizeOptions"
:key="item.value"
:disabled="size===item.value"
:command="item.value"
>
{{
item.label }}
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</template>
<script>
export default {
data() {
return {
sizeOptions: [
{ label: 'Default', value: 'default' },
{ label: 'Medium', value: 'medium' },
{ label: 'Small', value: 'small' },
{ label: 'Mini', value: 'mini' }
]
}
},
computed: {
size() {
return this.$store.getters.size
}
},
methods: {
handleSetSize(size) {
this.$ELEMENT.size = size
this.$store.dispatch('app/setSize', size)
this.refreshView()
this.$message({
message: '布局设置成功',
type: 'success'
})
},
refreshView() {
// In order to make the cached page re-rendered
// this.$store.dispatch('tagsView/delAllCachedViews', this.$route)
const { fullPath } = this.$route
this.$nextTick(() => {
this.$router.replace({
path: '/redirect' + fullPath
})
})
}
}
}
</script>

View File

@ -0,0 +1,129 @@
<template>
<div style="width: 100%;">
<el-col>
<el-form
ref="suspensionForm"
:model="suspensionForm"
label-width="80px"
size="mini"
>
<el-form-item
v-show="showProperty('show')"
:label="$t('chart.show')"
class="form-item"
>
<el-checkbox
v-model="suspensionForm.show"
@change="changeSuspensionAttr('show')"
>{{ $t('chart.show') }}
</el-checkbox>
</el-form-item>
</el-form>
</el-col>
</div>
</template>
<script>
import { DEFAULT_SUSPENSION } from '@/views/chart/chart/chart'
export default {
name: 'SuspensionForm',
props: {
param: {
type: Object,
required: true
},
chart: {
type: Object,
required: true
},
propertyInner: {
type: Array,
required: false,
default: function() {
return []
}
}
},
data() {
return {
suspensionForm: JSON.parse(JSON.stringify(DEFAULT_SUSPENSION)),
fontSize: []
}
},
watch: {
'chart': {
handler: function() {
this.initData()
}
}
},
mounted() {
this.initData()
},
methods: {
initData() {
const chart = JSON.parse(JSON.stringify(this.chart))
if (chart.customAttr) {
let customAttr = null
if (Object.prototype.toString.call(chart.customAttr) === '[object Object]') {
customAttr = JSON.parse(JSON.stringify(chart.customAttr))
} else {
customAttr = JSON.parse(chart.customAttr)
}
if (customAttr.suspension) {
this.suspensionForm = customAttr.suspension
}
}
},
changeSuspensionAttr(modifyName) {
this.suspensionForm['modifyName'] = modifyName
this.$emit('onSuspensionChange', this.suspensionForm)
},
showProperty(property) {
return this.propertyInner.includes(property)
}
}
}
</script>
<style scoped>
.shape-item{
padding: 6px;
border: none;
width: 100%;
display: flex;
justify-content: space-between;
align-items: center;
}
.form-item-slider ::v-deep .el-form-item__label{
font-size: 12px;
line-height: 38px;
}
.form-item ::v-deep .el-form-item__label{
font-size: 12px;
}
.el-select-dropdown__item{
padding: 0 20px;
}
span{
font-size: 12px
}
.el-form-item{
margin-bottom: 6px;
}
.switch-style{
position: absolute;
right: 10px;
margin-top: -4px;
}
.color-picker-style{
cursor: pointer;
z-index: 1003;
}
</style>

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