Merge branch 'dev' into pr@dev@dataset

# Conflicts:
#	backend/src/main/resources/db/migration/V42__1.16.sql
This commit is contained in:
taojinlong 2022-10-28 18:30:34 +08:00
commit beb946f0d6
92 changed files with 3054 additions and 1073 deletions

View File

@ -12,6 +12,7 @@ import io.dataease.auth.service.AuthUserService;
import io.dataease.auth.util.JWTUtils;
import io.dataease.auth.util.RsaUtil;
import io.dataease.commons.constants.SysLogConstants;
import io.dataease.commons.exception.DEException;
import io.dataease.commons.utils.*;
import io.dataease.controller.sys.request.LdapAddRequest;
import io.dataease.exception.DataEaseException;
@ -240,8 +241,13 @@ public class AuthServer implements AuthApi {
HttpServletRequest request = ServletUtils.request();
String idToken = request.getHeader("IdToken");
if (StringUtils.isNotBlank(idToken)) {
OidcXpackService oidcXpackService = SpringContextUtil.getBean(OidcXpackService.class);
oidcXpackService.logout(idToken);
try {
OidcXpackService oidcXpackService = SpringContextUtil.getBean(OidcXpackService.class);
oidcXpackService.logout(idToken);
} catch (Exception e) {
LogUtil.error(e.getMessage(), e);
DEException.throwException("oidc_logout_error");
}
}
}
@ -253,11 +259,16 @@ public class AuthServer implements AuthApi {
String result = null;
Integer defaultLoginType = systemParameterService.defaultLoginType();
if (defaultLoginType == 3 && isOpenCas()) {
HttpServletRequest request = ServletUtils.request();
HttpSession session = request.getSession();
session.invalidate();
CasXpackService casXpackService = SpringContextUtil.getBean(CasXpackService.class);
result = casXpackService.logout();
try {
HttpServletRequest request = ServletUtils.request();
HttpSession session = request.getSession();
session.invalidate();
CasXpackService casXpackService = SpringContextUtil.getBean(CasXpackService.class);
result = casXpackService.logout();
} catch (Exception e) {
LogUtil.error(e.getMessage(), e);
DEException.throwException("cas_logout_error");
}
}
try {
Long userId = JWTUtils.tokenInfoByToken(token).getUserId();

View File

@ -86,6 +86,7 @@ public class ShiroServiceImpl implements ShiroService {
filterChainDefinitionMap.put("/api/auth/isOpenWecom", ANON);
filterChainDefinitionMap.put("/api/auth/isOpenDingtalk", ANON);
filterChainDefinitionMap.put("/api/auth/isOpenLark", ANON);
filterChainDefinitionMap.put("/api/auth/isOpenCas", ANON);
filterChainDefinitionMap.put("/api/auth/isOpenLarksuite", ANON);
filterChainDefinitionMap.put("/api/auth/getPublicKey", ANON);
filterChainDefinitionMap.put("/api/pluginCommon/component/*", ANON);
@ -106,6 +107,7 @@ public class ShiroServiceImpl implements ShiroService {
filterChainDefinitionMap.put("/plugin/larksuite/bind*", ANON);
filterChainDefinitionMap.put("/plugin/larksuite/getQrParam", ANON);
filterChainDefinitionMap.put("/cas/reset/**", ANON);
filterChainDefinitionMap.put("/cas/loginPage", ANON);
filterChainDefinitionMap.put("/unauth", ANON);
filterChainDefinitionMap.put("/display/**", ANON);

View File

@ -86,7 +86,7 @@ public class DatasourceController {
@PostMapping("/get/{id}")
public DatasourceDTO getDatasource(@PathVariable String id) throws Exception {
DatasourceUnionRequest request = new DatasourceUnionRequest();
request.setUserId(String.valueOf(AuthUtils.getUser().getUserId()));
request.setUserId("1");
request.setId(id);
List<DatasourceDTO> datasourceList = datasourceService.getDatasourceList(request);
return CollectionUtils.isNotEmpty(datasourceList) ? datasourceList.get(0) : null;

View File

@ -21,24 +21,31 @@ import java.util.List;
@RestController
@Api(tags = "应用市场:应用日志")
@ApiSupport(order = 220)
@RequestMapping("/app/log")
@RequestMapping("app/log")
public class AppLogController {
@Resource
private AppLogService applogService;
private AppLogService appLogService;
@I18n
@ApiOperation("查询日志")
@PostMapping("/logGrid/{goPage}/{pageSize}")
@ApiImplicitParams({
@ApiImplicitParam(paramType = "path", name = "goPage", value = "页码", required = true, dataType = "Integer"),
@ApiImplicitParam(paramType = "path", name = "pageSize", value = "页容量", required = true, dataType = "Integer"),
@ApiImplicitParam(name = "request", value = "查询条件", required = true)
@ApiImplicitParam(paramType = "path", name = "goPage", value = "页码", required = true, dataType = "Integer"),
@ApiImplicitParam(paramType = "path", name = "pageSize", value = "页容量", required = true, dataType = "Integer"),
@ApiImplicitParam(name = "request", value = "查询条件", required = true)
})
public Pager<List<AppLogGridDTO>> logGrid(@PathVariable int goPage, @PathVariable int pageSize,
@RequestBody KeyGridRequest request) {
Page<Object> page = PageHelper.startPage(goPage, pageSize, true);
return PageUtils.setPageInfo(page, applogService.query(request));
return PageUtils.setPageInfo(page, appLogService.query(request));
}
@ApiOperation("删除日志和资源")
@PostMapping("/deleteLog")
public void deleteLogAndResource(@RequestBody AppLogGridDTO request) throws Exception {
appLogService.deleteLogAndResource(request);
}
}

View File

@ -203,4 +203,18 @@ public class PanelGroupController {
result.setResponseSource("appApply");
return result;
}
@PostMapping("/appEdit")
public void appEdit(@RequestBody PanelAppTemplateApplyRequest request) throws Exception{
panelGroupService.appEdit(request);
}
@GetMapping("/findOneWithParent/{panelId}")
public PanelGroupDTO findOneWithParent(@PathVariable String panelId) throws Exception{
PanelGroupDTO result = findOne(panelId);
result.setParents(authService.parentResource(panelId,"panel"));
result.setRequestId(UUIDUtil.getUUIDAsString());
result.setResponseSource("appApply");
return result;
}
}

View File

@ -18,4 +18,6 @@ public class DataSetGroupRequest extends DatasetGroup {
private String userId;
@ApiModelProperty("ID集合")
private Set<String> ids;
@ApiModelProperty("排除的ID")
private String excludedId;
}

View File

@ -13,12 +13,18 @@ import java.util.List;
@Data
public class PanelAppTemplateApplyRequest {
private String logId;
private String panelId;
private String panelGroupPid;
private String panelName;
private String datasetGroupId;
private String datasetGroupPid;
private String datasetGroupName;
private String appTemplateId;

View File

@ -16,4 +16,18 @@ public class AppLogGridDTO extends PanelAppTemplateLog implements Serializable {
private String panelName;
private String panelGroupPid;
private String datasourceType;
private String datasetGroupPid;
private Boolean deleteResource;
private String datasetPrivileges;
private String panelPrivileges;
private String datasourcePrivileges;
}

View File

@ -7,12 +7,38 @@
<result column="panel_name" property="panelName"/>
<result column="dataset_group_name" property="datasetGroupName"/>
<result column="datasource_name" property="datasourceName"/>
<result column="panel_group_pid" property="panelGroupPid"/>
<result column="dataset_group_pid" property="datasetGroupPid"/>
<result column="datasource_type" property="datasourceType"/>
<result column="dataset_privileges" property="datasetPrivileges"/>
<result column="panel_privileges" property="panelPrivileges"/>
<result column="datasource_privileges" property="datasourcePrivileges"/>
</resultMap>
<select id="query" parameterType="io.dataease.service.panel.applog.AppLogQueryParam" resultMap="BaseResultMapDTO">
select * from
select
logInfo.*,
get_auths(logInfo.dataset_group_id,'dataset',#{userId}) as `dataset_privileges`,
get_auths(logInfo.panel_id,'panel',#{userId}) as `panel_privileges`,
get_auths(logInfo.datasource_id,'link',#{userId}) as `datasource_privileges`
from
(select * from
(SELECT
panel_app_template_log.*,
panel_app_template_log.id,
panel_app_template_log.app_template_id,
panel_app_template_log.app_template_name,
datasource.id as datasource_id,
panel_app_template_log.source_datasource_name,
dataset_group.id as dataset_group_id,
panel_app_template_log.source_dataset_group_name,
panel_group.id as panel_id,
panel_app_template_log.source_panel_name,
panel_app_template_log.apply_time,
panel_app_template_log.apply_persion,
panel_app_template_log.is_success,
panel_app_template_log.remark,
panel_group.pid as panel_group_pid,
datasource.type as datasource_type,
dataset_group.pid as dataset_group_pid,
IFNULL(panel_app_template.name,CONCAT(panel_app_template_log.app_template_name,'(Deleted)')) as app_name,
IFNULL(panel_group.name,CONCAT(panel_app_template_log.source_panel_name,'(Deleted)')) as panel_name,
IFNULL(dataset_group.name,CONCAT(panel_app_template_log.source_dataset_group_name,'(Deleted)')) as dataset_group_name,

View File

@ -68,6 +68,10 @@
<if test="createTime != null">
and dataset_group.create_time = #{createTime,jdbcType=BIGINT}
</if>
<if test="excludedId != null">
and dataset_group.id != #{excludedId,jdbcType=VARCHAR}
</if>
<if test="ids != null and ids.size() > 0">
and id in
<foreach collection="ids" item="item" separator="," open="(" close=")">
@ -79,6 +83,6 @@
</select>
<select id="searchIds" resultType="java.util.Map">
select GET_V_AUTH_MODEL_WITH_CHILDREN(#{id},#{type}) ids
select GET_V_AUTH_MODEL_WITH_CHILDREN(#{id}, #{type}) ids
</select>
</mapper>

View File

@ -6,6 +6,7 @@ import io.dataease.auth.service.AuthUserService;
import io.dataease.auth.service.impl.AuthUserServiceImpl;
import io.dataease.auth.util.JWTUtils;
import io.dataease.dto.PermissionProxy;
import io.dataease.dto.chart.ViewOption;
import io.dataease.ext.ExtTaskMapper;
import io.dataease.commons.utils.CommonBeanFactory;
import io.dataease.commons.utils.CronUtils;
@ -29,6 +30,7 @@ import io.dataease.plugins.xpack.larksuite.dto.response.LarksuiteMsgResult;
import io.dataease.plugins.xpack.larksuite.service.LarksuiteXpackService;
import io.dataease.plugins.xpack.wecom.dto.entity.WecomMsgResult;
import io.dataease.plugins.xpack.wecom.service.WecomXpackService;
import io.dataease.service.chart.ChartViewService;
import io.dataease.service.chart.ViewExportExcel;
import io.dataease.service.sys.SysUserService;
import io.dataease.service.system.EmailService;
@ -199,10 +201,13 @@ public class EmailTaskHandler extends TaskHandler implements Job {
List<File> files = null;
String viewIds = emailTemplateDTO.getViewIds();
if (StringUtils.isNotBlank(viewIds)) {
ChartViewService chartViewService = SpringContextUtil.getBean(ChartViewService.class);
List<ViewOption> viewOptions = chartViewService.viewOptions(panelId);
if (StringUtils.isNotBlank(viewIds) && CollectionUtils.isNotEmpty(viewOptions)) {
List<String> viewOptionIdList = viewOptions.stream().map(ViewOption::getId).collect(Collectors.toList());
String viewDataRange = emailTemplateDTO.getViewDataRange();
Boolean justExportView = StringUtils.isBlank(viewDataRange) || StringUtils.equals("view", viewDataRange);
List<String> viewIdList = Arrays.asList(viewIds.split(",")).stream().filter(StringUtils::isNotBlank).map(s -> (s.trim())).collect(Collectors.toList());
List<String> viewIdList = Arrays.asList(viewIds.split(",")).stream().map(s -> s.trim()).filter(viewId -> StringUtils.isNotBlank(viewId) && viewOptionIdList.contains(viewId)).collect(Collectors.toList());
PermissionProxy proxy = new PermissionProxy();
proxy.setUserId(user.getUserId());
files = viewExportExcel.export(panelId, viewIdList, proxy, justExportView);

View File

@ -115,4 +115,13 @@ public class CasServer {
return error;
}
}
@GetMapping("/loginPage")
@ResponseBody
public String loginPage() {
String casServerUrlPrefix = systemParameterService.getValue("cas.login");
String callBack = systemParameterService.getValue("cas.callBack");
String result = casServerUrlPrefix + "?service=" + callBack;
return result;
}
}

View File

@ -648,6 +648,7 @@ public class ChartViewService {
yAxis = yAxis.stream().filter(item -> StringUtils.isNotEmpty(item.getChartId()) || dataeaseNames.contains(item.getDataeaseName())).collect(Collectors.toList());
break;
case "bar-group":
case "bar-group-stack":
xAxis = xAxis.stream().filter(item -> StringUtils.isNotEmpty(item.getChartId()) || (!desensitizationList.contains(item.getDataeaseName()) && dataeaseNames.contains(item.getDataeaseName()))).collect(Collectors.toList());
yAxis = yAxis.stream().filter(item -> StringUtils.isNotEmpty(item.getChartId()) || (!desensitizationList.contains(item.getDataeaseName()) && dataeaseNames.contains(item.getDataeaseName()))).collect(Collectors.toList());
xAxisBase = xAxisBase.stream().filter(item -> StringUtils.isNotEmpty(item.getChartId()) || (!desensitizationList.contains(item.getDataeaseName()) && dataeaseNames.contains(item.getDataeaseName()))).collect(Collectors.toList());
@ -1113,6 +1114,8 @@ public class ChartViewService {
} else if (StringUtils.equalsIgnoreCase(view.getRender(), "antv")) {
if (StringUtils.equalsIgnoreCase(view.getType(), "bar-group")) {
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);
} else if (StringUtils.containsIgnoreCase(view.getType(), "bar-stack")) {
mapChart = ChartDataBuild.transStackChartDataAntV(xAxis, yAxis, view, data, extStack, isDrill);
} else if (StringUtils.containsIgnoreCase(view.getType(), "line-stack")) {

View File

@ -994,4 +994,89 @@ public class ChartDataBuild {
map.put("tableRow", tableRow);
return map;
}
public static Map<String, Object> transGroupStackDataAntV(List<ChartViewFieldDTO> xAxisBase, List<ChartViewFieldDTO> xAxis, List<ChartViewFieldDTO> xAxisExt, List<ChartViewFieldDTO> yAxis, List<ChartViewFieldDTO> extStack, List<String[]> data, ChartViewWithBLOBs view, boolean isDrill) {
// 堆叠柱状图
if (CollectionUtils.isEmpty(xAxisExt)) {
return transStackChartDataAntV(xAxis, yAxis, view, data, extStack, isDrill);
// 分组柱状图
} else if (CollectionUtils.isNotEmpty(xAxisExt) && CollectionUtils.isEmpty(extStack)) {
return transBaseGroupDataAntV(xAxisBase, xAxis, xAxisExt, yAxis, view, data, isDrill);
// 分组堆叠柱状图
}else {
Map<String, Object> map = new HashMap<>();
List<AxisChartDataAntVDTO> dataList = new ArrayList<>();
for (int i1 = 0; i1 < data.size(); i1++) {
String[] row = data.get(i1);
StringBuilder xField = new StringBuilder();
if (isDrill) {
xField.append(row[xAxis.size() - 1]);
} else {
for (int i = 0; i < xAxisBase.size(); i++) {
if (i == xAxisBase.size() - 1) {
xField.append(row[i]);
} else {
xField.append(row[i]).append("\n");
}
}
}
StringBuilder groupField = new StringBuilder();
for (int i = xAxisBase.size(); i < xAxisBase.size() + xAxisExt.size(); i++) {
if (i == xAxisBase.size() + xAxisExt.size() - 1) {
groupField.append(row[i]);
} else {
groupField.append(row[i]).append("\n");
}
}
StringBuilder stackField = new StringBuilder();
for (int i = xAxis.size(); i < xAxis.size() + extStack.size(); i++) {
if (i == xAxis.size() + extStack.size() - 1) {
stackField.append(row[i]);
} else {
stackField.append(row[i]).append("\n");
}
}
AxisChartDataAntVDTO axisChartDataDTO = new AxisChartDataAntVDTO();
axisChartDataDTO.setField(xField.toString());
axisChartDataDTO.setName(xField.toString());
List<ChartDimensionDTO> dimensionList = new ArrayList<>();
List<ChartQuotaDTO> quotaList = new ArrayList<>();
for (int j = 0; j < xAxis.size(); j++) {
ChartDimensionDTO chartDimensionDTO = new ChartDimensionDTO();
chartDimensionDTO.setId(xAxis.get(j).getId());
chartDimensionDTO.setValue(row[j]);
dimensionList.add(chartDimensionDTO);
}
axisChartDataDTO.setDimensionList(dimensionList);
if (CollectionUtils.isNotEmpty(yAxis)) {
int valueIndex = xAxis.size() + extStack.size();
ChartQuotaDTO chartQuotaDTO = new ChartQuotaDTO();
chartQuotaDTO.setId(yAxis.get(0).getId());
quotaList.add(chartQuotaDTO);
axisChartDataDTO.setQuotaList(quotaList);
try {
axisChartDataDTO.setValue(StringUtils.isEmpty(row[valueIndex]) ? null : new BigDecimal(row[valueIndex]));
} catch (Exception e) {
axisChartDataDTO.setValue(new BigDecimal(0));
}
} else {
axisChartDataDTO.setQuotaList(quotaList);
axisChartDataDTO.setValue(new BigDecimal(0));
}
axisChartDataDTO.setGroup(groupField.toString());
axisChartDataDTO.setCategory(stackField.toString());
dataList.add(axisChartDataDTO);
}
map.put("data", dataList);
return map;
}
}
}

View File

@ -5,6 +5,7 @@ import io.dataease.commons.constants.CommonConstants;
import io.dataease.commons.constants.PanelConstants;
import io.dataease.commons.utils.AuthUtils;
import io.dataease.commons.utils.BeanUtils;
import io.dataease.controller.datasource.request.UpdataDsRequest;
import io.dataease.controller.request.dataset.DataSetTableRequest;
import io.dataease.controller.request.panel.PanelAppTemplateApplyRequest;
import io.dataease.controller.request.panel.PanelAppTemplateRequest;
@ -181,6 +182,7 @@ public class PanelAppTemplateService {
for (DatasetTableField datasetTableField : datasetTableFieldsInfo) {
String oldId = datasetTableField.getId();
datasetTableField.setTableId(datasetsRealMap.get(datasetTableField.getTableId()));
datasetTableField.setId(null);
DatasetTableField newTableField = dataSetTableFieldsService.save(datasetTableField);
datasetFieldsRealMap.put(oldId, newTableField.getId());
}
@ -270,15 +272,36 @@ public class PanelAppTemplateService {
return chartViewFieldsRealMap;
}
public void nameCheck(PanelAppTemplateApplyRequest request) {
panelGroupService.checkPanelName(request.getPanelName(), request.getPanelId(), PanelConstants.OPT_TYPE_INSERT, null, "panel");
DatasetGroup datasetGroup = new DatasetGroup();
datasetGroup.setPid(request.getDatasetGroupId());
datasetGroup.setName(request.getDatasetGroupName());
dataSetGroupService.checkName(datasetGroup);
request.getDatasourceList().stream().forEach(datasource -> {
datasourceService.checkName(datasource.getName(), datasource.getType(), null);
});
public void nameCheck(PanelAppTemplateApplyRequest request, String optType) {
if ("add".equals(optType)) {
panelGroupService.checkPanelName(request.getPanelName(), request.getPanelGroupPid(), PanelConstants.OPT_TYPE_INSERT, null, "panel");
DatasetGroup datasetGroup = new DatasetGroup();
datasetGroup.setPid(request.getDatasetGroupPid());
datasetGroup.setName(request.getDatasetGroupName());
dataSetGroupService.checkName(datasetGroup);
request.getDatasourceList().stream().forEach(datasource -> {
datasourceService.checkName(datasource.getName(), datasource.getType(), null);
});
} else {
DatasetGroup datasetGroup = new DatasetGroup();
datasetGroup.setPid(request.getDatasetGroupPid());
datasetGroup.setName(request.getDatasetGroupName());
datasetGroup.setId(request.getDatasetGroupId());
dataSetGroupService.checkName(datasetGroup);
request.getDatasourceList().stream().forEach(datasource -> {
datasourceService.checkName(datasource.getName(), datasource.getType(), datasource.getId());
});
}
}
@Transactional(rollbackFor = Exception.class)
public void editDatasource(List<Datasource> updateDatasourceList) throws Exception {
for (int i = 0; i < updateDatasourceList.size(); i++) {
UpdataDsRequest updataDsRequest = new UpdataDsRequest();
BeanUtils.copyBean(updataDsRequest, updateDatasourceList.get(i));
datasourceService.updateDatasource(updataDsRequest);
}
}
}

View File

@ -127,9 +127,9 @@ public class PanelGroupService {
@Resource
private PanelAppTemplateLogService appTemplateLogService;
@Resource
private ChartGroupService chartGroupService;
@Resource
private DataSetGroupService dataSetGroupService;
@Resource
private DatasetGroupMapper datasetGroupMapper;
public List<PanelGroupDTO> tree(PanelGroupRequest panelGroupRequest) {
String userId = String.valueOf(AuthUtils.getUser().getUserId());
@ -232,6 +232,25 @@ public class PanelGroupService {
return panelId;
}
public void move(PanelGroupRequest request){
PanelGroupWithBLOBs panelInfo = panelGroupMapper.selectByPrimaryKey(request.getId());
if (panelInfo.getPid().equalsIgnoreCase(request.getPid())) {
DataEaseException.throwException(Translator.get("i18n_select_diff_folder"));
}
// 移动校验
if (StringUtils.isNotEmpty(request.getName())) {
checkPanelName(request.getName(), request.getPid(), PanelConstants.OPT_TYPE_INSERT, request.getId(), panelInfo.getNodeType());
}
PanelGroupWithBLOBs record = new PanelGroupWithBLOBs();
record.setName(request.getName());
record.setId(request.getId());
record.setPid(request.getPid());
record.setUpdateTime(request.getUpdateTime());
record.setUpdateBy(request.getUpdateBy());
panelGroupMapper.updateByPrimaryKeySelective(record);
DeLogUtils.save(SysLogConstants.OPERATE_TYPE.MODIFY, sourceType, request.getId(), panelInfo.getPid(), request.getPid(), sourceType);
}
public void checkPanelName(String name, String pid, String optType, String id, String nodeType) {
PanelGroupExample groupExample = new PanelGroupExample();
@ -811,12 +830,12 @@ public class PanelGroupService {
@Transactional(rollbackFor = Exception.class)
public String appApply(PanelAppTemplateApplyRequest request) throws Exception{
//仪表板名称校验数据集分组名称校验数据源名称校验
panelAppTemplateService.nameCheck(request);
panelAppTemplateService.nameCheck(request,"add");
String newPanelId = UUIDUtil.getUUIDAsString();
// 新建数据集分组
DatasetGroup newDatasetGroup = new DatasetGroup();
newDatasetGroup.setPid(request.getDatasetGroupId());
newDatasetGroup.setPid(request.getDatasetGroupPid());
newDatasetGroup.setName(request.getDatasetGroupName());
newDatasetGroup.setType("group");
DataSetGroupDTO resultDatasetGroup = dataSetGroupService.save(newDatasetGroup);
@ -853,7 +872,7 @@ public class PanelGroupService {
panelAppTemplateService.applyViewsField(chartViewFieldsInfo,chartViewsRealMap,datasetsRealMap,datasetFieldsRealMap);
panelAppTemplateService.applyPanel(panelInfo,chartViewsRealMap,newPanelId, request.getPanelName(), request.getPanelId());
panelAppTemplateService.applyPanel(panelInfo,chartViewsRealMap,newPanelId, request.getPanelName(), request.getPanelGroupPid());
panelAppTemplateService.applyPanelView(panelViewsInfo,chartViewsRealMap,newPanelId);
@ -873,4 +892,42 @@ public class PanelGroupService {
appTemplateLogService.newAppApplyLog(templateLog);
return newPanelId;
}
@Transactional(rollbackFor = Exception.class)
public void appEdit(PanelAppTemplateApplyRequest request) throws Exception{
long currentTime = System.currentTimeMillis();
String userName = AuthUtils.getUser().getUsername();
//名称校验数据集分组名称校验数据源名称校验
panelAppTemplateService.nameCheck(request,"update");
//仪表板移动更新名称
PanelGroup panelHistoryInfo = panelGroupMapper.selectByPrimaryKey(request.getPanelId());
String panelHistoryPid = panelHistoryInfo.getPid();
if(panelHistoryPid.equals(request.getPanelGroupPid())){
// 未移动
checkPanelName(request.getPanelName(), request.getPanelGroupPid(), PanelConstants.OPT_TYPE_UPDATE, request.getPanelId(), "panel");
}else{
checkPanelName(request.getPanelName(), request.getPanelGroupPid(), PanelConstants.OPT_TYPE_INSERT, null, "panel");
}
panelHistoryInfo.setName(request.getPanelName());
panelHistoryInfo.setPid(request.getPanelGroupPid());
panelHistoryInfo.setUpdateBy(userName);
panelHistoryInfo.setUpdateTime(currentTime);
panelGroupMapper.updateByPrimaryKey(panelHistoryInfo);
//数据集分组移动,变更
DatasetGroup datasetGroupHistoryInfo = datasetGroupMapper.selectByPrimaryKey(request.getDatasetGroupId());
DatasetGroup datasetGroup = new DatasetGroup();
datasetGroup.setName(request.getDatasetGroupName());
datasetGroup.setId(request.getDatasetGroupId());
if(datasetGroupHistoryInfo.getPid().equals(request.getDatasetGroupPid())){
datasetGroup.setPid(request.getDatasetGroupPid());
}
dataSetGroupService.checkName(datasetGroup);
datasetGroupHistoryInfo.setName(request.getDatasetGroupName());
datasetGroupHistoryInfo.setPid(request.getDatasetGroupPid());
datasetGroupMapper.updateByPrimaryKey(datasetGroupHistoryInfo);
//数据源变更
panelAppTemplateService.editDatasource(request.getDatasourceList());
}
}

View File

@ -7,5 +7,6 @@ import java.util.List;
@Data
public class AppLogQueryParam extends GridExample {
private String userId;
}

View File

@ -1,13 +1,20 @@
package io.dataease.service.panel.applog;
import com.google.gson.Gson;
import io.dataease.commons.utils.AuthUtils;
import io.dataease.controller.sys.request.KeyGridRequest;
import io.dataease.dto.SysLogDTO;
import io.dataease.dto.appTemplateMarket.AppLogGridDTO;
import io.dataease.ext.ExtAppLogMapper;
import io.dataease.ext.query.GridExample;
import io.dataease.plugins.common.base.mapper.PanelAppTemplateLogMapper;
import io.dataease.service.dataset.DataSetGroupService;
import io.dataease.service.datasource.DatasourceService;
import io.dataease.service.panel.PanelGroupService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.util.List;
@ -19,12 +26,19 @@ public class AppLogService {
private PanelAppTemplateLogMapper appLogMapper;
@Resource
private ExtAppLogMapper extAppLogMapper;
@Resource
private PanelGroupService panelGroupService;
@Resource
private DataSetGroupService dataSetGroupService;
@Resource
private DatasourceService datasourceService;
public List<AppLogGridDTO> query(KeyGridRequest request) {
GridExample gridExample = request.convertExample();
gridExample.setExtendCondition(request.getKeyWord());
AppLogQueryParam logQueryParam = gson.fromJson(gson.toJson(gridExample), AppLogQueryParam.class);
logQueryParam.setUserId(String.valueOf(AuthUtils.getUser().getUserId()));
List<AppLogGridDTO> voLogs = extAppLogMapper.query(logQueryParam);
return voLogs;
}
@ -34,4 +48,19 @@ public class AppLogService {
}
@Transactional
public void deleteLogAndResource(AppLogGridDTO request) throws Exception {
if (request.getDeleteResource()) {
if (StringUtils.isNotEmpty(request.getPanelId())) {
panelGroupService.deleteCircle(request.getPanelId());
}
if (StringUtils.isNotEmpty(request.getDatasetGroupId())) {
dataSetGroupService.delete(request.getDatasetGroupId());
}
if (StringUtils.isNotEmpty(request.getDatasourceId())) {
datasourceService.deleteDatasource(request.getDatasourceId());
}
}
appLogMapper.deleteByPrimaryKey(request.getId());
}
}

View File

@ -27,7 +27,7 @@ ADD COLUMN `mobile_layout` tinyint(1) NULL DEFAULT 0 COMMENT '启用移动端布
DROP FUNCTION IF EXISTS `GET_PANEL_WITH_PRIVILEGE_AND_MOBILE`;
delimiter ;;
CREATE FUNCTION `GET_PANEL_WITH_PRIVILEGE_AND_MOBILE`(userId longtext,modelType varchar(255),privilegeType varchar(255))
RETURNS longtext CHARSET utf8
RETURNS longtext CHARSET utf8mb4 COLLATE utf8mb4_general_ci
READS SQL DATA
BEGIN
@ -73,7 +73,7 @@ delimiter ;
DROP FUNCTION IF EXISTS `GET_V_AUTH_MODEL_ID_P_USE_MOBILE`;
delimiter ;;
CREATE FUNCTION `GET_V_AUTH_MODEL_ID_P_USE_MOBILE`(userId longtext,modelType varchar(255))
RETURNS longtext CHARSET utf8
RETURNS longtext CHARSET utf8mb4 COLLATE utf8mb4_general_ci
READS SQL DATA
BEGIN

View File

@ -344,7 +344,7 @@ CREATE TABLE `sys_background_image` (
`base_url` varchar(255) DEFAULT NULL,
`url` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE utf8mb4_general_ci;
-- ----------------------------
-- Records of sys_background_image
@ -404,7 +404,7 @@ CREATE TABLE `dataease_code_version` (
`success` tinyint(1) NOT NULL,
PRIMARY KEY (`installed_rank`),
KEY `dataease_version_s_idx` (`success`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE utf8mb4_general_ci;
-- ----------------------------
-- Records of dataease_code_version
@ -429,7 +429,7 @@ CREATE ALGORITHM = UNDEFINED SQL SECURITY DEFINER VIEW `v_history_chart_view` AS
DROP FUNCTION IF EXISTS `GET_CHART_GROUP_WITH_CHILDREN`;
delimiter ;;
CREATE FUNCTION `GET_CHART_GROUP_WITH_CHILDREN`(parentId varchar(8000))
RETURNS LONGTEXT CHARSET utf8
RETURNS LONGTEXT CHARSET utf8mb4 COLLATE utf8mb4_general_ci
READS SQL DATA
BEGIN

View File

@ -105,7 +105,7 @@ ADD COLUMN `copy_id` varchar(255) NULL COMMENT '复制ID' AFTER `copy_from`;
DROP FUNCTION IF EXISTS `copy_auth`;
delimiter ;;
CREATE FUNCTION `copy_auth`(authSource varchar(255),authSourceType varchar(255),authUser varchar(255))
RETURNS varchar(255) CHARSET utf8mb4
RETURNS varchar(255) CHARSET utf8mb4 COLLATE utf8mb4_general_ci
READS SQL DATA
BEGIN
@ -256,7 +256,7 @@ delimiter ;
DROP FUNCTION IF EXISTS `delete_auth_source`;
delimiter ;;
CREATE FUNCTION `delete_auth_source`(authSource varchar(255),authSourceType varchar(255))
RETURNS varchar(255) CHARSET utf8mb4
RETURNS varchar(255) CHARSET utf8mb4 COLLATE utf8mb4_general_ci
READS SQL DATA
BEGIN
@ -285,7 +285,7 @@ INSERT INTO `sys_menu` VALUES (101, 1, 4, 1, '插件管理', 'system-plugin', 's
DROP FUNCTION IF EXISTS `GET_CHART_VIEW_COPY_NAME`;
delimiter ;;
CREATE FUNCTION `GET_CHART_VIEW_COPY_NAME`(chartId varchar(255),pid varchar(255))
RETURNS varchar(255) CHARSET utf8mb4
RETURNS varchar(255) CHARSET utf8mb4 COLLATE utf8mb4_general_ci
READS SQL DATA
BEGIN

View File

@ -213,7 +213,7 @@ delimiter ;
DROP FUNCTION IF EXISTS `GET_CHART_VIEW_COPY_NAME`;
delimiter ;;
CREATE FUNCTION `GET_CHART_VIEW_COPY_NAME`(chartId varchar(255),pid varchar(255))
RETURNS varchar(255) CHARSET utf8mb4
RETURNS varchar(255) CHARSET utf8mb4 COLLATE utf8mb4_general_ci
READS SQL DATA
BEGIN

View File

@ -32,6 +32,17 @@ WHERE (`msg_type_id` = 6);
ALTER TABLE `sys_user_assist`
ADD COLUMN `larksuite_id` VARCHAR(255) NULL DEFAULT NULL AFTER `lark_id`;
INSERT INTO `sys_menu` (`menu_id`, `pid`, `sub_count`, `type`, `title`, `name`, `component`, `menu_sort`, `icon`,
`path`, `i_frame`, `cache`, `hidden`, `permission`, `create_by`, `update_by`, `create_time`,
`update_time`)
VALUES (41, 1, 1, 1, '应用管理', 'system-app-template', 'panel/appTemplate/index', 13, 'sys-param',
'panel/appTemplate/index', 0, 0, 0, NULL, NULL, NULL, NULL, 1620444227389);
INSERT INTO `sys_menu` (`menu_id`, `pid`, `sub_count`, `type`, `title`, `name`, `component`, `menu_sort`, `icon`,
`path`, `i_frame`, `cache`, `hidden`, `permission`, `create_by`, `update_by`, `create_time`,
`update_time`)
VALUES (203, 0, 0, 1, '应用', 'app-template-market', 'panel/appTemplateMarket/index', 6, 'dashboard',
'/appTemplateMarket', 0, 0, 0, NULL, NULL, NULL, NULL, 1620444227389);
ALTER TABLE `dataset_table_field` CHANGE COLUMN `type` `type` VARCHAR(255) NOT NULL COMMENT '原始字段类型' ;
INSERT INTO `my_plugin` (`name`, `store`, `free`, `cost`, `category`, `descript`, `version`, `creator`, `load_mybatis`,
@ -53,3 +64,220 @@ CREATE TABLE `dataset_sql_log` (
`status` varchar(45) DEFAULT NULL COMMENT '状态',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
INSERT INTO `sys_menu` (`menu_id`, `pid`, `sub_count`, `type`, `title`, `name`, `component`, `menu_sort`, `icon`, `path`, `i_frame`, `cache`, `hidden`, `permission`, `create_by`, `update_by`, `create_time`, `update_time`) VALUES (204, 203, 0, 2, '删除记录', NULL, NULL, 999, NULL, NULL, 0, 0, 0, 'appLog:del', NULL, NULL, 1614930903502, 1614930903502);
INSERT INTO `sys_menu` (`menu_id`, `pid`, `sub_count`, `type`, `title`, `name`, `component`, `menu_sort`, `icon`, `path`, `i_frame`, `cache`, `hidden`, `permission`, `create_by`, `update_by`, `create_time`, `update_time`) VALUES (205, 203, 0, 2, '编辑记录', NULL, NULL, 999, NULL, NULL, 0, 0, 0, 'appLog:edit', NULL, NULL, 1614930935529, 1614930935529);
INSERT INTO `sys_auth` (`id`, `auth_source`, `auth_source_type`, `auth_target`, `auth_target_type`, `auth_time`, `auth_details`, `auth_user`, `update_time`, `copy_from`, `copy_id`) VALUES ('46e4e2cb-1349-40c3-a72d-7b0b30ab5d14', '203', 'menu', '1', 'role', 1666840141866, NULL, 'admin', NULL, NULL, NULL);
INSERT INTO `sys_auth` (`id`, `auth_source`, `auth_source_type`, `auth_target`, `auth_target_type`, `auth_time`, `auth_details`, `auth_user`, `update_time`, `copy_from`, `copy_id`) VALUES ('6e22ad53-d737-447f-9686-5041e122b4dc', '205', 'menu', '1', 'role', 1666840141468, NULL, 'admin', NULL, NULL, NULL);
INSERT INTO `sys_auth` (`id`, `auth_source`, `auth_source_type`, `auth_target`, `auth_target_type`, `auth_time`, `auth_details`, `auth_user`, `update_time`, `copy_from`, `copy_id`) VALUES ('da17fcfe-7875-4aaf-983b-d750d71f36d2', '204', 'menu', '1', 'role', 1666840141658, NULL, 'admin', NULL, NULL, NULL);
INSERT INTO `sys_auth_detail` (`id`, `auth_id`, `privilege_name`, `privilege_type`, `privilege_value`, `privilege_extend`, `remark`, `create_user`, `create_time`, `update_time`, `copy_from`, `copy_id`) VALUES ('b4fe2e52-55a4-11ed-bf84-0242ac130005', '6e22ad53-d737-447f-9686-5041e122b4dc', 'i18n_auth_grant', 15, 0, 'grant', '基础权限-授权', 'admin', 1666840141000, NULL, NULL, NULL);
INSERT INTO `sys_auth_detail` (`id`, `auth_id`, `privilege_name`, `privilege_type`, `privilege_value`, `privilege_extend`, `remark`, `create_user`, `create_time`, `update_time`, `copy_from`, `copy_id`) VALUES ('b4fe3215-55a4-11ed-bf84-0242ac130005', '6e22ad53-d737-447f-9686-5041e122b4dc', 'i18n_auth_use', 1, 1, 'use', '基础权限-使用', 'admin', 1666840141000, NULL, NULL, NULL);
INSERT INTO `sys_auth_detail` (`id`, `auth_id`, `privilege_name`, `privilege_type`, `privilege_value`, `privilege_extend`, `remark`, `create_user`, `create_time`, `update_time`, `copy_from`, `copy_id`) VALUES ('b51affbf-55a4-11ed-bf84-0242ac130005', 'da17fcfe-7875-4aaf-983b-d750d71f36d2', 'i18n_auth_grant', 15, 0, 'grant', '基础权限-授权', 'admin', 1666840141000, NULL, NULL, NULL);
INSERT INTO `sys_auth_detail` (`id`, `auth_id`, `privilege_name`, `privilege_type`, `privilege_value`, `privilege_extend`, `remark`, `create_user`, `create_time`, `update_time`, `copy_from`, `copy_id`) VALUES ('b51b0473-55a4-11ed-bf84-0242ac130005', 'da17fcfe-7875-4aaf-983b-d750d71f36d2', 'i18n_auth_use', 1, 1, 'use', '基础权限-使用', 'admin', 1666840141000, NULL, NULL, NULL);
INSERT INTO `sys_auth_detail` (`id`, `auth_id`, `privilege_name`, `privilege_type`, `privilege_value`, `privilege_extend`, `remark`, `create_user`, `create_time`, `update_time`, `copy_from`, `copy_id`) VALUES ('b53a1ad7-55a4-11ed-bf84-0242ac130005', '46e4e2cb-1349-40c3-a72d-7b0b30ab5d14', 'i18n_auth_grant', 15, 0, 'grant', '基础权限-授权', 'admin', 1666840142000, NULL, NULL, NULL);
INSERT INTO `sys_auth_detail` (`id`, `auth_id`, `privilege_name`, `privilege_type`, `privilege_value`, `privilege_extend`, `remark`, `create_user`, `create_time`, `update_time`, `copy_from`, `copy_id`) VALUES ('b53a1dfd-55a4-11ed-bf84-0242ac130005', '46e4e2cb-1349-40c3-a72d-7b0b30ab5d14', 'i18n_auth_use', 1, 1, 'use', '基础权限-使用', 'admin', 1666840142000, NULL, NULL, NULL);
DROP VIEW IF EXISTS `v_auth_model`;
CREATE ALGORITHM = UNDEFINED SQL SECURITY DEFINER VIEW `v_auth_model` AS SELECT
`sys_user`.`user_id` AS `id`,
concat( `sys_user`.`nick_name`, '', `sys_user`.`username`, '' ) AS `name`,
`sys_user`.`username` AS `label`,
'0' AS `pid`,
'leaf' AS `node_type`,
'user' AS `model_type`,
'user' AS `model_inner_type`,
'target' AS `auth_type`,
`sys_user`.`create_by` AS `create_by`,
0 AS `level`,
0 AS `mode`,
'0' AS `data_source_id`
FROM
`sys_user`
WHERE
( `sys_user`.`is_admin` <> 1 ) UNION ALL
SELECT
`sys_role`.`role_id` AS `id`,
`sys_role`.`name` AS `name`,
`sys_role`.`name` AS `label`,
'0' AS `pid`,
'leaf' AS `node_type`,
'role' AS `model_type`,
'role' AS `model_inner_type`,
'target' AS `auth_type`,
`sys_role`.`create_by` AS `create_by`,
0 AS `level`,
0 AS `mode`,
'0' AS `data_source_id`
FROM
`sys_role` UNION ALL
SELECT
`sys_dept`.`dept_id` AS `id`,
`sys_dept`.`name` AS `name`,
`sys_dept`.`name` AS `label`,(
cast( `sys_dept`.`pid` AS CHAR charset utf8mb4 ) COLLATE utf8mb4_general_ci
) AS `pid`,
IF
(( `sys_dept`.`sub_count` = 0 ), 'leaf', 'spine' ) AS `node_type`,
'dept' AS `model_type`,
'dept' AS `model_inner_type`,
'target' AS `auth_type`,
`sys_dept`.`create_by` AS `create_by`,
0 AS `level`,
0 AS `mode`,
'0' AS `data_source_id`
FROM
`sys_dept` UNION ALL
SELECT
`datasource`.`id` AS `id`,
`datasource`.`name` AS `NAME`,
`datasource`.`name` AS `label`,
'0' AS `pid`,
'leaf' AS `node_type`,
'link' AS `model_type`,
`datasource`.`type` AS `model_inner_type`,
'source' AS `auth_type`,
`datasource`.`create_by` AS `create_by`,
0 AS `level`,
0 AS `mode`,
'0' AS `data_source_id`
FROM
`datasource` UNION ALL
SELECT
`dataset_group`.`id` AS `id`,
`dataset_group`.`name` AS `NAME`,
`dataset_group`.`name` AS `label`,
IF
( isnull( `dataset_group`.`pid` ), '0', `dataset_group`.`pid` ) AS `pid`,
'spine' AS `node_type`,
'dataset' AS `model_type`,
`dataset_group`.`type` AS `model_inner_type`,
'source' AS `auth_type`,
`dataset_group`.`create_by` AS `create_by`,
`dataset_group`.`level` AS `level`,
0 AS `mode`,
'0' AS `data_source_id`
FROM
`dataset_group` UNION ALL
SELECT
`dataset_table`.`id` AS `id`,
`dataset_table`.`name` AS `NAME`,
`dataset_table`.`name` AS `label`,
`dataset_table`.`scene_id` AS `pid`,
'leaf' AS `node_type`,
'dataset' AS `model_type`,
`dataset_table`.`type` AS `model_inner_type`,
'source' AS `auth_type`,
`dataset_table`.`create_by` AS `create_by`,
0 AS `level`,
`dataset_table`.`mode` AS `mode`,
`dataset_table`.`data_source_id` AS `data_source_id`
FROM
`dataset_table` UNION ALL
SELECT
`panel_group`.`id` AS `id`,
`panel_group`.`name` AS `NAME`,
`panel_group`.`name` AS `label`,(
CASE
`panel_group`.`id`
WHEN 'panel_list' THEN
'0'
WHEN 'default_panel' THEN
'0' ELSE `panel_group`.`pid`
END
) AS `pid`,
IF
(( `panel_group`.`node_type` = 'folder' ), 'spine', 'leaf' ) AS `node_type`,
'panel' AS `model_type`,
`panel_group`.`panel_type` AS `model_inner_type`,
'source' AS `auth_type`,
`panel_group`.`create_by` AS `create_by`,
0 AS `level`,
0 AS `mode`,
'0' AS `data_source_id`
FROM
`panel_group` UNION ALL
SELECT
`sys_menu`.`menu_id` AS `menu_id`,
`sys_menu`.`title` AS `name`,
`sys_menu`.`title` AS `label`,
`sys_menu`.`pid` AS `pid`,
IF
(( `sys_menu`.`sub_count` > 0 ), 'spine', 'leaf' ) AS `node_type`,
'menu' AS `model_type`,(
CASE
`sys_menu`.`type`
WHEN 0 THEN
'folder'
WHEN 1 THEN
'menu'
WHEN 2 THEN
'button'
END
) AS `model_inner_type`,
'source' AS `auth_type`,
`sys_menu`.`create_by` AS `create_by`,
0 AS `level`,
0 AS `mode`,
'0' AS `data_source_id`
FROM
`sys_menu`
WHERE
((
`sys_menu`.`i_frame` <> 1
)
OR isnull( `sys_menu`.`i_frame` )) UNION ALL
SELECT
`plugin_sys_menu`.`menu_id` AS `menu_id`,
`plugin_sys_menu`.`title` AS `name`,
`plugin_sys_menu`.`title` AS `label`,
`plugin_sys_menu`.`pid` AS `pid`,
IF
(( `plugin_sys_menu`.`sub_count` > 0 ), 'spine', 'leaf' ) AS `node_type`,
'menu' AS `model_type`,(
CASE
`plugin_sys_menu`.`type`
WHEN 0 THEN
'folder'
WHEN 1 THEN
'menu'
WHEN 2 THEN
'button'
END
) AS `model_inner_type`,
'source' AS `auth_type`,
`plugin_sys_menu`.`create_by` AS `create_by`,
0 AS `level`,
0 AS `mode`,
'0' AS `data_source_id`
FROM
`plugin_sys_menu`
WHERE
((
`plugin_sys_menu`.`i_frame` <> 1
)
OR isnull( `plugin_sys_menu`.`i_frame` ));
-- ----------------------------
-- Function structure for delete_auth_target
-- ----------------------------
DROP FUNCTION IF EXISTS `delete_auth_target`;
delimiter ;;
CREATE FUNCTION `delete_auth_target`(authTarget varchar(255),authTargetType varchar(255))
RETURNS varchar(255) CHARSET utf8mb4
READS SQL DATA
BEGIN
delete from sys_auth_detail where auth_id in (
select id from sys_auth where sys_auth.auth_target=authTarget and sys_auth.auth_target_type=authTargetType
);
delete from sys_auth where sys_auth.auth_target=authTarget and sys_auth.auth_target_type=authTargetType;
RETURN 'success';
END
;;
delimiter ;

View File

@ -45,6 +45,7 @@
"js-cookie": "2.2.0",
"jsencrypt": "^3.0.0-rc.1",
"jspdf": "^2.3.1",
"jszip": "^3.10.1",
"lodash": "^4.17.21",
"lodash.isboolean": "^3.0.3",
"lodash.isempty": "^4.4.0",

View File

@ -11,7 +11,7 @@ export function logGrid(page, size, data) {
export function opTypes() {
return request({
url: '/api/log/opTypes',
url: '/app/log/opTypes',
method: 'post',
loading: true
})
@ -19,10 +19,19 @@ export function opTypes() {
export function exportExcel(data) {
return request({
url: '/api/log/export',
url: '/app/log/export',
method: 'post',
loading: true,
responseType: 'blob',
data
})
}
export function deleteLogAndResource(data) {
return request({
url: '/app/log/deleteLog',
method: 'post',
data,
loading: true
})
}

View File

@ -313,7 +313,33 @@ export function appApply(data) {
return request({
url: 'panel/group/appApply',
method: 'post',
loading: true,
loading: false,
data
})
}
export function appEdit(data) {
return request({
url: 'panel/group/appEdit',
method: 'post',
loading: false,
data
})
}
export function editApply(data) {
return request({
url: 'panel/group/appApply',
method: 'post',
loading: false,
data
})
}
export function findOneWithParent(panelId) {
return request({
url: 'panel/group/findOneWithParent/' + panelId,
method: 'get',
loading: false
})
}

View File

@ -18,14 +18,16 @@ export function getInfo(token) {
export function logout() {
return request({
url: '/api/auth/logout',
method: 'post'
method: 'post',
hideMsg: true
})
}
export function deLogout() {
return request({
url: '/api/auth/deLogout',
method: 'post'
method: 'post',
hideMsg: true
})
}
@ -100,6 +102,13 @@ export function casStatus() {
})
}
export function casLoginPage() {
return request({
url: '/cas/loginPage',
method: 'get'
})
}
export function wecomStatus() {
return request({
url: '/api/auth/isOpenWecom',

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

After

Width:  |  Height:  |  Size: 60 KiB

View File

@ -157,6 +157,9 @@ export default {
loadOptions() {
this.panelId && viewOptions(this.panelId).then(res => {
this.selectOptions = res.data
this.innerValues?.length && this.selectOptions?.length && this.innerValues.filter(viewId => !this.selectOptions.some(option => option.id === viewId)).forEach(item => {
this._selectRemoveTag(item)
})
this.init()
})
},
@ -185,7 +188,10 @@ export default {
},
_selectClearFun() {
this.$store.dispatch('task/delPanelViews', this.panelId)
const viewIds = JSON.parse(JSON.stringify(this.$store.getters.panelViews[this.panelId]))
let viewIds = []
if (this.$store.getters.panelViews?.[this.panelId]) {
viewIds = JSON.parse(JSON.stringify(this.$store.getters.panelViews[this.panelId]))
}
this.$emit('input', viewIds)
},

View File

@ -39,7 +39,7 @@ export const colorCases = [
{
name: i18n.t('chart.color_gentle'),
value: 'gentle',
colors: ['#5b9bd5', '#ed7d31', '#70ad47', '#ffc000', '#4472c4', '#91d024', '#b235e6', '#02ae75', '#5b9bd5']
colors: ['#5b9bd5', '#ed7d31', '#70ad47', '#ffc000', '#4472c4', '#91d024', '#b235e6', '#02ae75', '#003F78']
},
{
name: i18n.t('chart.color_technology'),
@ -59,7 +59,7 @@ export const colorCases = [
{
name: i18n.t('chart.color_fresh'),
value: 'fresh',
colors: ['#5f9b3c', '#75c24b', '#83d65f', '#aacf53', '#c7dc68', '#d8e698', '#e0ebaf', '#bbc8e6', '#e5e5e5']
colors: ['#e5e5e5', '#bbc8e6', '#e0ebaf', '#d8e698', '#c7dc68', '#aacf53', '#83d65f', '#75c24b', '#5f9b3c']
},
{
name: i18n.t('chart.color_energy'),
@ -79,7 +79,7 @@ export const colorCases = [
{
name: i18n.t('chart.color_spiritual'),
value: 'spiritual',
colors: ['#00a3af', '#4da798', '#57baaa', '#62d0bd', '#6ee4d0', '#86e7d6', '#aeede1', '#bde1e6', '#e5e5e5']
colors: ['#e5e5e5', '#bde1e6', '#aeede1', '#86e7d6', '#6ee4d0', '#62d0bd', '#57baaa', '#4da798', '#00a3af']
}
]

View File

@ -106,6 +106,7 @@
<el-color-picker
v-else
v-model="option.colors[index]"
popper-class="gradient-picker-dropdown"
@change="switchColorItem(option.colors, option.value)"
/>
</span>
@ -423,4 +424,7 @@ export default {
width: 20px;
height: 20px;
}
.gradient-picker-dropdown .el-color-dropdown__link-btn {
display: none;
}
</style>

View File

@ -42,7 +42,7 @@ export default {
return backPath || backName || backTo
},
needInnerPadding() {
return ['sys-identification', 'sys-abutment', 'sys-task-email', 'system-dept', 'system-dept-form', 'system-auth', 'sys-appearance', 'system-param', 'system-template', 'sys-task-dataset', 'sys-msg-web-all', 'system-plugin'].includes(this.$route.name)
return ['system-app-template', 'sys-identification', 'sys-abutment', 'sys-task-email', 'system-dept', 'system-dept-form', 'system-auth', 'sys-appearance', 'system-param', 'system-template', 'sys-task-dataset', 'sys-msg-web-all', 'system-plugin'].includes(this.$route.name)
}
}
}

View File

@ -61,8 +61,8 @@
v-if="filterVisible && panelInfo.id"
:title="(currentWidget && currentWidget.getLeftPanel && currentWidget.getLeftPanel().label ? $t(currentWidget.getLeftPanel().label) : '') + $t('panel.module')"
:visible.sync="filterVisible"
custom-class="de-filter-dialog"
:append-to-body="true"
custom-class="de-filter-dialog min-width-730"
append-to-body
@close="cancelFilter"
>
<filter-dialog
@ -88,13 +88,6 @@
</span>
</div>
</el-dialog>
<!--矩形样式组件-->
<TextAttr
v-if="showAttr"
:canvas-id="canvasId"
:scroll-left="scrollLeft"
:scroll-top="scrollTop"
/>
</div>
</template>
@ -239,13 +232,6 @@ export default {
mobileLayoutStatus() {
this.restore()
}
// // tab
// curComponent: {
// handler(newVal, oldVla) {
// // this.restore()
// },
// deep: true
// },
},
created() {
},
@ -301,8 +287,7 @@ export default {
}
},
canvasScroll(e) {
this.scrollLeft = e.target.scrollLeft
this.scrollTop = e.target.scrollTop
this.$emit('canvasScroll', { scrollLeft: e.target.scrollLeft, scrollTop: e.target.scrollTop })
bus.$emit('onScroll')
},
// handleDrop(e) {
@ -597,4 +582,7 @@ export default {
overflow-y: auto;
background-size: 100% 100% !important;
}
.min-width-730 {
min-width: 730px !important;
}
</style>

View File

@ -10,6 +10,7 @@
:source-element="sourceConfig"
:terminal="terminal"
:element="config"
:canvas-id="canvasId"
:show-position="showPosition"
@showViewDetails="showViewDetails"
/>
@ -195,7 +196,7 @@ export default {
return style
},
componentActiveFlag() {
return (this.curComponent && this.config === this.curComponent && !this.previewVisible && !this.showPosition.includes('email-task')) || this.showPosition.includes('multiplexing')
return !this.mobileLayoutStatus && ((this.curComponent && this.config === this.curComponent && !this.previewVisible && !this.showPosition.includes('email-task')) || this.showPosition.includes('multiplexing'))
},
curGap() {
return (this.canvasStyleData.panel.gap === 'yes' && this.config.auxiliaryMatrix) ? this.componentGap : 0

View File

@ -942,12 +942,6 @@ export default {
height: this.outStyle.height + this.scrollTop + 'px !important'
}
},
//
// eslint-disable-next-line
coordinates() {
// eslint-disable-next-line
return this.coordinates
},
customStyle() {
let style = {
width: '100%',

View File

@ -27,7 +27,7 @@
v-else-if="componentDataShow && componentDataShow.length===0"
class="custom-position"
>
{{ $t('panel.panelNull') }}
<span v-show="isMainCanvas()">{{ $t('panel.panelNull') }}</span>
</el-row>
<div
v-else
@ -214,7 +214,7 @@ export default {
let style = {
width: '100%'
}
if (this.canvasStyleData.openCommonStyle) {
if (this.canvasStyleData.openCommonStyle && this.isMainCanvas()) {
if (this.canvasStyleData.panel.backgroundType === 'image' && this.canvasStyleData.panel.imageUrl) {
style = {
background: `url(${imgUrlTrans(this.canvasStyleData.panel.imageUrl)}) no-repeat`,
@ -308,6 +308,9 @@ export default {
bus.$off('trigger-reset-button', this.triggerResetButton)
},
methods: {
isMainCanvas() {
return this.canvasId === 'canvas-main'
},
triggerResetButton() {
this.triggerSearchButton(true)
},
@ -439,7 +442,7 @@ export default {
} else {
this.scaleHeight = canvasHeight * 100 / this.canvasStyleData.height//
}
if (this.canvasId === 'canvas-main') {
if (this.isMainCanvas()) {
this.$store.commit('setPreviewCanvasScale', { scaleWidth: (this.scaleWidth / 100), scaleHeight: (this.scaleHeight / 100) })
}
this.handleScaleChange()

View File

@ -27,6 +27,7 @@
<ComponentWrapper
v-for="(item, index) in componentDataInfo"
:key="index"
:canvas-id="canvasId"
:config="item"
:search-count="searchCount"
:canvas-style-data="canvasStyleData"
@ -55,6 +56,10 @@ export default {
event: 'change'
},
props: {
canvasId: {
type: String,
required: true
},
screenShot: {
type: Boolean,
default: false

View File

@ -134,12 +134,12 @@ export default {
linkJumpSetShow() {
return this.curComponent.type === 'view' &&
!this.jumpExcludeViewType.includes(this.curComponent.propValue.innerType) &&
!(this.curComponent.propValue.innerType.includes('table') && this.curComponent.propValue.render === 'echarts')
!(this.curComponent.propValue.innerType && this.curComponent.propValue.innerType.includes('table') && this.curComponent.propValue.render === 'echarts')
},
linkageSettingShow() {
return this.curComponent.type === 'view' &&
!this.linkageExcludeViewType.includes(this.curComponent.propValue.innerType) &&
!(this.curComponent.propValue.innerType.includes('table') && this.curComponent.propValue.render === 'echarts')
!(this.curComponent.propValue.innerType && this.curComponent.propValue.innerType.includes('table') && this.curComponent.propValue.render === 'echarts')
},
panelInfo() {
return this.$store.state.panel.panelInfo

View File

@ -588,7 +588,7 @@ export default {
mainStyle() {
const style = {
left: (this.getPositionX(this.curComponent.style.left) - this.scrollLeft) + 'px',
top: (this.getPositionY(this.curComponent.style.top) - this.scrollTop + 25) + 'px'
top: (this.getPositionY(this.curComponent.style.top) - this.scrollTop + 20) + 'px'
}
return style
},

View File

@ -1,6 +1,7 @@
<template>
<div
class="rich-main-class"
:style="autoStyle"
@dblclick="setEdit"
>
<Editor
@ -86,9 +87,9 @@ export default {
plugins: 'advlist autolink link image lists charmap media wordcount table contextmenu directionality pagebreak', //
//
toolbar: 'undo redo |fontselect fontsizeselect |forecolor backcolor bold italic |underline strikethrough link| formatselect |' +
'alignleft aligncenter alignright | bullist numlist |' +
' blockquote subscript superscript removeformat | table image media | fullscreen ' +
'| bdmap indent2em lineheight formatpainter axupimgs',
'alignleft aligncenter alignright | bullist numlist |' +
' blockquote subscript superscript removeformat | table image media | fullscreen ' +
'| bdmap indent2em lineheight formatpainter axupimgs',
toolbar_location: '/',
font_formats: '微软雅黑=Microsoft YaHei;宋体=SimSun;黑体=SimHei;仿宋=FangSong;华文黑体=STHeiti;华文楷体=STKaiti;华文宋体=STSong;华文仿宋=STFangsong;Andale Mono=andale mono,times;Arial=arial,helvetica,sans-serif;Arial Black=arial black,avant garde;Book Antiqua=book antiqua,palatino;Comic Sans MS=comic sans ms,sans-serif;Courier New=courier new,courier;Georgia=georgia,palatino;Helvetica=helvetica;Impact=impact,chicago;Symbol=symbol;Tahoma=tahoma,arial,helvetica,sans-serif;Terminal=terminal,monaco;Times New Roman=times new roman,times;Trebuchet MS=trebuchet ms,geneva;Verdana=verdana,geneva;Webdings=webdings;Wingdings=wingdings',
fontsize_formats: '12px 14px 16px 18px 20px 22px 24px 28px 32px 36px 48px 56px 72px', //
@ -169,37 +170,37 @@ export default {
</script>
<style lang="scss" scoped>
.rich-main-class {
width: 100%;
height: 100%;
overflow-y: auto!important;
position: relative;
}
::-webkit-scrollbar {
width: 0px!important;
height: 0px!important;
}
::v-deep ol {
display: block!important;
list-style-type: decimal;
margin-block-start: 1em!important;
margin-block-end: 1em!important;
margin-inline-start: 0px!important;
margin-inline-end: 0px!important;
padding-inline-start: 40px!important;
}
::v-deep ul {
display: block!important;
list-style-type: disc;
margin-block-start: 1em!important;
margin-block-end: 1em!important;
margin-inline-start: 0px!important;
margin-inline-end: 0px!important;
padding-inline-start: 40px!important;
}
::v-deep li {
display: list-item!important;
text-align: -webkit-match-parent!important;
}
.rich-main-class {
width: 100%;
height: 100%;
overflow-y: auto!important;
position: relative;
}
::-webkit-scrollbar {
width: 0px!important;
height: 0px!important;
}
::v-deep ol {
display: block!important;
list-style-type: decimal;
margin-block-start: 1em!important;
margin-block-end: 1em!important;
margin-inline-start: 0px!important;
margin-inline-end: 0px!important;
padding-inline-start: 40px!important;
}
::v-deep ul {
display: block!important;
list-style-type: disc;
margin-block-start: 1em!important;
margin-block-end: 1em!important;
margin-inline-start: 0px!important;
margin-inline-end: 0px!important;
padding-inline-start: 40px!important;
}
::v-deep li {
display: list-item!important;
text-align: -webkit-match-parent!important;
}
</style>

View File

@ -1,6 +1,7 @@
<template>
<div
class="rich-main-class"
:style="autoStyle"
@dblclick="setEdit"
>
<Editor

View File

@ -45,7 +45,7 @@ export default {
.el-date-editor {
padding-left: 12px;
width: 100%;
width: 100% !important;
}
.calendar-outlined {

View File

@ -56,7 +56,7 @@
</el-dropdown>
</span>
<de-canvas-tab
v-if="item.content && item.content.type==='canvas' && isEdit"
v-if="item.content && item.content.type==='canvas' && isEdit && !mobileLayoutStatus"
:ref="'canvasTabRef-'+item.name"
:parent-forbid="true"
:canvas-style-data="canvasStyleData"
@ -64,10 +64,13 @@
:canvas-id="element.id+'-'+item.name"
class="tab_canvas"
:class="moveActive ? 'canvas_move_in':''"
@canvasScroll="canvasScroll"
/>
<div style="width: 100%;height:100%">
<div
v-if="item.content && item.content.type==='canvas' && (!isEdit || mobileLayoutStatus)"
style="width: 100%;height:100%"
>
<Preview
v-if="item.content && item.content.type==='canvas' && !isEdit"
:component-data="tabCanvasComponentData(item.name)"
:canvas-style-data="canvasStyleData"
:canvas-id="element.id+'-'+item.name"
@ -193,6 +196,13 @@
</span>
</el-dialog>
<text-attr
v-if="showAttr && curComponent.canvasId !== 'canvas-main'"
:canvas-id="curComponent.canvasId"
:scroll-left="scrollLeft"
:scroll-top="scrollTop"
/>
</div>
</template>
@ -211,11 +221,16 @@ import { findPanelElementInfo } from '@/api/panel/panel'
import { getNowCanvasComponentData } from '@/components/canvas/utils/utils'
import DeCanvasTab from '@/components/canvas/DeCanvas'
import Preview from '@/components/canvas/components/Editor/Preview'
import TextAttr from '@/components/canvas/components/TextAttr'
export default {
name: 'DeTabs',
components: { Preview, DeCanvasTab, TabUseList, ViewSelect, DataeaseTabs },
components: { TextAttr, Preview, DeCanvasTab, TabUseList, ViewSelect, DataeaseTabs },
props: {
canvasId: {
type: String,
default: 'canvas-main'
},
element: {
type: Object,
default: null
@ -252,6 +267,20 @@ export default {
},
data() {
return {
scrollLeft: 50,
scrollTop: 10,
//
showAttrComponent: [
'custom',
'v-text',
'picture-add',
'de-tabs',
'rect-shape',
'de-show-date',
'de-video',
'de-stream-media',
'de-frame'
],
activeTabName: null,
tabIndex: 1,
dialogVisible: false,
@ -264,6 +293,23 @@ export default {
}
},
computed: {
curCanvasScaleSelf() {
return this.curCanvasScaleMap[this.canvasId]
},
showAttr() {
if (this.mobileLayoutStatus) {
return false
} else if (this.curComponent && this.showAttrComponent.includes(this.curComponent.type)) {
//
if (this.curComponent.type === 'custom' && (!this.curComponent.options.attrs.showTitle || !this.curComponent.options.attrs.title)) {
return false
} else {
return true
}
} else {
return false
}
},
moveActive() {
return this.tabMoveInActiveId && this.tabMoveInActiveId === this.element.id
},
@ -285,7 +331,9 @@ export default {
'curComponent',
'mobileLayoutStatus',
'canvasStyleData',
'tabMoveInActiveId'
'tabMoveInActiveId',
'curCanvasScaleMap',
'pcComponentData'
]),
fontColor() {
return this.element && this.element.style && this.element.style.headFontColor || 'none'
@ -360,9 +408,23 @@ export default {
bus.$off('add-new-tab', this.addNewTab)
},
methods: {
initScroll() {
this.scrollLeft = 50
this.scrollTop = 10
},
canvasScroll(scrollInfo) {
this.scrollLeft = scrollInfo.scrollLeft + 50
this.scrollTop = scrollInfo.scrollTop + 10
console.log('scrollInfo=' + JSON.stringify(scrollInfo))
bus.$emit('onScroll')
},
tabCanvasComponentData(tabName) {
const result = getNowCanvasComponentData(this.element.id + '-' + tabName)
return result
const tabCanvasId = this.element.id + '-' + tabName
if (this.mobileLayoutStatus) {
return this.pcComponentData.filter(item => item.canvasId === tabCanvasId)
} else {
return getNowCanvasComponentData(tabCanvasId)
}
},
setContentThemeStyle() {
this.element.options.tabList.forEach(tab => {

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 6.5 KiB

View File

@ -1423,6 +1423,7 @@ export default {
gauge_size_field_delete: 'Dynamic field changedplease edit again',
chart_group: 'Sub Type',
chart_bar_group: 'Bar Group',
chart_bar_group_stack: 'Group Stack Bar',
field_dynamic: 'Dynamic',
aggregation: 'Aggregation',
filter_between: 'Between',
@ -2631,6 +2632,28 @@ export default {
search_by_keyword: 'Search by keyword',
apply_logs: 'Apply logs',
app_group_delete_tips: 'Are you sure to delete this application category?',
app_group_delete_content: 'After deletion, all application templates in this category will also be deleted.'
app_group_delete_content: 'After deletion, all application templates in this category will also be deleted.',
panel_position: 'Panel position',
panel_name: 'Panel name',
dataset_group_position: 'Dataset group position',
dataset_group_name: 'Dataset name',
datasource_info: 'Datasource info',
datasource: 'Datasource',
dataset_group: 'Dataset group',
panel: 'Panel',
log_delete_tips: 'Are you sure to delete this application record?',
log_resource_delete_tips: 'Delete related resources (irrecoverable after deletion)',
file_error_tips: 'The relevant data file is not found. The current file may not be a DataEase application file, or the file may be damaged ',
app_export: 'Application export',
app_version: 'Application version',
program_version: 'DataEase minimum version',
creator: 'Author',
export: 'Export'
},
logout: {
oidc_logout_error: 'OIDC failed to exit, do you continue to exit DataEase?',
cas_logout_error: 'The CAS service is abnormal, please contact the administrator!'
}
}

View File

@ -1423,6 +1423,7 @@ export default {
gauge_size_field_delete: '動態值中字段發生變更,請重新編輯',
chart_group: '子類別',
chart_bar_group: '分組柱狀圖',
chart_bar_group_stack: '分組堆疊柱狀圖',
field_dynamic: '動態值',
aggregation: '聚合方式',
filter_between: '介於',
@ -2632,6 +2633,27 @@ export default {
search_by_keyword: '通過關鍵字搜索',
apply_logs: '應用記錄',
app_group_delete_tips: '確定刪除該應用分類嗎?',
app_group_delete_content: '刪除後,該分類中所有的應用模闆也將被刪除。'
app_group_delete_content: '刪除後,該分類中所有的應用模板也將被刪除。',
panel_position: '儀表板位置',
panel_name: '儀表板名稱',
dataset_group_position: '數據集分組位置',
dataset_group_name: '數據集分組名稱',
datasource_info: '數據源信息',
datasource: '數據源',
dataset_group: '數據集分組',
panel: '儀表板',
log_delete_tips: '確定刪除該條應用記錄嗎?',
log_resource_delete_tips: '刪除相關資源(刪除後不可恢復)',
file_error_tips: '未找到相關數據文件當前文件可能不是DataEase應用文件或者文件已經損壞',
app_export: '应用导出',
app_version: '应用版本',
program_version: 'DataEase最低版本',
creator: '作者',
export: '导出'
},
logout: {
oidc_logout_error: 'OIDC退出失敗是否繼續退出DataEase',
cas_logout_error: 'CAS服務異常請聯系管理員'
}
}

View File

@ -1422,6 +1422,7 @@ export default {
gauge_size_field_delete: '动态值中字段发生变更,请重新编辑',
chart_group: '子类别',
chart_bar_group: '分组柱状图',
chart_bar_group_stack: '分组堆叠柱状图',
field_dynamic: '动态值',
aggregation: '聚合方式',
filter_between: '介于',
@ -2632,6 +2633,27 @@ export default {
search_by_keyword: '通过关键字搜索',
apply_logs: '应用记录',
app_group_delete_tips: '确定删除该应用分类吗?',
app_group_delete_content: '删除后,该分类中所有的应用模板也将被删除。'
app_group_delete_content: '删除后,该分类中所有的应用模板也将被删除。',
panel_position: '仪表板位置',
panel_name: '仪表板名称',
dataset_group_position: '数据集分组位置',
dataset_group_name: '数据集分组名称',
datasource_info: '数据源信息',
datasource: '数据源',
dataset_group: '数据集分组',
panel: '仪表板',
log_delete_tips: '确定删除该条应用记录吗?',
log_resource_delete_tips: '删除相关资源(删除后不可恢复)',
file_error_tips: '未找到相关数据文件当前文件可能不是DataEase应用文件或者文件已经损坏',
app_export: '應用導出',
app_version: '應用版本',
program_version: 'DataEase最低版本',
creator: '作者',
export: '導出'
},
logout: {
oidc_logout_error: 'OIDC退出失败是否继续退出DataEase',
cas_logout_error: 'CAS服务异常请联系管理员'
}
}

View File

@ -151,8 +151,8 @@ const data = {
mouseY: 0,
width: 0,
height: 0
}
},
previewVisible: false
},
mutations: {
...animation.mutations,
@ -172,6 +172,10 @@ const data = {
state.isClickComponent = status
},
setPreviewVisible(state, previewVisible) {
state.previewVisible = previewVisible
},
setEditMode(state, mode) {
state.editMode = mode
},
@ -259,6 +263,7 @@ const data = {
} else {
state.componentData.push(component)
}
this.commit('setCurComponent', { component: component, index: index || state.componentData.length - 1 })
},
removeViewFilter(state, componentId) {
state.componentData = state.componentData.map(item => {

View File

@ -6,6 +6,7 @@ import { getLanguage } from '@/lang/index'
import Cookies from 'js-cookie'
import router from '@/router'
import i18n from '@/lang'
import { $alert, $confirm } from '@/utils/message'
const getDefaultState = () => {
return {
token: getToken(),
@ -146,6 +147,28 @@ const actions = {
resolve(res.data)
}).catch(error => {
reject(error)
if (error?.response?.data?.message) {
if (error.response.data.message === ('oidc_logout_error')) {
const message = i18n.t('logout.' + error.response.data.message)
$confirm(message, () => {
removeToken() // must remove token first
resetRouter()
commit('RESET_STATE')
window.location.href = '/'
}, {
confirmButtonText: i18n.t('commons.confirm')
})
}
if (error.response.data.message === ('cas_logout_error')) {
const message = i18n.t('logout.' + error.response.data.message)
$alert(message, () => {
}, {
confirmButtonText: i18n.t('commons.confirm'),
showClose: false
})
}
}
})
})
},

View File

@ -1632,4 +1632,29 @@ div:focus {
white-space: nowrap;
height: 24px;
}
}
.db-multiple-select-pop {
.selected::after {
content: '';
width: 6px;
height: 12px;
position: absolute;
right: 12px;
top: 9px;
border: 2px solid #3370ff;
border-top-color: rgba(0, 0, 0, 0);
border-left-color: rgba(0, 0, 0, 0);
-webkit-transform: rotate(45deg);
transform: rotate(45deg);
}
}
.role-add-name {
.el-select-dropdown__item.selected::after {
content: '';
position: absolute;
right: 12px;
top: 9px;
}
}

View File

@ -93,6 +93,12 @@ export function baseBarOptionAntV(plot, container, chart, action, isGroup, isSta
} else {
delete options.isStack
}
if (chart.type === 'bar-group-stack') {
options.groupField = 'group'
} else {
delete options.groupField
}
// 目前只有百分比堆叠柱状图需要这个属性,先直接在这边判断而不作为参数传过来
options.isPercent = chart.type === 'percentage-bar-stack'
// custom color

View File

@ -889,7 +889,9 @@ export const BASE_MAP = {
},
emphasis: {
label: {
show: false
}
}
}
}

View File

@ -195,7 +195,7 @@ export function getLabel(chart) {
f.formatterCfg.thousandSeparator = false
}
res = valueFormatter(param.value, f.formatterCfg)
} else if (chart.type === 'bar-group') {
} else if (equalsAny(chart.type, 'bar-group', 'bar-group-stack')) {
const f = yAxis[0]
if (f.formatterCfg) {
res = valueFormatter(param.value, f.formatterCfg)
@ -350,7 +350,11 @@ export function getTooltip(chart) {
}
}
} else if (chart.type.includes('group')) {
obj = { name: param.category, value: param.value }
if (chart.type === 'bar-group') {
obj = { name: param.category, value: param.value }
} else {
obj = { name: param.group, value: param.value }
}
for (let i = 0; i < yAxis.length; i++) {
const f = yAxis[i]
if (f.formatterCfg) {

View File

@ -95,6 +95,7 @@ export function baseMapOption(chart_option, chart, themeStyle, curAreaCode) {
chart_option.series[0].label.shadowBlur = 2
chart_option.series[0].label.showdowColor = customAttr.label.shadowColor
}
chart_option.series[0].itemStyle.emphasis.label.show = customAttr.label.show
}
const valueArr = chart.data.series[0].data
// visualMap

View File

@ -3,7 +3,6 @@ import { getCustomTheme, getSize } from '@/views/chart/chart/common/common_table
import { DEFAULT_COLOR_CASE, DEFAULT_TOTAL } from '@/views/chart/chart/chart'
import { formatterItem, valueFormatter } from '@/views/chart/chart/formatter'
import { hexColorToRGBA } from '@/views/chart/chart/util'
import Vue from 'vue'
export function baseTableInfo(s2, container, chart, action, tableData) {
const containerDom = document.getElementById(container)
@ -12,7 +11,6 @@ export function baseTableInfo(s2, container, chart, action, tableData) {
if (!fields || fields.length === 0) {
if (s2) {
s2.destroy()
destroyS2()
}
return
}
@ -140,7 +138,6 @@ export function baseTableInfo(s2, container, chart, action, tableData) {
// 开始渲染
if (s2) {
s2.destroy()
destroyS2
}
s2 = new TableSheet(containerDom, s2DataConfig, s2Options)
@ -163,7 +160,6 @@ export function baseTableNormal(s2, container, chart, action, tableData) {
if (!fields || fields.length === 0) {
if (s2) {
s2.destroy()
destroyS2
}
return
}
@ -278,7 +274,6 @@ export function baseTableNormal(s2, container, chart, action, tableData) {
// 开始渲染
if (s2) {
s2.destroy()
destroyS2()
}
s2 = new TableSheet(containerDom, s2DataConfig, s2Options)
@ -315,7 +310,6 @@ export function baseTablePivot(s2, container, chart, action, tableData) {
if (!fields || fields.length === 0) {
if (s2) {
s2.destroy()
destroyS2()
}
return
}
@ -437,7 +431,6 @@ export function baseTablePivot(s2, container, chart, action, tableData) {
// 开始渲染
if (s2) {
s2.destroy()
destroyS2()
}
s2 = new PivotSheet(containerDom, s2DataConfig, s2Options)
@ -451,13 +444,6 @@ export function baseTablePivot(s2, container, chart, action, tableData) {
return s2
}
function destroyS2(s2) {
for (const i in s2) {
Vue.$delete(s2, i)
}
s2 = null
}
function getCurrentField(valueFieldList, field) {
let list = []
let res = null

View File

@ -833,6 +833,85 @@ export const TYPE_CONFIGS = [
]
}
},
{
render: 'antv',
category: 'chart.chart_type_compare',
value: 'bar-group-stack',
title: 'chart.chart_bar_group_stack',
icon: 'bar-group-stack',
properties: [
'color-selector',
'size-selector-ant-v',
'label-selector-ant-v',
'tooltip-selector-ant-v',
'x-axis-selector-ant-v',
'y-axis-selector-ant-v',
'title-selector-ant-v',
'legend-selector-ant-v'
],
propertyInner: {
'color-selector': [
'value',
'colorPanel',
'customColor',
'alpha'
],
'size-selector-ant-v': [
'barDefault',
'barGap'
],
'label-selector-ant-v': [
'show',
'fontSize',
'color',
'position-v'
],
'tooltip-selector-ant-v': [
'show',
'textStyle'
],
'x-axis-selector-ant-v': [
'show',
'position',
'name',
'nameTextStyle',
'splitLine',
'axisForm',
'axisLabel'
],
'y-axis-selector-ant-v': [
'show',
'position',
'name',
'nameTextStyle',
'axisValue',
'splitLine',
'axisForm',
'axisLabel'
],
'title-selector-ant-v': [
'show',
'title',
'fontSize',
'color',
'hPosition',
'isItalic',
'isBolder',
'remarkShow',
'fontFamily',
'letterSpace',
'fontShadow'
],
'legend-selector-ant-v': [
'show',
'icon',
'orient',
'textStyle',
'hPosition',
'vPosition'
]
}
},
{
render: 'antv',
category: 'chart.chart_type_compare',

View File

@ -47,6 +47,9 @@
</div>
</div>
<div
:class="loading ? 'symbol-map-loading' : 'symbol-map-loaded'"
/>
</div>
</template>
@ -167,7 +170,8 @@ export default {
borderRadius: '0px',
mapCenter: null,
linkageActiveParam: null,
buttonTextColor: null
buttonTextColor: null,
loading: true
}
},
@ -222,6 +226,7 @@ export default {
}
},
preDraw() {
this.loading = true
// domecharts
// echartdom,idechart id
const that = this
@ -253,6 +258,10 @@ export default {
that.$refs.viewTrack.trackButtonClick()
}
})
this.myChart.off('finished')
this.myChart.on('finished', () => {
this.loading = false
})
})
},
loadThemeStyle() {

View File

@ -67,6 +67,7 @@ import TitleRemark from '@/views/chart/view/TitleRemark'
import { DEFAULT_TITLE_STYLE } from '@/views/chart/chart/chart'
import { baseMixOptionAntV } from '@/views/chart/chart/mix/mix_antv'
import { compareItem } from '@/views/chart/chart/compare'
import { mapState } from 'vuex'
import clickoutside from 'element-ui/src/utils/clickoutside.js'
import bus from '@/utils/bus'
@ -163,7 +164,11 @@ export default {
},
mainActiveName() {
return this.$store.state.panel.mainActiveName
}
},
...mapState([
'mobileLayoutStatus',
'previewVisible'
])
},
watch: {
chart: {
@ -253,6 +258,8 @@ export default {
this.myChart = baseBarOptionAntV(this.myChart, this.chartId, chart, this.antVAction, true, false)
} else if (chart.type === 'bar-stack' || chart.type === 'percentage-bar-stack') {
this.myChart = baseBarOptionAntV(this.myChart, this.chartId, chart, this.antVAction, false, true)
} else if (chart.type === 'bar-group-stack') {
this.myChart = baseBarOptionAntV(this.myChart, this.chartId, chart, this.antVAction, true, true)
} else if (chart.type === 'bar-horizontal') {
this.myChart = hBaseBarOptionAntV(this.myChart, this.chartId, chart, this.antVAction, true, false)
} else if (chart.type === 'bar-stack-horizontal') {
@ -442,7 +449,7 @@ export default {
})
},
handleTitleEditer() {
if (this.mainActiveName !== 'PanelEdit') return
if (this.mainActiveName !== 'PanelEdit' || this.mobileLayoutStatus || this.previewVisible) return
this.chartTitleEditer = true
this.chartTitleUpdate = this.chart.title
this.$nextTick(() => {

View File

@ -98,6 +98,7 @@ import TitleRemark from '@/views/chart/view/TitleRemark'
import { DEFAULT_TITLE_STYLE } from '@/views/chart/chart/chart'
import clickoutside from 'element-ui/src/utils/clickoutside.js'
import bus from '@/utils/bus'
import { mapState } from 'vuex'
import { compareItem } from '@/views/chart/chart/compare'
import {
getChartDetails
@ -197,7 +198,11 @@ export default {
},
mainActiveName() {
return this.$store.state.panel.mainActiveName
}
},
...mapState([
'mobileLayoutStatus',
'previewVisible'
])
},
watch: {
chart: {
@ -220,7 +225,6 @@ export default {
},
beforeDestroy() {
clearInterval(this.scrollTimer)
this.destroyS2()
},
methods: {
initData() {
@ -263,13 +267,6 @@ export default {
})
}
},
destroyS2() {
if (!this.myChart) return
for (const i in this.myChart) {
this.$delete(this.myChart, i)
}
this.myChart = null
},
drawView() {
const chart = this.chart
// type
@ -295,7 +292,6 @@ export default {
if (this.myChart) {
this.antVRenderStatus = false
this.myChart.destroy()
this.destroyS2()
}
}
@ -479,7 +475,7 @@ export default {
})
},
handleTitleEditer() {
if (this.mainActiveName !== 'PanelEdit') return
if (this.mainActiveName !== 'PanelEdit' || this.mobileLayoutStatus || this.previewVisible) return
this.chartTitleEditer = true
this.chartTitleUpdate = this.chart.title
this.$nextTick(() => {

View File

@ -12,10 +12,10 @@
:label="$t('chart.show')"
class="form-item"
>
<el-checkbox
<el-switch
v-model="titleForm.show"
@change="changeTitleStyle('show')"
>{{ $t('chart.show') }}</el-checkbox>
/>
</el-form-item>
<div v-show="showProperty('show') && titleForm.show">
<el-form-item

View File

@ -51,7 +51,7 @@
:title="$t('chart.assist_line')"
:visible="editLineDialog"
:show-close="false"
width="70%"
width="1000px"
class="dialog-css"
>
<assist-line-edit

View File

@ -243,7 +243,7 @@
:title="$t('chart.threshold')"
:visible="editLabelThresholdDialog"
:show-close="false"
width="50%"
width="800px"
class="dialog-css"
append-to-body
>
@ -274,7 +274,7 @@
:title="$t('chart.threshold')"
:visible="editTableThresholdDialog"
:show-close="false"
width="50%"
width="800px"
class="dialog-css"
append-to-body
>

View File

@ -17,6 +17,7 @@
<el-input
v-model="item.name"
class="value-item"
style="width: 90% !important;"
:placeholder="$t('chart.name')"
size="mini"
clearable
@ -97,6 +98,7 @@
v-model="item.summary"
size="mini"
class="select-item"
style="margin-left: 10px;"
:placeholder="$t('chart.aggregation')"
@change="changeAssistLine"
>

View File

@ -100,6 +100,7 @@
v-show="!item.term.includes('null') && !item.term.includes('empty') && item.term !== 'between'"
v-model="item.value"
class="value-item"
style="margin-left: 10px;"
:placeholder="$t('chart.drag_block_label_value')"
size="mini"
clearable
@ -426,7 +427,7 @@ span {
.between-item {
position: relative;
display: inline-block;
width: 80px !important;
width: 90px !important;
}
.select-item {

View File

@ -549,7 +549,7 @@
</el-row>
<!--group field,use xaxisExt-->
<el-row
v-if="view.type === 'bar-group'"
v-if="view.type === 'bar-group' || view.type === 'bar-group-stack'"
class="padding-lr"
>
<span style="width: 80px;text-align: right;">

View File

@ -123,7 +123,7 @@
</el-collapse-item>
</el-collapse>
</el-row>
<el-row>
<el-row class="de-collapse-style">
<span class="padding-lr">{{ $t('chart.module_style') }}</span>
<el-collapse
v-model="styleActiveNames"
@ -476,7 +476,7 @@ export default {
<style lang='scss' scoped>
.de-collapse-style {
.el-collapse-item__header {
::v-deep.el-collapse-item__header {
height: 34px !important;
line-height: 34px !important;
padding: 0 0 0 6px !important;

View File

@ -32,6 +32,7 @@
<el-select
v-model="dataSource"
class="ds-list"
popper-class="db-multiple-select-pop"
filterable
:placeholder="$t('dataset.pls_slc_data_source')"
size="small"
@ -623,20 +624,3 @@ export default {
}
}
</style>
<style lang="scss">
.db-select-pop {
.selected::after {
content: '';
width: 6px;
height: 12px;
position: absolute;
right: 12px;
top: 9px;
border: 2px solid #3370ff;
border-top-color: rgba(0, 0, 0, 0);
border-left-color: rgba(0, 0, 0, 0);
-webkit-transform: rotate(45deg);
transform: rotate(45deg);
}
}
</style>

View File

@ -33,7 +33,7 @@
v-model="dataSource"
class="ds-list"
filterable
popper-class="db-select-pop"
popper-class="db-multiple-select-pop"
:placeholder="$t('dataset.pls_slc_data_source')"
size="small"
>
@ -640,20 +640,3 @@ export default {
}
}
</style>
<style lang="scss">
.db-select-pop {
.selected::after {
content: '';
width: 6px;
height: 12px;
position: absolute;
right: 12px;
top: 9px;
border: 2px solid #3370ff;
border-top-color: rgba(0, 0, 0, 0);
border-left-color: rgba(0, 0, 0, 0);
-webkit-transform: rotate(45deg);
transform: rotate(45deg);
}
}
</style>

View File

@ -21,7 +21,7 @@
style="left: 55px"
class="el-form-item__error"
>
{{ $t('deDataset.already_Exists') }}
{{ $t('deDataset.already_exists') }}
</div>
</template>
<template v-else>

View File

@ -79,7 +79,7 @@
v-if="loginTypes.includes(7)"
:label="7"
size="mini"
>Larksuite</el-radio>
>Lark</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item prop="username">
@ -130,17 +130,17 @@
>
<el-row class="code-contaniner">
<plugin-com
v-if="loginTypes.includes(4) && codeIndex === 4"
v-if="codeShow && loginTypes.includes(4) && codeIndex === 4"
ref="WecomQr"
component-name="WecomQr"
/>
<plugin-com
v-if="loginTypes.includes(5) && codeIndex === 5"
v-if="codeShow && loginTypes.includes(5) && codeIndex === 5"
ref="DingtalkQr"
component-name="DingtalkQr"
/>
<plugin-com
v-if="loginTypes.includes(6) && codeIndex === 6"
v-if="codeShow && loginTypes.includes(6) && codeIndex === 6"
ref="LarkQr"
component-name="LarkQr"
/>
@ -210,7 +210,7 @@
<script>
import { encrypt } from '@/utils/rsaEncrypt'
import { ldapStatus, oidcStatus, getPublicKey, pluginLoaded, defaultLoginType, wecomStatus, dingtalkStatus, larkStatus, larksuiteStatus } from '@/api/user'
import { ldapStatus, oidcStatus, getPublicKey, pluginLoaded, defaultLoginType, wecomStatus, dingtalkStatus, larkStatus, larksuiteStatus, casStatus, casLoginPage } from '@/api/user'
import { getSysUI } from '@/utils/auth'
import { changeFavicon } from '@/utils/index'
import { initTheme } from '@/utils/ThemeUtil'
@ -282,6 +282,12 @@ export default {
this.contentShow = true
})
casStatus().then(res => {
if (res.success && res.data) {
this.loginTypes.push(3)
}
})
ldapStatus().then(res => {
if (res.success && res.data) {
this.loginTypes.push(1)
@ -340,6 +346,12 @@ export default {
if (res && res.success) {
this.defaultType = res.data
}
if (this.loginTypes.includes(3) && this.defaultType === 3) {
casLoginPage().then(res => {
debugger
window.location.href = res.data
})
}
this.setDefaultType()
})
},

View File

@ -32,7 +32,7 @@
</el-col>
<el-col
v-show="panel.backgroundType==='image'"
span="10"
:span="10"
>
<el-upload
action=""

View File

@ -0,0 +1,534 @@
<template>
<div style="width: 100%;height: 100%">
<div class="de-template">
<div
v-loading="$store.getters.loadingMap[$store.getters.currentPath]"
class="tabs-container flex-tabs"
>
<div class="de-tabs-left">
<template-list
ref="templateList"
:template-type="currentTemplateType"
:template-list="templateList"
:show-position="showPosition"
@templateDelete="templateListDelete"
@templateEdit="templateEdit"
@showCurrentTemplate="showCurrentTemplate"
@templateImport="templateImport"
@showTemplateEditDialog="showTemplateEditDialog"
/>
</div>
<div class="de-tabs-right">
<div
v-if="currentTemplateLabel"
class="active-template"
>
{{ currentTemplateLabel }}&nbsp;&nbsp;({{
currentTemplateShowList.length
}})
<deBtn
v-if="showPositionCheck('system-setting')"
type="primary"
icon="el-icon-upload2"
@click="templateImport(currentTemplateId)"
>
{{ $t('app_template.app_upload') }}
</deBtn>
</div>
<el-empty
v-if="!currentTemplateShowList.length"
:image="noneImg"
:description="$t('app_template.no_apps')"
/>
<div
v-show="currentTemplateId !== ''"
id="template-box"
class="template-box"
>
<template-item
v-for="item in currentTemplateShowList"
:key="item.id"
:width="templateCurWidth"
:model="item"
:show-position="showPosition"
@applyNew="applyNew(item)"
@previewApp="previewApp(item)"
@command="(key) => handleCommand(key, item)"
/>
</div>
</div>
</div>
</div>
<el-dialog
:title="dialogTitle"
:visible.sync="editTemplate"
append-to-body
class="de-dialog-form"
width="600px"
destroy-on-close="true"
>
<el-form
ref="templateEditForm"
class="de-form-item"
:model="templateEditForm"
:rules="templateEditFormRules"
>
<el-form-item
:label="dialogTitleLabel"
prop="name"
>
<el-input v-model="templateEditForm.name" />
</el-form-item>
<el-form-item
:label="$t('app_template.app_group_icon')"
prop="icon"
>
<el-col style="width: 148px!important;height: 148px!important;overflow: hidden">
<el-upload
action=""
accept=".jpeg,.jpg,.png,.gif,.svg"
class="avatar-uploader"
list-type="picture-card"
:class="{disabled:uploadDisabled}"
:on-preview="handlePictureCardPreview"
:on-remove="handleRemove"
:http-request="upload"
:file-list="fileList"
>
<i class="el-icon-plus" />
</el-upload>
<el-dialog
top="25vh"
width="600px"
:append-to-body="true"
:destroy-on-close="true"
:visible.sync="dialogVisible"
>
<img
width="100%"
:src="dialogImageUrl"
>
</el-dialog>
</el-col>
</el-form-item>
</el-form>
<div
slot="footer"
class="dialog-footer"
>
<deBtn
secondary
@click="close()"
>{{ $t('commons.cancel') }}
</deBtn>
<deBtn
type="primary"
@click="saveTemplateEdit(templateEditForm)"
>{{ $t('commons.confirm') }}
</deBtn>
</div>
</el-dialog>
<!--导入templatedialog-->
<el-dialog
:title="templateDialog.title"
:visible.sync="templateDialog.visible"
:show-close="true"
class="de-dialog-form"
width="600px"
>
<template-import
v-if="templateDialog.visible"
:pid="templateDialog.pid"
:opt-type="templateOptType"
:app-template-info="currentAppTemplateInfo"
@refresh="showCurrentTemplate(currentTemplateId,
currentTemplateLabel)"
@closeEditTemplateDialog="closeEditTemplateDialog"
/>
</el-dialog>
</div>
</template>
<script>
import TemplateList from './component/TemplateList'
import TemplateItem from './component/TemplateItem'
import TemplateImport from './component/TemplateImport'
import { save, update, templateDelete, find } from '@/api/system/appTemplate'
import elementResizeDetectorMaker from 'element-resize-detector'
import msgCfm from '@/components/msgCfm/index'
import { uploadFileResult } from '@/api/staticResource/staticResource'
import { imgUrlTrans } from '@/components/canvas/utils/utils'
export default {
name: 'AppTemplateContent',
components: { TemplateList, TemplateItem, TemplateImport },
mixins: [msgCfm],
props: {
showPosition: {
type: String,
required: false,
default: 'system-setting'
}
},
data() {
return {
templateOptType: 'add',
currentAppTemplateInfo: null,
fileList: [],
dialogImageUrl: '',
dialogVisible: false,
uploadDisabled: false,
showShare: false,
currentTemplateShowList: [],
noneImg: require('@/assets/None.png'),
currentPid: '',
currentTemplateType: 'self',
templateEditFormRules: {
name: [
{ required: true, trigger: 'blur', validator: this.roleValidator },
{
required: true,
message: this.$t('commons.input_content'),
trigger: 'blur'
},
{
max: 50,
message: this.$t('commons.char_can_not_more_50'),
trigger: 'change'
}
],
icon: [
{
required: true,
message: '请选择文件',
trigger: 'change'
}
]
},
templateEditForm: {},
editTemplate: false,
dialogTitle: '',
dialogTitleLabel: '',
currentTemplateLabel: '',
currentTemplateId: '',
templateList: [],
templateMiniWidth: 286,
templateCurWidth: 286,
formType: '',
originName: '',
templateDialog: {
title: '导入应用',
visible: false,
pid: ''
}
}
},
computed: {
nameList() {
const { nodeType } = this.templateEditForm || {}
if (nodeType === 'template') {
return this.currentTemplateShowList.map((ele) => ele.name)
}
if (nodeType === 'folder') {
return this.templateList.map((ele) => ele.name)
}
return []
}
},
mounted() {
this.getTree()
const _this = this
const erd = elementResizeDetectorMaker()
const templateMainDom = document.getElementById('template-box')
// div
erd.listenTo(templateMainDom, (element) => {
_this.$nextTick(() => {
const curSeparator = Math.trunc(
templateMainDom.offsetWidth / _this.templateMiniWidth
)
_this.templateCurWidth =
Math.trunc(templateMainDom.offsetWidth / curSeparator) - 24 - curSeparator
})
})
},
methods: {
previewApp(item) {
this.$emit('previewApp', item)
},
applyNew(item) {
this.$emit('applyNew', item)
},
showPositionCheck(requiredPosition) {
return this.showPosition === requiredPosition
},
roleValidator(rule, value, callback) {
if (this.nameRepeat(value)) {
const { nodeType } = this.templateEditForm || {}
callback(
new Error(
this.$t(
`system_parameter_setting.${
nodeType === 'folder'
? 'name_already_exists_type'
: 'the_same_category'
}`
)
)
)
} else {
callback()
}
},
nameRepeat(value) {
if (!this.nameList || this.nameList.length === 0) {
return false
}
//
if (this.formType === 'edit' && this.originName === value) {
return false
}
return this.nameList.some((name) => name === value)
},
handleCommand(key, data) {
switch (key) {
case 'rename':
this.templateEdit(data)
break
case 'delete':
this.templateDeleteConfirm(data)
break
case 'update':
this.updateAppTemplate(data)
break
default:
break
}
},
updateAppTemplate(data) {
this.templateOptType = 'update'
this.templateDialog.visible = true
this.currentAppTemplateInfo = data
this.templateDialog.pid = data.pid
},
templateDeleteConfirm(template) {
const options = {
title: '是否卸载当前应用?',
type: 'primary',
cb: () => this.templateDelete(template.id)
}
this.handlerConfirm(options, '卸载')
},
handleClick(tab, event) {
this.getTree()
},
showCurrentTemplate(pid, name) {
this.currentTemplateId = pid
this.currentTemplateLabel = name
if (this.currentTemplateId) {
find({ pid: this.currentTemplateId }).then((response) => {
this.currentTemplateShowList = response.data
})
}
},
templateListDelete(id) {
if (id) {
templateDelete(id).then((response) => {
this.openMessageSuccess('commons.delete_success')
this.getTree()
})
}
},
templateDelete(id) {
if (id) {
templateDelete(id).then((response) => {
this.openMessageSuccess('commons.delete_success')
this.showCurrentTemplate(this.currentTemplateId, this.currentTemplateLabel)
})
}
},
showTemplateEditDialog(type, templateInfo) {
this.templateEditForm = null
this.formType = type
if (type === 'edit') {
if (templateInfo.icon) {
this.fileList.push({ url: imgUrlTrans(templateInfo.icon) })
}
this.templateEditForm = JSON.parse(JSON.stringify(templateInfo))
this.dialogTitle = this.$t(
`system_parameter_setting.${
this.templateEditForm.nodeType === 'folder'
? 'edit_classification'
: 'edit_template'
}`
)
this.originName = this.templateEditForm.label
} else {
this.fileList = []
this.dialogTitle = this.$t('panel.add_app_category')
this.templateEditForm = {
name: '',
nodeType: 'folder',
templateType: this.currentTemplateType,
icon: '',
level: 0,
pid: 0
}
}
this.dialogTitleLabel = this.$t(
`system_parameter_setting.${
this.templateEditForm.nodeType === 'folder'
? 'classification_name'
: 'template_name'
}`
)
this.editTemplate = true
},
templateEdit(templateInfo) {
this.showTemplateEditDialog('edit', templateInfo)
},
saveTemplateEdit(templateEditForm) {
this.$refs['templateEditForm'].validate((valid) => {
if (valid) {
const method = templateEditForm.id ? update : save
method(templateEditForm).then((response) => {
this.close()
this.openMessageSuccess(
`system_parameter_setting.${
this.templateEditForm.id
? 'rename_succeeded'
: 'added_successfully'
}`
)
this.getTree()
})
} else {
return false
}
})
},
close() {
this.$refs['templateEditForm'].resetFields()
this.editTemplate = false
this.handleRemove()
},
getTree() {
const request = {
templateType: this.currentTemplateType,
pid: '0'
}
find(request).then((res) => {
this.templateList = res.data
this.showFirst()
})
},
showFirst() {
//
if (this.templateList && this.templateList.length > 0) {
let showFirst = true
this.templateList.forEach((template) => {
if (template.id === this.currentTemplateId) {
showFirst = false
}
})
if (showFirst) {
this.$nextTick().then(() => {
const [obj = {}] = this.templateList
this.$refs.templateList.nodeClick(obj)
})
} else {
this.showCurrentTemplate(this.currentTemplateId, this.currentTemplateLabel)
}
} else {
this.currentTemplateShowList = []
}
},
closeEditTemplateDialog() {
this.templateDialog.visible = false
},
templateImport(pid) {
this.templateOptType = 'new'
this.currentAppTemplateInfo = null
this.templateDialog.visible = true
this.templateDialog.pid = pid
},
handleRemove(file, fileList) {
this.uploadDisabled = false
this.templateEditForm.icon = null
this.fileList = []
},
handlePictureCardPreview(file) {
this.dialogImageUrl = file.url
this.dialogVisible = true
},
upload(file) {
const _this = this
uploadFileResult(file.file, (fileUrl) => {
_this.templateEditForm.icon = fileUrl
})
}
}
}
</script>
<style lang="scss" scoped>
.de-template {
height: 100%;
background-color: var(--MainBG, #f5f6f7);
.tabs-container {
height: 100%;
background: var(--ContentBG, #ffffff);
overflow-x: auto;
}
.flex-tabs {
display: flex;
background: #f5f6f7;
}
.de-tabs-left {
background: #fff;
width: 269px;
border-right: 1px solid rgba(31, 35, 41, 0.15);
padding: 24px;
}
.de-tabs-right {
flex: 1;
background: #fff;
padding: 24px 0 24px 24px;
overflow: hidden;
.template-box {
display: flex;
flex-wrap: wrap;
overflow-y: auto;
box-sizing: border-box;
align-content: flex-start;
height: calc(100% - 10px);
width: 100%;
padding-bottom: 24px;
}
.active-template {
margin: 4px 0 20px 0;
padding-right: 24px;
font-family: "PingFang SC";
font-style: normal;
font-weight: 500;
font-size: 16px;
display: flex;
align-items: center;
justify-content: space-between;
color: var(--deTextPrimary, #1f2329);
}
}
}
::v-deep .container-wrapper {
padding: 0px !important;
}
</style>

View File

@ -0,0 +1,57 @@
<template>
<el-drawer
v-closePress
:title="'应用模板'"
:visible.sync="applyDrawer"
custom-class="de-user-drawer"
size="600px"
direction="rtl"
>
<ds-form
v-if="applyDrawer"
:reference-position="'appMarket'"
:outer-params="outerParams"
@closeDraw="close"
/>
</el-drawer>
</template>
<script>
import DsForm from '@/views/system/datasource/DsForm'
export default {
name: 'AppTemplateApply',
components: {
DsForm
},
data() {
return {
outerParams: {},
applyDrawer: false
}
},
computed: {
},
mounted() {
},
methods: {
search() {
this.applyDrawer = false
this.$emit('search', this.formatCondition(), this.formatText())
},
init(params) {
this.applyDrawer = true
this.outerParams = params
},
close() {
this.$emit('closeDraw')
this.applyDrawer = false
}
}
}
</script>
<style scoped>
::v-deep .el-drawer__body{
padding: 0px 0px!important;
}
</style>

View File

@ -31,7 +31,7 @@
id="input"
ref="files"
type="file"
accept=".DEAPP"
accept=".zip"
hidden
@change="handleFileChange"
>
@ -47,14 +47,16 @@
secondary
@click="cancel()"
>{{
$t("commons.cancel")
}}</deBtn>
$t('commons.cancel')
}}
</deBtn>
<deBtn
type="primary"
@click="save()"
>{{
$t("commons.confirm")
}}</deBtn>
$t('commons.confirm')
}}
</deBtn>
</el-row>
</div>
</template>
@ -64,6 +66,7 @@ import { save, update, nameCheck } from '@/api/system/appTemplate'
import msgCfm from '@/components/msgCfm/index'
import { find } from '@/api/system/template'
import { imgUrlTrans } from '@/components/canvas/utils/utils'
import JSZip from 'jszip'
export default {
mixins: [msgCfm],
@ -186,22 +189,31 @@ export default {
})
},
handleFileChange(e) {
const jsZip = new JSZip()
const file = e.target.files[0]
const reader = new FileReader()
const _this = this
reader.onload = (res) => {
_this.appResultInfo = JSON.parse(res.target.result)
_this.importTemplateInfo = JSON.parse(this.appResultInfo.panelInfo)
_this.templateInfo.name = this.importTemplateInfo.name
_this.templateInfo.templateStyle = this.importTemplateInfo.panelStyle
_this.templateInfo.templateData = this.importTemplateInfo.panelData
_this.templateInfo.snapshot = this.importTemplateInfo.snapshot
_this.templateInfo.dynamicData = this.importTemplateInfo.dynamicData
_this.templateInfo.staticResource =
_this.importTemplateInfo.staticResource
_this.templateInfo.nodeType = 'template'
}
reader.readAsText(file)
jsZip.loadAsync(file).then(function(file) {
jsZip.file('DATA_RELATION.DE').async('string').then(function(content) {
_this.appResultInfo = { ...JSON.parse(content), ..._this.appResultInfo }
})
jsZip.file('APP.json').async('string').then(function(content) {
_this.appResultInfo['applicationInfo'] = content
const appInfo = JSON.parse(content)
_this.templateInfo.name = appInfo.appName
})
jsZip.file('TEMPLATE.DET').async('string').then(function(content) {
_this.appResultInfo['panelInfo'] = content
_this.importTemplateInfo = JSON.parse(content)
_this.templateInfo.templateStyle = _this.importTemplateInfo.panelStyle
_this.templateInfo.templateData = _this.importTemplateInfo.panelData
_this.templateInfo.snapshot = _this.importTemplateInfo.snapshot
_this.templateInfo.dynamicData = _this.importTemplateInfo.dynamicData
_this.templateInfo.staticResource = _this.importTemplateInfo.staticResource
_this.templateInfo.nodeType = 'template'
})
}).catch(() => {
_this.$warning(this.$t('app_template.file_error_tips'))
})
},
goFile() {
this.$refs.files.click()
@ -216,10 +228,12 @@ export default {
border: none;
padding: 0 0;
}
.my_table ::v-deep .el-table th.is-leaf {
/* 去除上边框 */
border: none;
}
.my_table ::v-deep .el-table::before {
/* 去除下边框 */
height: 0;
@ -229,6 +243,7 @@ export default {
margin-top: 24px;
text-align: right;
}
.preview {
margin-top: -12px;
border: 1px solid #e6e6e6;
@ -237,6 +252,7 @@ export default {
background-size: 100% 100% !important;
border-radius: 4px;
}
.preview-show {
border-left: 1px solid #e6e6e6;
height: 300px;
@ -250,6 +266,7 @@ export default {
display: flex;
align-items: center;
justify-content: space-between;
.el-input {
margin-right: 2px;
flex: 1;

View File

@ -12,7 +12,10 @@
alt=""
>
</div>
<div class="card-info">
<div
v-if="showPositionCheck('system-setting')"
class="card-info"
>
<el-tooltip
class="item"
effect="dark"
@ -34,22 +37,60 @@
<slot>
<el-dropdown-item command="update">
<i class="el-icon-edit" />
{{ $t("commons.update") }}
{{ $t('commons.update') }}
</el-dropdown-item>
<el-dropdown-item command="delete">
<i class="el-icon-delete" />
{{ $t("commons.uninstall") }}
{{ $t('commons.uninstall') }}
</el-dropdown-item>
</slot>
</el-dropdown-menu>
</el-dropdown>
</div>
<div
v-if="showPositionCheck('market-manage')"
class="card-info-apply"
>
<el-row>
<el-row>
<el-tooltip
class="item"
effect="dark"
:content="model.name"
placement="top"
>
<span class="de-model-text-market">{{ model.name }}</span>
</el-tooltip>
</el-row>
<el-row class="market-button-area">
<el-button
size="small"
style="width: 45%"
@click="templatePreview"
>{{ $t('panel.preview') }}
</el-button>
<el-button
size="small"
style="width: 45%"
type="primary"
@click="apply"
>{{ $t('panel.apply') }}
</el-button>
</el-row>
</el-row>
</div>
</div>
</template>
<script>
export default {
props: {
showPosition: {
type: String,
required: false,
default: 'system-setting'
},
model: {
type: Object,
default: () => {
@ -74,6 +115,15 @@ export default {
}
},
methods: {
templatePreview() {
this.$emit('previewApp')
},
apply() {
this.$emit('applyNew')
},
showPositionCheck(requiredPosition) {
return this.showPosition === requiredPosition
},
handleCommand(key) {
this.$emit('command', key)
}
@ -83,6 +133,7 @@ export default {
<style lang="scss">
.de-card-model {
position: relative;
box-sizing: border-box;
background: #ffffff;
border: 1px solid var(--deCardStrokeColor, #dee0e3);
@ -132,20 +183,67 @@ export default {
}
}
.de-model-text {
font-family: "PingFang SC";
font-style: normal;
font-weight: 400;
font-size: 14px;
line-height: 22px;
color: #1f2329;
display: inline-block;
width: 90%;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
margin-right: 10px;
&:hover .card-info-apply {
height: 92px;
}
&:hover .market-button-area {
display: block;
}
.market-button-area {
text-align: center;
margin-top: 4px;
display: none;
}
.card-info-apply {
background: #ffffff;
width: 100%;
height: 48px;
position: absolute;
bottom: 0px;
left: 0px;
transition: height 0.3s ease-out;
align-items: center;
justify-content: space-between;
padding: 12px 12px 12px 12px;
box-sizing: border-box;
border-radius: 0 0 4px 4px;
border-top: 1px solid var(--deCardStrokeColor, #dee0e3);
overflow-y: hidden;
}
}
.de-model-text {
font-family: "PingFang SC";
font-style: normal;
font-weight: 400;
font-size: 14px;
line-height: 22px;
color: #1f2329;
display: inline-block;
width: 90%;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
margin-right: 10px;
}
.de-model-text-market {
font-family: "PingFang SC";
font-style: normal;
color: #1f2329;
display: inline-block;
width: 90%;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
margin-right: 10px;
font-weight: 500;
font-size: 16px;
line-height: 24px;
}
.de-card-model:hover {

View File

@ -29,12 +29,15 @@
:class="[{ select: activeTemplate === ele.id }]"
@click="nodeClick(ele)"
>
<svg-icon
style="margin-right: 9px"
icon-class="scene"
/>
<img
:src="iconImgRul(ele.icon)"
style="margin-right: 8px;border-radius: 4px"
width="24"
height="24"
>
<span>{{ ele.name }}</span>
<span
v-if="showPositionCheck('system-setting')"
class="more"
@click.stop
>
@ -74,7 +77,7 @@
</li>
</ul>
<deBtn
v-if="templateFilterText === ''"
v-if="templateFilterText === '' && showPositionCheck('system-setting')"
style="width: 100%"
icon="el-icon-plus"
secondary
@ -87,12 +90,18 @@
<script>
import msgCfm from '@/components/msgCfm/index'
import { imgUrlTrans } from '@/components/canvas/utils/utils'
export default {
name: 'TemplateList',
components: {},
mixins: [msgCfm],
props: {
showPosition: {
type: String,
required: false,
default: 'system-setting'
},
templateType: {
type: String,
default: ''
@ -114,13 +123,6 @@ export default {
},
computed: {
templateListComputed() {
// if (!this.templateFilterText)
// return [
// ...this.templateList,
// ...this.templateList,
// ...this.templateList,
// ...this.templateList,
// ];
if (!this.templateFilterText) return [...this.templateList]
return this.templateList.filter((ele) =>
ele.name.includes(this.templateFilterText)
@ -128,6 +130,12 @@ export default {
}
},
methods: {
showPositionCheck(requiredPosition) {
return this.showPosition === requiredPosition
},
iconImgRul(iconUrl) {
return imgUrlTrans(iconUrl)
},
clickMore(type, data) {
switch (type) {
case 'edit':

View File

@ -1,513 +1,15 @@
<template>
<de-layout-content>
<div class="de-template">
<div
v-loading="$store.getters.loadingMap[$store.getters.currentPath]"
class="tabs-container flex-tabs"
>
<div class="de-tabs-left">
<template-list
ref="templateList"
:template-type="currentTemplateType"
:template-list="templateList"
@templateDelete="templateListDelete"
@templateEdit="templateEdit"
@showCurrentTemplate="showCurrentTemplate"
@templateImport="templateImport"
@showTemplateEditDialog="showTemplateEditDialog"
/>
</div>
<div class="de-tabs-right">
<div
v-if="currentTemplateLabel"
class="active-template"
>
{{ currentTemplateLabel }}&nbsp;&nbsp;({{
currentTemplateShowList.length
}})
<deBtn
type="primary"
icon="el-icon-upload2"
@click="templateImport(currentTemplateId)"
>
{{ $t('app_template.app_upload') }}
</deBtn>
</div>
<el-empty
v-if="!currentTemplateShowList.length"
:image="noneImg"
:description="$t('app_template.no_apps')"
/>
<div
v-show="currentTemplateId !== ''"
id="template-box"
class="template-box"
>
<template-item
v-for="item in currentTemplateShowList"
:key="item.id"
:width="templateCurWidth"
:model="item"
@command="(key) => handleCommand(key, item)"
/>
</div>
</div>
</div>
</div>
<el-dialog
:title="dialogTitle"
:visible.sync="editTemplate"
append-to-body
class="de-dialog-form"
width="600px"
destroy-on-close="true"
>
<el-form
ref="templateEditForm"
class="de-form-item"
:model="templateEditForm"
:rules="templateEditFormRules"
>
<el-form-item
:label="dialogTitleLabel"
prop="name"
>
<el-input v-model="templateEditForm.name" />
</el-form-item>
<el-form-item
:label="$t('app_template.app_group_icon')"
prop="icon"
>
<el-col style="width: 148px!important;height: 148px!important;overflow: hidden">
<el-upload
action=""
accept=".jpeg,.jpg,.png,.gif,.svg"
class="avatar-uploader"
list-type="picture-card"
:class="{disabled:uploadDisabled}"
:on-preview="handlePictureCardPreview"
:on-remove="handleRemove"
:http-request="upload"
:file-list="fileList"
>
<i class="el-icon-plus" />
</el-upload>
<el-dialog
top="25vh"
width="600px"
:append-to-body="true"
:destroy-on-close="true"
:visible.sync="dialogVisible"
>
<img
width="100%"
:src="dialogImageUrl"
>
</el-dialog>
</el-col>
</el-form-item>
</el-form>
<div
slot="footer"
class="dialog-footer"
>
<deBtn
secondary
@click="close()"
>{{ $t("commons.cancel") }}</deBtn>
<deBtn
type="primary"
@click="saveTemplateEdit(templateEditForm)"
>{{ $t("commons.confirm") }}
</deBtn>
</div>
</el-dialog>
<!--导入templatedialog-->
<el-dialog
:title="templateDialog.title"
:visible.sync="templateDialog.visible"
:show-close="true"
class="de-dialog-form"
width="600px"
>
<template-import
v-if="templateDialog.visible"
:pid="templateDialog.pid"
:opt-type="templateOptType"
:app-template-info="currentAppTemplateInfo"
@refresh="showCurrentTemplate(currentTemplateId,
currentTemplateLabel)"
@closeEditTemplateDialog="closeEditTemplateDialog"
/>
</el-dialog>
<app-template-content :show-position="'system-setting'" />
</de-layout-content>
</template>
<script>
import AppTemplateContent from '@/views/panel/appTemplate/AppTemplateContent'
import DeLayoutContent from '@/components/business/DeLayoutContent'
import TemplateList from './component/TemplateList'
import TemplateItem from './component/TemplateItem'
import TemplateImport from './component/TemplateImport'
import { save, update, templateDelete, find } from '@/api/system/appTemplate'
import elementResizeDetectorMaker from 'element-resize-detector'
import msgCfm from '@/components/msgCfm/index'
import { uploadFileResult } from '@/api/staticResource/staticResource'
import { imgUrlTrans } from '@/components/canvas/utils/utils'
export default {
name: 'AppTemplate',
components: { DeLayoutContent, TemplateList, TemplateItem, TemplateImport },
mixins: [msgCfm],
data() {
return {
templateOptType: 'add',
currentAppTemplateInfo: null,
fileList: [],
dialogImageUrl: '',
dialogVisible: false,
uploadDisabled: false,
showShare: false,
currentTemplateShowList: [],
noneImg: require('@/assets/None.png'),
currentPid: '',
currentTemplateType: 'self',
templateEditFormRules: {
name: [
{ required: true, trigger: 'blur', validator: this.roleValidator },
{
required: true,
message: this.$t('commons.input_content'),
trigger: 'blur'
},
{
max: 50,
message: this.$t('commons.char_can_not_more_50'),
trigger: 'change'
}
],
icon: [
{
required: true,
message: '请选择文件',
trigger: 'change'
}
]
},
templateEditForm: {},
editTemplate: false,
dialogTitle: '',
dialogTitleLabel: '',
currentTemplateLabel: '',
currentTemplateId: '',
templateList: [],
templateMiniWidth: 286,
templateCurWidth: 286,
formType: '',
originName: '',
templateDialog: {
title: '导入应用',
visible: false,
pid: ''
}
}
},
computed: {
nameList() {
const { nodeType } = this.templateEditForm || {}
if (nodeType === 'template') {
return this.currentTemplateShowList.map((ele) => ele.name)
}
if (nodeType === 'folder') {
return this.templateList.map((ele) => ele.name)
}
return []
}
},
mounted() {
this.getTree()
const _this = this
const erd = elementResizeDetectorMaker()
const templateMainDom = document.getElementById('template-box')
// div
erd.listenTo(templateMainDom, (element) => {
_this.$nextTick(() => {
const curSeparator = Math.trunc(
templateMainDom.offsetWidth / _this.templateMiniWidth
)
_this.templateCurWidth =
Math.trunc(templateMainDom.offsetWidth / curSeparator) - 24 - curSeparator
})
})
},
methods: {
roleValidator(rule, value, callback) {
if (this.nameRepeat(value)) {
const { nodeType } = this.templateEditForm || {}
callback(
new Error(
this.$t(
`system_parameter_setting.${
nodeType === 'folder'
? 'name_already_exists_type'
: 'the_same_category'
}`
)
)
)
} else {
callback()
}
},
nameRepeat(value) {
if (!this.nameList || this.nameList.length === 0) {
return false
}
//
if (this.formType === 'edit' && this.originName === value) {
return false
}
return this.nameList.some((name) => name === value)
},
handleCommand(key, data) {
switch (key) {
case 'rename':
this.templateEdit(data)
break
case 'delete':
this.templateDeleteConfirm(data)
break
case 'update':
this.updateAppTemplate(data)
break
default:
break
}
},
updateAppTemplate(data) {
this.templateOptType = 'update'
this.templateDialog.visible = true
this.currentAppTemplateInfo = data
this.templateDialog.pid = data.pid
},
templateDeleteConfirm(template) {
const options = {
title: '是否卸载当前应用?',
type: 'primary',
cb: () => this.templateDelete(template.id)
}
this.handlerConfirm(options, '卸载')
},
handleClick(tab, event) {
this.getTree()
},
showCurrentTemplate(pid, name) {
this.currentTemplateId = pid
this.currentTemplateLabel = name
if (this.currentTemplateId) {
find({ pid: this.currentTemplateId }).then((response) => {
this.currentTemplateShowList = response.data
})
}
},
templateListDelete(id) {
if (id) {
templateDelete(id).then((response) => {
this.openMessageSuccess('commons.delete_success')
this.getTree()
})
}
},
templateDelete(id) {
if (id) {
templateDelete(id).then((response) => {
this.openMessageSuccess('commons.delete_success')
this.showCurrentTemplate(this.currentTemplateId, this.currentTemplateLabel)
})
}
},
showTemplateEditDialog(type, templateInfo) {
this.templateEditForm = null
this.formType = type
if (type === 'edit') {
if (templateInfo.icon) {
this.fileList.push({ url: imgUrlTrans(templateInfo.icon) })
}
this.templateEditForm = JSON.parse(JSON.stringify(templateInfo))
this.dialogTitle = this.$t(
`system_parameter_setting.${
this.templateEditForm.nodeType === 'folder'
? 'edit_classification'
: 'edit_template'
}`
)
this.originName = this.templateEditForm.label
} else {
this.fileList = []
this.dialogTitle = this.$t('panel.add_app_category')
this.templateEditForm = {
name: '',
nodeType: 'folder',
templateType: this.currentTemplateType,
icon: '',
level: 0,
pid: 0
}
}
this.dialogTitleLabel = this.$t(
`system_parameter_setting.${
this.templateEditForm.nodeType === 'folder'
? 'classification_name'
: 'template_name'
}`
)
this.editTemplate = true
},
templateEdit(templateInfo) {
this.showTemplateEditDialog('edit', templateInfo)
},
saveTemplateEdit(templateEditForm) {
this.$refs['templateEditForm'].validate((valid) => {
if (valid) {
const method = templateEditForm.id ? update : save
method(templateEditForm).then((response) => {
this.close()
this.openMessageSuccess(
`system_parameter_setting.${
this.templateEditForm.id
? 'rename_succeeded'
: 'added_successfully'
}`
)
this.getTree()
})
} else {
return false
}
})
},
close() {
this.$refs['templateEditForm'].resetFields()
this.editTemplate = false
this.handleRemove()
},
getTree() {
const request = {
templateType: this.currentTemplateType,
pid: '0'
}
find(request).then((res) => {
this.templateList = res.data
this.showFirst()
})
},
showFirst() {
//
if (this.templateList && this.templateList.length > 0) {
let showFirst = true
this.templateList.forEach((template) => {
if (template.id === this.currentTemplateId) {
showFirst = false
}
})
if (showFirst) {
this.$nextTick().then(() => {
const [obj = {}] = this.templateList
this.$refs.templateList.nodeClick(obj)
})
} else {
this.showCurrentTemplate(this.currentTemplateId, this.currentTemplateLabel)
}
} else {
this.currentTemplateShowList = []
}
},
closeEditTemplateDialog() {
this.templateDialog.visible = false
},
templateImport(pid) {
this.templateOptType = 'new'
this.currentAppTemplateInfo = null
this.templateDialog.visible = true
this.templateDialog.pid = pid
},
handleRemove(file, fileList) {
this.uploadDisabled = false
this.templateEditForm.icon = null
this.fileList = []
},
handlePictureCardPreview(file) {
this.dialogImageUrl = file.url
this.dialogVisible = true
},
upload(file) {
const _this = this
uploadFileResult(file.file, (fileUrl) => {
_this.templateEditForm.icon = fileUrl
})
}
}
components: { DeLayoutContent, AppTemplateContent }
}
</script>
<style lang="scss" scoped>
.de-template {
height: 100%;
background-color: var(--MainBG, #f5f6f7);
.tabs-container {
height: 100%;
background: var(--ContentBG, #ffffff);
overflow-x: auto;
}
.flex-tabs {
display: flex;
background: #f5f6f7;
}
.de-tabs-left {
background: #fff;
width: 269px;
border-right: 1px solid rgba(31, 35, 41, 0.15);
padding: 24px;
}
.de-tabs-right {
flex: 1;
background: #fff;
padding: 24px 0 24px 24px;
overflow: hidden;
.template-box {
display: flex;
flex-wrap: wrap;
overflow-y: auto;
box-sizing: border-box;
align-content: flex-start;
height: calc(100% - 10px);
width: 100%;
padding-bottom: 24px;
}
.active-template {
margin: 4px 0 20px 0;
padding-right: 24px;
font-family: "PingFang SC";
font-style: normal;
font-weight: 500;
font-size: 16px;
display: flex;
align-items: center;
justify-content: space-between;
color: var(--deTextPrimary, #1f2329);
}
}
}
::v-deep .container-wrapper {
padding: 0px !important;
}
</style>

View File

@ -0,0 +1,125 @@
<template>
<el-row>
<el-row style="height: 56px">
<el-col
:span="12"
style="text-align: left;line-height: 56px"
>
<svg-icon
icon-class="icon_left_outlined"
class="toolbar-icon-active icon20 margin-left20"
@click="closePreview"
/>
<span class="text16 margin-left12">
{{ templateInfo.name }}
</span>
</el-col>
<el-col
:span="12"
style="text-align: right;line-height: 56px;padding-right: 24px"
>
<el-button
size="small"
type="primary"
width="80px"
@click="appApply"
>{{ $t('panel.apply') }}
</el-button>
</el-col>
</el-row>
<el-row class="img-main">
<img
width="100%"
:src="templateInfo.snapshot"
alt=""
>
</el-row>
</el-row>
</template>
<script>
export default {
name: 'AppMarketPreview',
components: { },
props: {
templateInfo: {
type: Object,
required: true
}
},
data() {
return {
noneImg: require('@/assets/None.png')
}
},
computed: {
},
watch: {
},
mounted() {
},
methods: {
appApply() {
this.$emit('appApply')
},
closePreview() {
this.$emit('closePreview')
}
}
}
</script>
<style lang="scss" scoped>
.img-main{
border-radius: 4px;
overflow-x: auto;
overflow-y: auto;
text-align: center;
height: calc(100vh - 113px)!important;
}
.toolbar-icon-active {
cursor: pointer;
transition: .1s;
border-radius: 3px;
&:active {
color: #000;
border-color: #3a8ee6;
background-color: red;
outline: 0;
}
&:hover {
background-color: rgba(31, 35, 41, 0.1);
color: #3a8ee6;
}
}
.icon20 {
font-size: 20px;
color: var(--TextPrimary, #1F2329);
}
.icon16 {
font-size: 16px!important;
color: var(--TextPrimary, #1F2329);
}
.text16 {
font-size: 16px;
font-weight: 500;
line-height: 24px;
color: var(--TextPrimary, #1F2329);
}
.margin-left12 {
margin-left: 12px !important;
}
.margin-left20 {
margin-left: 12px !important;
}
</style>

View File

@ -1,12 +1,11 @@
<template>
<el-row class="outer-body">
<!--预览模式-->
<MarketPreview
<AppMarketPreview
v-if="previewModel"
:preview-id="templatePreviewId"
:current-app="currentApp"
:template-info="previewItem"
@closePreview="previewModel=false"
@templateApply="templateApply"
@appApply="appApply"
/>
<!--列表模式-->
<el-row
@ -32,42 +31,16 @@
</el-tabs>
</el-row>
<el-row v-show="marketActiveTab==='apps'">
<el-row
v-show="hasResult"
id="template-main"
v-loading="$store.getters.loadingMap[$store.getters.currentPath]"
class="template-main"
>
<el-col
v-for="(templateItem) in currentAppShowList"
:key="templateItem.id"
style="text-align: center;padding: 24px 12px 0 12px"
:style="{width: templateSpan}"
>
<app-template-item
:template="templateItem"
:base-url="baseUrl"
:width="templateCurWidth"
@appPreview="appPreview"
/>
</el-col>
</el-row>
<el-row
v-show="!hasResult"
class="custom-position template-main"
>
<div style="text-align: center">
<svg-icon
icon-class="no_result"
style="font-size: 75px;margin-bottom: 16px"
/>
<br>
<span>{{ $t('commons.no_result') }}</span>
</div>
</el-row>
<app-template-content
:ref="'appTemplateContent'"
class="template-main-content"
:show-position="'market-manage'"
@previewApp="previewApp"
@applyNew="applyNew"
/>
</el-row>
<el-row
v-show="marketActiveTab==='apply_logs'"
v-if="marketActiveTab==='apply_logs'"
class="main-log-area template-main"
>
<app-template-log class="log-area" />
@ -123,15 +96,23 @@
<el-button
size="mini"
@click="folderSelectShow=false"
>{{ $t('commons.cancel') }}</el-button>
>{{ $t('commons.cancel') }}
</el-button>
<el-button
size="mini"
type="primary"
:disabled="!panelForm.name || !panelForm.pid"
@click="apply"
>{{ $t('commons.confirm') }}</el-button>
>{{ $t('commons.confirm') }}
</el-button>
</div>
</el-dialog>
<keep-alive>
<app-template-apply
ref="templateApply"
/>
</keep-alive>
</el-row>
</template>
@ -139,16 +120,18 @@
import { searchAppTemplate } from '@/api/appTemplateMarket'
import { groupTree, panelSave } from '@/api/panel/panel'
import { DEFAULT_COMMON_CANVAS_STYLE_STRING } from '@/views/panel/panel'
import MarketPreview from '@/views/panel/appTemplateMarket/component/MarketPreview'
import elementResizeDetectorMaker from 'element-resize-detector'
import AppTemplateItem from '@/views/panel/appTemplateMarket/component/AppTemplateItem'
import AppTemplateLog from '@/views/panel/appTemplateMarket/log'
import AppTemplateContent from '@/views/panel/appTemplate/AppTemplateContent'
import AppMarketPreview from '@/views/panel/appTemplateMarket/component/AppMarketPreview'
import AppTemplateApply from '@/views/panel/appTemplate/component/AppTemplateApply'
export default {
name: 'AppTemplateMarket',
components: { AppTemplateLog, AppTemplateItem, MarketPreview },
components: { AppTemplateApply, AppMarketPreview, AppTemplateContent, AppTemplateLog },
data() {
return {
previewItem: null,
hasResult: true,
templateMiniWidth: 330,
templateCurWidth: 310,
@ -194,11 +177,8 @@ export default {
}
}
},
computed: {
},
watch: {
},
computed: {},
watch: {},
mounted() {
this.initMarketTemplate()
this.getGroupTree()
@ -215,6 +195,24 @@ export default {
})
},
methods: {
applyNew(item) {
const datasourceInfo = JSON.parse(item.datasourceInfo)[0]
const param = {
datasourceType: datasourceInfo.type,
appTemplateId: item.id,
appTemplateName: item.name,
panelName: item.name,
datasetGroupName: item.name
}
this.$refs.templateApply.init(param)
},
appApply() {
this.applyNew(this.previewItem)
},
previewApp(item) {
this.previewModel = true
this.previewItem = item
},
initMarketTemplate() {
searchAppTemplate({ nodeType: 'folder' }).then(rsp => {
this.currentAppShowList = rsp.data
@ -280,109 +278,120 @@ export default {
</script>
<style lang="scss" scoped>
.template-main{
text-align: center;
border-radius: 4px;
padding: 0 12px 24px 12px;
height: calc(100vh - 190px)!important;
overflow-x: hidden;
overflow-y: auto;
background-color: var(--ContentBG,#ffffff);
}
.market-main{
padding:24px
}
.title-left{
float: left;
font-size: 20px;
font-weight: 500;
line-height: 28px;
color: var(--TextPrimary, #1F2329);
}
.title-right{
float: right;
width: 320px;
}
.dialog-footer-self{
text-align: right;
}
.search-button-self{
text-align: left;
padding-left: 10px;
}
.template-main-content {
height: calc(100vh - 190px) !important;
}
.topbar-icon-active {
cursor: pointer;
transition: .1s;
border-radius: 3px;
font-size: 22px;
background-color: rgb(245, 245, 245);
.template-main {
text-align: center;
border-radius: 4px;
padding: 0 12px 24px 12px;
height: calc(100vh - 190px) !important;
overflow-x: hidden;
overflow-y: auto;
background-color: var(--ContentBG, #ffffff);
}
.market-main {
padding: 24px
}
.title-left {
float: left;
font-size: 20px;
font-weight: 500;
line-height: 28px;
color: var(--TextPrimary, #1F2329);
}
.title-right {
float: right;
width: 320px;
}
.dialog-footer-self {
text-align: right;
}
.search-button-self {
text-align: left;
padding-left: 10px;
}
.topbar-icon-active {
cursor: pointer;
transition: .1s;
border-radius: 3px;
font-size: 22px;
background-color: rgb(245, 245, 245);
&:active {
color: #000;
border-color: #3a8ee6;
background-color: red;
outline: 0;
}
color: #000;
border-color: #3a8ee6;
background-color: red;
outline: 0;
}
&:hover {
background-color: rgba(31, 35, 41, 0.1);
color: #3a8ee6;
}
background-color: rgba(31, 35, 41, 0.1);
color: #3a8ee6;
}
.custom-position {
height: 80vh;
flex: 1;
display: flex;
align-items: center;
justify-content: space-between;
font-size: 14px;
flex-flow: row nowrap;
color: #646A73;
font-weight: 400;
}
.outer-body{
width: 100%;
height: calc(100vh - 56px);
background-color: var(--MainBG,#f5f6f7);
}
.custom-position {
height: 80vh;
flex: 1;
display: flex;
align-items: center;
justify-content: space-between;
font-size: 14px;
flex-flow: row nowrap;
color: #646A73;
font-weight: 400;
}
.outer-body {
width: 100%;
height: calc(100vh - 56px);
background-color: var(--MainBG, #f5f6f7);
}
.market-dialog-css {
::v-deep .el-form-item__label {
width: 100% !important;
text-align: left;
}
.market-dialog-css{
::v-deep .el-form-item__label {
width: 100% !important;
text-align: left;
}
::v-deep
.el-form-item.is-required:not(.is-no-asterisk)
> .el-form-item__label:before {
display: none;
}
::v-deep
.el-form-item.is-required:not(.is-no-asterisk)
> .el-form-item__label::after {
content: "*";
color: #f54a45;
margin-left: 2px;
}
::v-deep .el-form-item__content {
margin-left: 0 !important;
}
::v-deep .vue-treeselect__input{
vertical-align:middle;
}
::v-deep
.el-form-item.is-required:not(.is-no-asterisk)
> .el-form-item__label:before {
display: none;
}
.main-log-area{
::v-deep
.el-form-item.is-required:not(.is-no-asterisk)
> .el-form-item__label::after {
content: "*";
color: #f54a45;
margin-left: 2px;
}
::v-deep .el-form-item__content {
margin-left: 0 !important;
}
::v-deep .vue-treeselect__input {
vertical-align: middle;
}
}
.main-log-area {
position: relative;
padding: 24px;
}
.log-area{
height: calc(100vh - 240px);
}
.log-area {
height: calc(100vh - 240px);
}
</style>

View File

@ -10,7 +10,8 @@
type="primary"
icon="el-icon-plus"
@click="applyNew()"
>{{ $t('commons.create') }}</deBtn>
>{{ $t('commons.create') }}
</deBtn>
<span>&nbsp;</span>
</el-col>
<el-col
@ -33,10 +34,12 @@
:plain="!!cacheCondition.length"
icon="iconfont icon-icon-filter"
@click="filterShow"
>{{ $t("user.filter")
}}<template v-if="filterTexts.length">
({{ cacheCondition.length }})
</template>
>{{
$t('user.filter')
}}
<template v-if="filterTexts.length">
({{ cacheCondition.length }})
</template>
</deBtn>
</el-col>
</el-row>
@ -45,7 +48,7 @@
class="filter-texts"
>
<span class="sum">{{ paginationConfig.total }}</span>
<span class="title">{{ $t("user.result_one") }}</span>
<span class="title">{{ $t('user.result_one') }}</span>
<el-divider direction="vertical" />
<i
v-if="showScroll"
@ -74,7 +77,8 @@
class="clear-btn"
icon="el-icon-delete"
@click="clearFilter"
>{{ $t("user.clear_filter") }}</el-button>
>{{ $t('user.clear_filter') }}
</el-button>
</div>
<div
id="resize-for-filter"
@ -82,6 +86,7 @@
:class="[filterTexts.length ? 'table-container-filter' : '']"
>
<grid-table
:ref="'grid-table'"
v-loading="$store.getters.loadingMap[$store.getters.currentPath]"
:table-data="data"
:columns="[]"
@ -92,23 +97,37 @@
>
<el-table-column
show-overflow-tooltip
prop="opType"
:label="'数据源'"
prop="datasourceName"
:label="$t('app_template.datasource')"
>
<template #default="{ row }">
<span>{{ row.datasourceName }}</span>
<span
v-if="row.datasourceId && hasDataPermission('use',row.datasourcePrivileges)"
class="link-span"
@click="goToDatasource(row)"
>{{ row.datasourceName }}</span>
<span v-else>{{ row.datasourceName }}</span>
</template>
</el-table-column>
<el-table-column
show-overflow-tooltip
prop="datasetGroupName"
:label="'数据集分组'"
:label="$t('app_template.dataset_group')"
/>
<el-table-column
show-overflow-tooltip
prop="panelName"
:label="'仪表板'"
/>
:label="$t('app_template.panel')"
>
<template #default="{ row }">
<span
v-if="row.panelId && hasDataPermission('use',row.panelPrivileges)"
class="link-span"
@click="goPanel(row)"
>{{ row.panelName }}</span>
<span v-else>{{ row.panelName }}</span>
</template>
</el-table-column>
<el-table-column
show-overflow-tooltip
prop="appName"
@ -124,6 +143,31 @@
<span>{{ scope.row.applyTime | timestampFormatDate }}</span>
</template>
</el-table-column>
<el-table-column
v-if="optShow"
slot="__operation"
:label="$t('commons.operating')"
fixed="right"
:width="operateWidth"
>
<template slot-scope="scope">
<el-button
v-permission="['appLog:edit']"
class="de-text-btn mr2"
type="text"
@click="editApply(scope.row)"
>{{ $t('commons.edit') }}
</el-button>
<el-button
v-if="scope.row.id !== 1"
v-permission="['appLog:del']"
class="de-text-btn"
type="text"
@click="del(scope.row)"
>{{ $t('commons.delete') }}
</el-button>
</template>
</el-table-column>
</grid-table>
</div>
<keep-alive>
@ -132,6 +176,39 @@
@search="filterDraw"
/>
</keep-alive>
<keep-alive>
<app-template-apply
ref="templateEditApply"
@closeDraw="closeDraw"
/>
</keep-alive>
<!--导入templatedialog-->
<el-dialog
:title="$t('app_template.log_delete_tips')"
:visible.sync="deleteConfirmDialog"
:show-close="true"
width="420px"
>
<el-row>
<el-checkbox
v-model="deleteItemInfo.deleteResource"
:disabled="!(hasDataPermission('manage',deleteItemInfo.panelPrivileges) &&hasDataPermission('manage',deleteItemInfo.datasetPrivileges) &&hasDataPermission('manage',deleteItemInfo.datasourcePrivileges))"
/>
{{ $t('app_template.log_resource_delete_tips') }}
</el-row>
<span slot="footer">
<el-button
size="mini"
@click="closeDel"
>{{ $t('commons.cancel') }}</el-button>
<el-button
type="danger"
size="mini"
@click="confirmDel"
>{{ $t('commons.confirm') }}</el-button>
</span>
</el-dialog>
</el-row>
</template>
@ -144,10 +221,13 @@ import {
addOrder,
formatOrders
} from '@/utils/index'
import { logGrid } from '@/api/appTemplateMarket/log'
import { deleteLogAndResource, logGrid } from '@/api/appTemplateMarket/log'
import { findOneWithParent } from '@/api/panel/panel'
import AppTemplateApply from '@/views/panel/appTemplate/component/AppTemplateApply'
export default {
name: 'AppTemplateLog',
components: { GridTable, filterUser },
components: { AppTemplateApply, GridTable, filterUser },
mixins: [keyEnter],
props: {
appTemplateId: {
@ -162,6 +242,12 @@ export default {
},
data() {
return {
optShow: false,
deleteConfirmDialog: false,
deleteItemInfo: {
deleteResource: false
},
operateWidth: 168,
columns: [],
paginationConfig: {
currentPage: 1,
@ -194,6 +280,56 @@ export default {
this.resizeObserver()
},
methods: {
closeDel() {
this.deleteItemInfo = {
deleteResource: false
}
this.deleteConfirmDialog = false
},
confirmDel() {
deleteLogAndResource(this.deleteItemInfo).then(() => {
this.closeDel()
this.search()
})
},
closeDraw() {
this.search()
},
editApply(item) {
const param = {
datasourceType: item.datasourceType,
logId: item.id,
panelId: item.panelId,
panelGroupPid: item.panelGroupPid,
datasourceId: item.datasourceId,
datasetGroupPid: item.datasetGroupPid,
datasetGroupId: item.datasetGroupId,
datasetGroupName: item.datasetGroupName,
panelName: item.panelName,
datasourcePrivileges: item.datasourcePrivileges,
panelPrivileges: item.panelPrivileges,
datasetPrivileges: item.datasetPrivileges
}
this.$refs.templateEditApply.init(param)
},
goToDatasource(row) {
},
goPanel(row) {
findOneWithParent(row.panelId).then(rsp => {
this.$router.push({ name: 'panel', params: rsp.data })
})
},
edit() {
},
del(item) {
this.deleteItemInfo = {
...item,
deleteResource: false
}
this.deleteConfirmDialog = true
},
applyNew() {
this.$emit('applyNew')
},
@ -289,6 +425,11 @@ export default {
logGrid(currentPage, pageSize, param).then((response) => {
this.data = response.data.listObject
this.paginationConfig.total = response.data.itemCount
const _this = this
_this.optShow = false
this.$nextTick(() => {
_this.optShow = true
})
})
}
}
@ -302,4 +443,13 @@ export default {
.table-container-filter {
height: calc(100% - 110px);
}
.link-span {
color: #3370FF;
cursor: pointer;
&:hover {
text-decoration: underline;
}
}
</style>

View File

@ -6,7 +6,7 @@
<el-row class="component-wait-main">
<el-col
v-for="(config) in pcComponentData"
v-if="!config.mobileSelected"
v-if="!config.mobileSelected && config.canvasId === 'canvas-main'"
:id="'wait' + config.id"
:key="config.id"
:span="8"

View File

@ -174,10 +174,12 @@
v-if="!previewVisible&&!mobileLayoutStatus"
ref="canvasMainRef"
class="canvas_main_content"
:style="customCanvasStyle"
:canvas-style-data="canvasStyleData"
:component-data="mainCanvasComponentData"
:canvas-id="canvasId"
:canvas-pid="'0'"
@canvasScroll="canvasScroll"
>
<canvas-opt-bar slot="optBar" />
</de-canvas>
@ -466,6 +468,13 @@
</div>
</el-dialog>
<!--放在这个位置防止遮挡-->
<text-attr
v-if="showAttr && curComponent.canvasId === 'canvas-main'"
:canvas-id="canvasId"
:scroll-left="scrollLeft"
:scroll-top="scrollTop"
/>
</el-row>
</template>
@ -519,10 +528,12 @@ import { listenGlobalKeyDown } from '@/components/canvas/utils/shortcutKey'
import { adaptCurThemeCommonStyle } from '@/components/canvas/utils/style'
import eventBus from '@/components/canvas/utils/eventBus'
import DeCanvas from '@/components/canvas/DeCanvas'
import TextAttr from '@/components/canvas/components/TextAttr'
export default {
name: 'PanelEdit',
components: {
TextAttr,
DeCanvas,
Multiplexing,
ChartStyleBatchSet,
@ -767,6 +778,9 @@ export default {
},
mobileLayoutStatus() {
this.restore()
},
previewVisible(val) {
this.$store.commit('setPreviewVisible', val)
}
},
created() {
@ -1309,9 +1323,9 @@ export default {
//
bus.$emit('change_panel_right_draw', true)
},
canvasScroll(event) {
this.scrollLeft = event.target.scrollLeft
this.scrollTop = event.target.scrollTop
canvasScroll(scrollInfo) {
this.scrollLeft = scrollInfo.scrollLeft
this.scrollTop = scrollInfo.scrollTop
bus.$emit('onScroll')
},
destroyTimeMachine() {
@ -1501,6 +1515,7 @@ export default {
color: gray;
height: 30px;
width: 100%;
text-align: center;
}
.this_mobile_canvas_bottom {

View File

@ -0,0 +1,195 @@
<template>
<el-drawer
v-closePress
:title="$t('app_template.app_export')"
:visible.sync="applyDownloadDrawer"
custom-class="de-user-drawer"
size="600px"
direction="rtl"
>
<div class="app-export">
<el-form
ref="applyDownloadForm"
:model="form"
:rules="rule"
size="small"
class="de-form-item"
label-width="180px"
label-position="right"
>
<el-form-item
:label="$t('app_template.app_name')"
prop="appName"
>
<el-input
v-model="form.appName"
autocomplete="off"
:placeholder="$t('commons.input_name')"
/>
</el-form-item>
<el-form-item
:label="$t('app_template.app_version')"
prop="version"
>
<el-input
v-model="form.version"
autocomplete="off"
/>
</el-form-item>
<el-form-item
:label="$t('app_template.program_version')"
prop="required"
>
<el-input
v-model="form.required"
autocomplete="off"
/>
</el-form-item>
<el-form-item
:label="$t('app_template.creator')"
prop="creator"
>
<el-input
v-model="form.creator"
autocomplete="off"
/>
</el-form-item>
<el-form-item
:label="$t('commons.description')"
prop="description"
>
<deTextarea
v-model="form.description"
class="w100-textarea"
/>
</el-form-item>
</el-form>
</div>
<div
class="app-export-bottom"
>
<div
class="apply"
style="width: 100%"
>
<deBtn
secondary
@click="close"
>{{ $t('commons.cancel') }}
</deBtn>
<deBtn
type="primary"
@click="downloadApp"
>{{ $t('app_template.export') }}
</deBtn>
</div>
</div>
</el-drawer>
</template>
<script>
import i18n from '@/lang/index'
import deTextarea from '@/components/deCustomCm/deTextarea.vue'
import msgCfm from '@/components/msgCfm'
export default {
name: 'AppExportForm',
components: {
deTextarea
},
mixins: [msgCfm],
props: {},
data() {
return {
applyDownloadDrawer: false,
form: {
appName: null,
icon: null,
version: null,
creator: null,
required: '1.16.0',
description: null
},
rule: {
appName: [
{
required: true,
min: 2,
max: 25,
message: i18n.t('datasource.input_limit_2_25', [2, 25]),
trigger: 'blur'
}
],
creator: [
{
required: true,
min: 2,
max: 25,
message: i18n.t('datasource.input_limit_2_25', [2, 25]),
trigger: 'blur'
}
],
required: [
{
required: true,
min: 2,
max: 25,
message: i18n.t('datasource.input_limit_2_25', [2, 25]),
trigger: 'blur'
}
],
version: [
{
required: true,
min: 2,
max: 25,
message: i18n.t('datasource.input_limit_2_25', [2, 25]),
trigger: 'blur'
}
]
}
}
},
created() {
},
methods: {
init(params) {
this.applyDownloadDrawer = true
this.form = params
},
close() {
this.$emit('closeDraw')
this.applyDownloadDrawer = false
},
downloadApp() {
this.$refs.applyDownloadForm.validate(valid => {
if (valid) {
this.$emit('downLoadApp', this.form)
this.applyDownloadDrawer = false
} else {
return false
}
})
}
}
}
</script>
<style lang="scss" scoped>
.app-export{
width: 100%;
height: calc(100% - 56px);
}
.app-export-bottom{
width: 100%;
height: 56px;
text-align: right;
}
::v-deep .el-drawer__body{
padding-bottom: 0px!important;
}
</style>

View File

@ -8,16 +8,19 @@
<el-radio
v-model="inputType"
label="new"
> {{ $t('panel.custom') }}</el-radio>
> {{ $t('panel.custom') }}
</el-radio>
<el-radio
v-model="inputType"
label="new_outer_template"
>{{ $t('panel.import_template') }} </el-radio>
>{{ $t('panel.import_template') }}
</el-radio>
<el-radio
v-model="inputType"
label="new_inner_template"
@click.native="getTree"
>{{ $t('panel.copy_template') }} </el-radio>
>{{ $t('panel.copy_template') }}
</el-radio>
</el-col>
<el-col
v-if="inputType==='new_outer_template'"
@ -28,7 +31,8 @@
size="small"
type="primary"
@click="goFile"
>{{ $t('panel.upload_template') }}</el-button>
>{{ $t('panel.upload_template') }}
</el-button>
<input
id="input"
ref="files"
@ -77,13 +81,15 @@
<el-button
size="mini"
@click="cancel()"
>{{ $t('commons.cancel') }}</el-button>
>{{ $t('commons.cancel') }}
</el-button>
<el-button
type="primary"
size="mini"
:disabled="!saveStatus"
@click="save()"
>{{ $t('commons.confirm') }}</el-button>
>{{ $t('commons.confirm') }}
</el-button>
</el-row>
</el-row>
</template>
@ -234,7 +240,7 @@ export default {
showClose: true
})
this.loading = false
this.$emit('closeEditPanelDialog', response.data)
this.$emit('closeEditPanelDialog', { id: response.data, name: this.editPanel.panelInfo.name })
}).catch(() => {
this.loading = false
})
@ -265,34 +271,38 @@ export default {
<style scoped>
.my_table ::v-deep .el-table__row>td{
.my_table ::v-deep .el-table__row > td {
/* 去除表格线 */
border: none;
padding: 0 0;
}
.my_table ::v-deep .el-table th.is-leaf {
/* 去除上边框 */
border: none;
border: none;
}
.my_table ::v-deep .el-table::before{
.my_table ::v-deep .el-table::before {
/* 去除下边框 */
height: 0;
}
.root-class {
margin: 15px 0px 5px;
text-align: center;
}
.preview {
margin-top: 5px;
border:1px solid #E6E6E6;
height:250px !important;
overflow:hidden;
background-size: 100% 100% !important;
}
.preview-show {
border-left:1px solid #E6E6E6;
height:250px;
background-size: 100% 100% !important;
}
.root-class {
margin: 15px 0px 5px;
text-align: center;
}
.preview {
margin-top: 5px;
border: 1px solid #E6E6E6;
height: 250px !important;
overflow: hidden;
background-size: 100% 100% !important;
}
.preview-show {
border-left: 1px solid #E6E6E6;
height: 250px;
background-size: 100% 100% !important;
}
</style>

View File

@ -645,6 +645,9 @@ export default {
if (panelInfo) {
this.defaultTree()
this.tree()
if (this.editPanel.optType === 'rename' && panelInfo.id === this.$store.state.panel.panelInfo.id) {
this.$store.state.panel.panelInfo.name = panelInfo.name
}
//
if (
panelInfo &&

View File

@ -118,6 +118,10 @@
icon="el-icon-picture-outline"
@click.native="downloadAsImage"
>{{ $t('panel.export_to_img') }}</el-dropdown-item>
<el-dropdown-item
icon="el-icon-s-data"
@click.native="downLoadToAppPre"
>{{ $t('panel.export_to_app') }}</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</span>
@ -274,6 +278,48 @@
@closePreExport="closePreExport"
/>
</el-dialog>
<el-dialog
v-if="appExportShow"
:title="'应用导出'"
:visible.sync="appExportShow"
width="80%"
:top="'8vh'"
:destroy-on-close="true"
class="dialog-css2"
>
<span style="position: absolute;right: 70px;top:15px">
<svg-icon
icon-class="PDF"
class="ds-icon-pdf"
/>
<el-select
v-model="pdfTemplateSelectedIndex"
:placeholder="'切换PDF模板'"
@change="changePdfTemplate()"
>
<el-option
v-for="(item, index) in pdfTemplateAll"
:key="index"
:label="item.name"
:value="index"
/>
</el-select>
</span>
<PDFPreExport
:snapshot="snapshotInfo"
:panel-name="panelInfo.name"
:template-content="pdfTemplateContent"
@closePreExport="closePreExport"
/>
</el-dialog>
<keep-alive>
<app-export-form
ref="appExportForm"
@downLoadApp="downLoadApp"
/>
</keep-alive>
</el-row>
</template>
<script>
@ -283,6 +329,7 @@ import SaveToTemplate from '@/views/panel/list/SaveToTemplate'
import { mapState } from 'vuex'
import html2canvas from 'html2canvasde'
import FileSaver from 'file-saver'
import JSZip from 'jszip'
import { starStatus, saveEnshrine, deleteEnshrine } from '@/api/panel/enshrine'
import bus from '@/utils/bus'
import { queryAll } from '@/api/panel/pdfTemplate'
@ -292,10 +339,11 @@ import { proxyInitPanelData } from '@/api/panel/shareProxy'
import { dataURLToBlob, getNowCanvasComponentData } from '@/components/canvas/utils/utils'
import { findResourceAsBase64 } from '@/api/staticResource/staticResource'
import PanelDetailInfo from '@/views/panel/list/common/PanelDetailInfo'
import AppExportForm from '@/views/panel/list/AppExportForm'
export default {
name: 'PanelViewShow',
components: { PanelDetailInfo, Preview, SaveToTemplate, PDFPreExport, ShareHead },
components: { AppExportForm, PanelDetailInfo, Preview, SaveToTemplate, PDFPreExport, ShareHead },
props: {
activeTab: {
type: String,
@ -304,6 +352,7 @@ export default {
},
data() {
return {
canvasInfoTemp: 'preview-temp-canvas-main',
canvasId: 'canvas-main',
showMain: true,
pdfTemplateSelectedIndex: 0,
@ -315,6 +364,7 @@ export default {
hasStar: false,
fullscreen: false,
pdfExportShow: false,
appExportShow: false,
snapshotInfo: '',
showType: 0,
dataLoading: false,
@ -380,6 +430,9 @@ export default {
bus.$off('set-panel-share-user', this.setPanelShareUser)
},
methods: {
downLoadApp(appAttachInfo) {
this.downLoadToApp(appAttachInfo)
},
setPanelShowType(type) {
this.showType = type || 0
},
@ -405,7 +458,7 @@ export default {
saveToTemplate() {
this.dataLoading = true
setTimeout(() => {
html2canvas(document.getElementById('canvasInfoTemp')).then(canvas => {
html2canvas(document.getElementById(this.canvasInfoTemp)).then(canvas => {
this.templateSaveShow = true
this.dataLoading = false
const snapshot = canvas.toDataURL('image/jpeg', 0.1) // 0.2
@ -430,7 +483,7 @@ export default {
_this.dataLoading = true
try {
_this.findStaticSource(function(staticResource) {
html2canvas(document.getElementById('canvasInfoTemp')).then(canvas => {
html2canvas(document.getElementById(_this.canvasInfoTemp)).then(canvas => {
_this.dataLoading = false
const snapshot = canvas.toDataURL('image/jpeg', 0.1) // 0.1
if (snapshot !== '') {
@ -453,14 +506,15 @@ export default {
_this.dataLoading = false
}
},
saveAppFile(appAttachInfo) {
saveAppFile(appRelationInfo, appAttachInfo) {
const _this = this
_this.dataLoading = true
try {
const jsZip = new JSZip()
_this.findStaticSource(function(staticResource) {
html2canvas(document.getElementById('canvasInfoTemp')).then(canvas => {
html2canvas(document.getElementById(_this.canvasInfoTemp)).then(canvas => {
_this.dataLoading = false
const snapshot = canvas.toDataURL('image/jpeg', 0.1) // 0.1
const snapshot = canvas.toDataURL('image/jpeg', 1) // 0.1
if (snapshot !== '') {
const panelInfo = {
name: _this.$store.state.panel.panelInfo.name,
@ -468,11 +522,19 @@ export default {
snapshot: snapshot,
panelStyle: JSON.stringify(_this.canvasStyleData),
panelData: JSON.stringify(_this.componentData),
dynamicData: JSON.stringify(_this.panelViewDetailsInfo),
staticResource: JSON.stringify(staticResource || {})
}
appAttachInfo['panelInfo'] = JSON.stringify(panelInfo)
const blob = new Blob([JSON.stringify(appAttachInfo)], { type: '' })
FileSaver.saveAs(blob, _this.$store.state.panel.panelInfo.name + '-APP.DEAPP')
const blobTemplate = new Blob([JSON.stringify(panelInfo)], { type: '' })
const blobRelation = new Blob([JSON.stringify(appRelationInfo)], { type: '' })
const blobAppInfo = new Blob([JSON.stringify(appAttachInfo)], { type: '' })
jsZip.file('TEMPLATE.DET', blobTemplate, { binary: true })
jsZip.file('DATA_RELATION.DE', blobRelation, { binary: true })
jsZip.file('APP.json', blobAppInfo, { binary: true })
jsZip.generateAsync({ type: 'blob' }).then(content => {
//
FileSaver.saveAs(content, appAttachInfo.appName + '.zip') // file-saver
})
}
})
})
@ -481,11 +543,21 @@ export default {
_this.dataLoading = false
}
},
downLoadToApp() {
downLoadToAppPre() {
this.$refs.appExportForm.init({
appName: this.$store.state.panel.panelInfo.name,
icon: null,
version: '1.0',
creator: this.$store.getters.user.nickName,
required: '1.16.0',
description: null
})
},
downLoadToApp(appAttachInfo) {
this.dataLoading = true
export2AppCheck(this.$store.state.panel.panelInfo.id).then(rsp => {
if (rsp.data.checkStatus) {
this.saveAppFile(rsp.data)
this.saveAppFile(rsp.data, appAttachInfo)
} else {
this.dataLoading = false
this.$message({
@ -528,7 +600,7 @@ export default {
setTimeout(() => {
this.exporting = true
setTimeout(() => {
const canvasID = document.getElementById('canvasInfoTemp')
const canvasID = document.getElementById(this.canvasInfoTemp)
const a = document.createElement('a')
html2canvas(canvasID).then(canvas => {
this.exporting = false
@ -559,7 +631,7 @@ export default {
setTimeout(() => {
this.exporting = true
setTimeout(() => {
html2canvas(document.getElementById('canvasInfoTemp')).then(canvas => {
html2canvas(document.getElementById(this.canvasInfoTemp)).then(canvas => {
const snapshot = canvas.toDataURL('image/jpeg', 1) //
this.dataLoading = false
this.exporting = false
@ -573,7 +645,7 @@ export default {
},
refreshTemplateInfo() {
this.templateInfo = {}
html2canvas(document.getElementById('canvasInfoTemp')).then(canvas => {
html2canvas(document.getElementById(this.canvasInfoTemp)).then(canvas => {
const snapshot = canvas.toDataURL('image/jpeg', 0.1) // 0.2
if (snapshot !== '') {
this.templateInfo = {
@ -623,7 +695,9 @@ export default {
if (this.showType === 1 && this.shareUserId !== null) {
const param = { userId: this.shareUserId }
proxyInitPanelData(this.panelInfo.id, param, null)
} else { initPanelData(this.panelInfo.id, false) }
} else {
initPanelData(this.panelInfo.id, false)
}
},
changePublishState() {
if (this.panelInfo.status === 'publish') {
@ -642,72 +716,76 @@ export default {
</script>
<style>
.view-list {
height: 100%;
width: 20%;
min-width: 180px;
max-width: 220px;
border: 1px solid #E6E6E6;
border-left: 0 solid;
overflow-y: auto;
}
.view-list {
height: 100%;
width: 20%;
min-width: 180px;
max-width: 220px;
border: 1px solid #E6E6E6;
border-left: 0 solid;
overflow-y: auto;
}
.view-list-thumbnails-outline {
height: 100%;
overflow-y: auto;
}
.view-list-thumbnails-outline {
height: 100%;
overflow-y: auto;
}
.view-list-thumbnails {
width: 100%;
padding: 0px 15px 15px 0px;
}
.view-list-thumbnails {
width: 100%;
padding: 0px 15px 15px 0px;
}
.panel-design {
min-height: 400px;
height: 100%;
min-width: 500px;
overflow-y: hidden;
border-top: 1px solid #E6E6E6;
}
.panel-design {
min-height: 400px;
height: 100%;
min-width: 500px;
overflow-y: hidden;
border-top: 1px solid #E6E6E6;
}
.panel-design-head {
height: 40px;
background-color: var(--SiderBG, white);
padding: 0 10px;
line-height: 40px;
}
.panel-share-head {
height: auto !important;
}
.blackTheme .panel-design-head {
color: var(--TextActive);
}
.panel-design-head {
height: 40px;
background-color: var(--SiderBG, white);
padding: 0 10px;
line-height: 40px;
}
.panel-design-preview {
width: 100%;
height: calc(100% - 40px);
overflow-x: hidden;
overflow-y: auto;
/*padding: 5px;*/
}
.panel-share-head {
height: auto !important;
}
.custom-position {
flex: 1;
display: flex;
align-items: center;
justify-content: space-between;
font-size: 14px;
flex-flow: row nowrap;
color: #9ea6b2;
}
.blackTheme .panel-design-head {
color: var(--TextActive);
}
.dialog-css2 ::v-deep .el-dialog__title {
font-size: 14px!important;
}
.dialog-css2 ::v-deep .el-dialog__header {
padding: 20px 20px 0!important;
}
.dialog-css2 ::v-deep .el-dialog__body {
padding: 0px 20px!important;
}
.panel-design-preview {
width: 100%;
height: calc(100% - 40px);
overflow-x: hidden;
overflow-y: auto;
/*padding: 5px;*/
}
.custom-position {
flex: 1;
display: flex;
align-items: center;
justify-content: space-between;
font-size: 14px;
flex-flow: row nowrap;
color: #9ea6b2;
}
.dialog-css2 ::v-deep .el-dialog__title {
font-size: 14px !important;
}
.dialog-css2 ::v-deep .el-dialog__header {
padding: 20px 20px 0 !important;
}
.dialog-css2 ::v-deep .el-dialog__body {
padding: 0px 20px !important;
}
</style>

View File

@ -29,20 +29,6 @@
<script>
export default {
name: 'PanelDetailInfo',
props: {
type: {
type: String,
required: true
},
data: {
type: Object,
required: true
},
tabStatus: {
type: Boolean,
required: true
}
},
data() {
return {
tabActive: 'chart',

View File

@ -291,9 +291,10 @@
['oracle', 'sqlServer', 'pg', 'redshift', 'db2'].includes(form.type)
"
class="schema-label"
prop="configuration.schema"
>
<template slot="label">
{{ $t('datasource.schema') }}
<span class="name">{{ $t('datasource.schema') }}<i class="required" /></span>
<el-button
type="text"
icon="el-icon-plus"
@ -895,6 +896,13 @@ export default {
trigger: 'blur'
}
],
'configuration.schema': [
{
required: true,
message: i18n.t('datasource.please_input_connect_timeout'),
trigger: 'blur'
}
],
url: [
{
required: true,
@ -1617,4 +1625,20 @@ export default {
}
}
}
.schema-label {
::v-deep.el-form-item__label {
display: flex;
justify-content: space-between;
&::after {
display: none;
}
.name {
.required::after {
content: "*";
color: #f54a45;
margin-left: 2px;
}
}
}
}
</style>

View File

@ -1,9 +1,12 @@
<template>
<div
v-loading="formLoading"
class="de-ds-form"
:class="positionCheck('datasource')?'de-ds-form':'de-ds-form-app'"
>
<div class="de-ds-top">
<div
v-if="positionCheck('datasource')"
class="de-ds-top"
>
<span class="name">
<i
class="el-icon-arrow-left"
@ -17,7 +20,7 @@
!canEdit
? $t('datasource.show_info')
: formType == 'add'
? `${$t('commons.create') + typeMap }${ $t('commons.datasource')}`
? `${$t('commons.create') + typeMap}${$t('commons.datasource')}`
: $t('datasource.modify')
}}
</span>
@ -63,6 +66,73 @@
<div class="de-ds-cont">
<div class="de-ds-inner">
<div class="w600">
<el-form
v-if="positionCheck('appMarket')"
ref="attachParamsForm"
:model="attachForm"
:rules="attachRule"
class="de-form-item"
label-width="180px"
label-position="right"
>
<div
class="de-row-rules"
style="margin: 0 0 16px 0;"
>
<span>{{ $t('datasource.basic_info') }}</span>
</div>
<el-form-item
:label="$t('app_template.panel_position')"
prop="panelGroupPid"
>
<treeselect
v-model="attachForm.panelGroupPid"
:disabled="!(formType === 'add' ? true : hasDataPermission('manage', outerParams.panelPrivileges))"
:clearable="false"
:options="panelGroupList"
:normalizer="normalizer"
:placeholder="$t('chart.select_group')"
: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')"
/>
</el-form-item>
<el-form-item
:label="$t('app_template.panel_name')"
prop="panelName"
>
<el-input
v-model="attachForm.panelName"
:disabled="!(formType === 'add' ? true : hasDataPermission('manage', outerParams.panelPrivileges))"
/>
</el-form-item>
<el-form-item
:label="$t('app_template.dataset_group_position')"
prop="datasetGroupPid"
>
<treeselect
v-model="attachForm.datasetGroupPid"
:disabled="!(formType === 'add' ? true : hasDataPermission('manage', outerParams.datasetPrivileges))"
:clearable="false"
:options="datasetGroupList"
:normalizer="normalizer"
:placeholder="$t('chart.select_group')"
: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')"
/>
</el-form-item>
<el-form-item
:label="$t('app_template.dataset_group_name')"
prop="datasetGroupName"
>
<el-input
v-model="attachForm.datasetGroupName"
:disabled="!(formType === 'add' ? true : hasDataPermission('manage', outerParams.panelPrivileges))"
/>
</el-form-item>
</el-form>
<el-form
ref="dsForm"
:model="form"
@ -80,7 +150,9 @@
label-position="right"
>
<div class="de-row-rules">
<span>{{ $t('datasource.basic_info') }}</span>
<span>{{
positionCheck('appMarket') ? $t('app_template.datasource_info') : $t('datasource.basic_info')
}}</span>
</div>
<el-form-item
:label="$t('datasource.display_name')"
@ -92,6 +164,24 @@
:placeholder="$t('commons.input_name')"
/>
</el-form-item>
<el-form-item
:label="$t('datasource.type')"
prop="type"
>
<el-select
v-model="form.type"
:placeholder="$t('datasource.please_choose_type')"
style="width: 100%"
disabled
>
<el-option
v-for="item in dsTypes"
:key="item.type"
:label="item.name"
:value="item.type"
/>
</el-select>
</el-form-item>
<el-form-item
:label="$t('commons.description')"
prop="desc"
@ -146,6 +236,52 @@
</div>
</div>
</div>
<div
v-if="positionCheck('appMarket')"
class="de-ds-bottom"
>
<div
class="apply"
style="width: 100%"
>
<template v-if="canEdit">
<deBtn
secondary
@click="closeDraw"
>{{ $t('commons.cancel') }}
</deBtn>
<deBtn
v-if="
formType === 'add' ||
hasDataPermission('manage', params.privileges)
"
secondary
@click="validaDatasource"
>{{ $t('commons.validate') }}
</deBtn>
<deBtn
v-if="
formType === 'add' ||
hasDataPermission('manage', params.privileges)
"
type="primary"
@click="save"
>{{ $t('commons.save') }}
</deBtn>
</template>
<template v-else>
<deBtn
v-if="
formType === 'add'
? true
: hasDataPermission('manage', params.privileges)
"
@click="validaDatasource"
>{{ $t('commons.validate') }}
</deBtn>
</template>
</div>
</div>
</div>
</template>
@ -167,6 +303,10 @@ import PluginCom from '@/views/system/plugin/PluginCom'
import { listDatasourceType, listDatasource } from '@/api/system/datasource'
import deTextarea from '@/components/deCustomCm/deTextarea.vue'
import msgCfm from '@/components/msgCfm'
import { dsGroupTree } from '@/api/dataset/dataset'
import { appApply, appEdit, groupTree } from '@/api/panel/panel'
import { deepCopy } from '@/components/canvas/utils/utils'
export default {
name: 'DsForm',
components: {
@ -175,8 +315,51 @@ export default {
deTextarea
},
mixins: [msgCfm],
props: {
referencePosition: {
type: String,
default: 'datasource'
},
outerParams: {
type: Object,
request: false
}
},
data() {
return {
appMarketEdit: true,
attachRule: {
panelName: [
{
required: true,
min: 2,
max: 25,
message: i18n.t('datasource.input_limit_2_25', [2, 25]),
trigger: 'blur'
}
],
datasetGroupName: [
{
required: true,
min: 2,
max: 25,
message: i18n.t('datasource.input_limit_2_25', [2, 25]),
trigger: 'blur'
}
],
datasetGroupPid: [{ required: true, message: i18n.t('chart.select_group'), trigger: 'blur' }],
panelGroupPid: [{ required: true, message: i18n.t('chart.select_group'), trigger: 'blur' }]
},
panelGroupList: [],
datasetGroupList: [],
attachForm: {
appTemplateId: '',
panelGroupPid: null,
panelName: '',
datasetGroupPid: null,
datasetGroupId: null,
datasetGroupName: ''
},
disabled: false,
form: {
configuration: {
@ -402,8 +585,30 @@ export default {
async created() {
await this.datasourceTypes()
this.queryTreeData()
const { id, showModel, type, name } = this.$route.query
let { id, showModel, type, name } = this.$route.query
this.params = this.$route.query
if (this.positionCheck('appMarket')) {
id = this.outerParams.datasourceId
showModel = this.outerParams.showModel
type = this.outerParams.datasourceType
name = this.outerParams.name
this.attachForm.appTemplateId = this.outerParams.appTemplateId
this.attachForm.panelGroupPid = this.outerParams.panelGroupPid
this.attachForm.panelId = this.outerParams.panelId
this.attachForm.panelName = this.outerParams.panelName
this.attachForm.datasetGroupPid = this.outerParams.datasetGroupPid ? this.outerParams.datasetGroupPid : '0'
this.attachForm.datasetGroupId = this.outerParams.datasetGroupId
this.attachForm.datasetGroupName = this.outerParams.datasetGroupName
this.params = {
id: this.outerParams.datasourceId,
showModel: this.outerParams.showModel,
type: this.outerParams.datasourceType,
name: this.outerParams.name,
privileges: this.outerParams.datasourcePrivileges
}
this.getPanelGroupTree()
this.getDatasetGroupTree()
}
if (id) {
await this.getDatasourceDetail(id, showModel)
this.edit(this.params)
@ -420,14 +625,47 @@ export default {
this.disabled = Boolean(id) && showModel === 'show' && !this.canEdit
},
methods: {
normalizer(node) {
// children=null
if (node.children === null || node.children === 'null') {
delete node.children
}
},
getDatasetGroupTree() {
dsGroupTree({ nodeType: 'group', excludedId: this.attachForm.datasetGroupId }).then(res => {
this.datasetGroupList = [{
id: '0',
name: this.$t('dataset.dataset_group'),
label: this.$t('dataset.dataset_group'),
pid: '0',
privileges: 'grant,manage,use',
type: 'group',
children: res.data
}]
})
},
getPanelGroupTree() {
groupTree({ nodeType: 'folder' }).then(res => {
this.panelGroupList = res.data
if (!this.attachForm.panelGroupPid && this.panelGroupList && this.panelGroupList.length > 0) {
this.attachForm.panelGroupPid = this.panelGroupList[0].id
}
})
},
positionCheck(referencePosition) {
return this.referencePosition === referencePosition
},
datasourceTypes() {
return listDatasourceType().then((res) => {
this.dsTypes = res.data || []
})
},
getDatasourceDetail(id, showModel) {
this.formLoading = true
return getDatasourceDetail(id).then((res) => {
this.params = { ...res.data, showModel }
}).finally(() => {
this.formLoading = false
})
},
queryTreeData() {
@ -569,7 +807,7 @@ export default {
if (
configuration.host === this.form.configuration.host &&
configuration.dataBase ===
this.form.configuration.dataBase &&
this.form.configuration.dataBase &&
configuration.port === this.form.configuration.port
) {
repeat = true
@ -584,7 +822,7 @@ export default {
if (
configuration.host === this.form.configuration.host &&
configuration.dataBase ===
this.form.configuration.dataBase &&
this.form.configuration.dataBase &&
configuration.port === this.form.configuration.port &&
configuration.schema === this.form.configuration.schema
) {
@ -621,7 +859,7 @@ export default {
configuration.schema === this.form.configuration.schema &&
configuration.host === this.form.configuration.host &&
configuration.dataBase ===
this.form.configuration.dataBase &&
this.form.configuration.dataBase &&
configuration.port === this.form.configuration.port
) {
repeat = true
@ -631,7 +869,7 @@ export default {
if (
configuration.host === this.form.configuration.host &&
configuration.dataBase ===
this.form.configuration.dataBase &&
this.form.configuration.dataBase &&
configuration.port === this.form.configuration.port
) {
repeat = true
@ -656,11 +894,20 @@ export default {
if (!status) {
return
}
if (this.positionCheck('appMarket')) {
this.$refs.attachParamsForm.validate(valid => {
if (!valid) {
return false
}
}
)
}
this.$refs.dsForm.validate((valid) => {
if (!valid) {
return false
}
const method = this.formType === 'add' ? addDs : editDs
let method = this.formType === 'add' ? addDs : editDs
const form = JSON.parse(JSON.stringify(this.form))
if (form.type === 'api') {
if (this.form.apiConfiguration.length < 1) {
@ -674,17 +921,29 @@ export default {
} else {
form.configuration = JSON.stringify(form.configuration)
}
const isAppMarket = this.positionCheck('appMarket')
let appApplyForm
if (isAppMarket) {
if (typeof form.desc === 'object') {
form.desc = ''
}
appApplyForm = {
...this.attachForm,
datasourceList: [deepCopy(form)]
}
method = this.formType === 'add' ? appApply : appEdit
}
if (
this.formType === 'modify' &&
this.originConfiguration !== form.configuration
) {
if (repeat) {
if (repeat && !isAppMarket) {
$confirm(
i18n.t('datasource.repeat_datasource_msg') +
'[' +
repeatDsName.join(',') +
'], ' +
i18n.t('datasource.confirm_save'),
'[' +
repeatDsName.join(',') +
'], ' +
i18n.t('datasource.confirm_save'),
() => {
$confirm(i18n.t('datasource.edit_datasource_msg'), () => {
this.method(method, form)
@ -693,27 +952,40 @@ export default {
)
} else {
$confirm(i18n.t('datasource.edit_datasource_msg'), () => {
this.method(method, form)
isAppMarket ? this.appApplyMethod(method, appApplyForm) : this.method(method, form)
})
}
return
}
if (repeat) {
if (repeat && !isAppMarket) {
$confirm(
i18n.t('datasource.repeat_datasource_msg') +
'[' +
repeatDsName.join(',') +
'], ' +
i18n.t('datasource.confirm_save'),
'[' +
repeatDsName.join(',') +
'], ' +
i18n.t('datasource.confirm_save'),
() => {
this.method(method, form)
}
)
} else {
this.method(method, form)
isAppMarket ? this.appApplyMethod(method, appApplyForm) : this.method(method, form)
}
})
},
appApplyMethod(method, form) {
this.formLoading = true
method(form).then((res) => {
this.$success(i18n.t('commons.save_success'))
if (this.formType === 'add') {
this.$router.push({ name: 'panel', params: res.data })
} else {
this.closeDraw()
}
}).finally(() => {
this.formLoading = false
})
},
method(method, form) {
this.formLoading = true
method(form).then((res) => {
@ -767,6 +1039,14 @@ export default {
if (!status) {
return
}
if (this.positionCheck('appMarket')) {
this.$refs.attachParamsForm.validate(valid => {
if (!valid) {
return false
}
}
)
}
this.$refs.dsForm.validate((valid) => {
if (valid) {
const data = JSON.parse(JSON.stringify(this.form))
@ -785,7 +1065,7 @@ export default {
} else {
this.openMessageSuccess(
res.message.substring(0, 2500) + '......',
'danger'
'error'
)
}
}
@ -805,7 +1085,7 @@ export default {
} else {
this.openMessageSuccess(
res.message.substring(0, 2500) + '......',
'danger'
'error'
)
}
}
@ -844,6 +1124,10 @@ export default {
backToList() {
this.$router.push('/datasource/index')
},
closeDraw() {
this.$emit('closeDraw')
},
logOutTips() {
const options = {
title: 'role.tips',
@ -967,21 +1251,47 @@ export default {
}
})
},
handleClick(tab, event) {}
handleClick(tab, event) {
}
}
}
</script>
<style lang="scss" scoped>
.de-ds-form {
width: 100vw;
height: 100vh;
.de-ds-top {
.de-ds-form-app {
width: 100%;
height: 100%;
.de-ds-cont {
display: flex;
width: 100%;
height: calc(100% - 56px);
overflow-y: auto;
overflow-x: hidden;
padding: 12px 24px 24px 24px;
.de-ds-inner {
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
}
.w600 {
width: 600px;
height: 100%;
}
}
.de-ds-bottom {
display: flex;
text-align: right;
align-items: center;
justify-content: space-between;
height: 56px;
padding: 12px 24px;
box-shadow: 0px 2px 4px rgba(31, 35, 41, 0.08);
box-shadow: 2px 2px 4px rgba(31, 35, 41, 0.08);
.name {
font-family: 'PingFang SC';
font-style: normal;
@ -990,16 +1300,46 @@ export default {
line-height: 24px;
color: var(--deTextPrimary, #1f2329);
}
i {
cursor: pointer;
}
}
}
.de-ds-form {
width: 100vw;
height: 100vh;
.de-ds-top {
display: flex;
align-items: center;
justify-content: space-between;
height: 56px;
padding: 12px 24px;
box-shadow: 0px 2px 4px rgba(31, 35, 41, 0.08);
.name {
font-family: 'PingFang SC';
font-style: normal;
font-weight: 500;
font-size: 16px;
line-height: 24px;
color: var(--deTextPrimary, #1f2329);
}
i {
cursor: pointer;
}
}
.de-ds-cont {
display: flex;
width: 100%;
height: calc(100% - 56px);
padding: 12px 24px 24px 24px;
background: #f5f6f7;
.de-ds-inner {
width: 100%;
height: 100;
@ -1009,6 +1349,7 @@ export default {
justify-content: center;
overflow-y: auto;
}
.w600 {
width: 600px;
height: 100%;

View File

@ -4,7 +4,7 @@
<el-col :span="10">
<deBtn
type="primary"
icon="el-icon-circle-plus-outline"
icon="el-icon-plus"
@click="() => selectDataset()"
>{{ $t("dataset.add_task") }}</deBtn>
<deBtn

View File

@ -125,20 +125,19 @@
</div>
</div>
</div>
<div class="foot">
<el-button
class="btn normal"
<div class="de-foot">
<deBtn
secondary
@click="reset"
>{{
$t("commons.reset")
}}</el-button>
<el-button
}}</deBtn>
<deBtn
type="primary"
class="btn"
@click="search"
>{{
$t("commons.adv_search.search")
}}</el-button>
}}</deBtn>
</div>
</el-drawer>
</template>

View File

@ -177,6 +177,7 @@
style="width: 100%"
:disabled="formType !== 'add' && form.isAdmin"
multiple
filterable
:placeholder="$t('user.input_roles')"
@remove-tag="deleteTag"
@change="changeRole"