提交 0a75df58 authored 作者: wangjiahao's avatar wangjiahao

Merge remote-tracking branch 'origin/main' into main

# Conflicts: # frontend/src/main.js
...@@ -48,13 +48,11 @@ public class ShiroConfig { ...@@ -48,13 +48,11 @@ public class ShiroConfig {
// 添加自己的过滤器并且取名为jwt // 添加自己的过滤器并且取名为jwt
Map<String, Filter> filterMap = new LinkedHashMap<>(); Map<String, Filter> filterMap = new LinkedHashMap<>();
filterMap.put("f2cPerms", new F2CPermissionsFilter()); filterMap.put("f2cPerms", new F2CPermissionsFilter());
//filterMap.put("f2cRoles", new F2CRolesFilter());
filterMap.put("jwt", new JWTFilter()); filterMap.put("jwt", new JWTFilter());
/*filterMap.put("jwt", jwtFilter);*/
filterMap.put("logout", new F2CLogoutFilter()); filterMap.put("logout", new F2CLogoutFilter());
factoryBean.setSecurityManager(securityManager); factoryBean.setSecurityManager(securityManager);
factoryBean.setLoginUrl("/index.html"); factoryBean.setLoginUrl("/login");
factoryBean.setUnauthorizedUrl("/index.html"); factoryBean.setUnauthorizedUrl("/login");
factoryBean.setFilterChainDefinitionMap(shiroService.loadFilterChainDefinitionMap()); factoryBean.setFilterChainDefinitionMap(shiroService.loadFilterChainDefinitionMap());
factoryBean.setFilters(filterMap); factoryBean.setFilters(filterMap);
return factoryBean; return factoryBean;
......
...@@ -80,12 +80,14 @@ public class JWTFilter extends BasicHttpAuthenticationFilter { ...@@ -80,12 +80,14 @@ public class JWTFilter extends BasicHttpAuthenticationFilter {
}else { }else {
response401(request, response); response401(request, response);
} }
} }
} }
return false; return false;
} }
private String refreshToken(ServletRequest request, ServletResponse response) throws Exception{ private String refreshToken(ServletRequest request, ServletResponse response) throws Exception{
// 获取AccessToken(Shiro中getAuthzHeader方法已经实现) // 获取AccessToken(Shiro中getAuthzHeader方法已经实现)
String token = this.getAuthzHeader(request); String token = this.getAuthzHeader(request);
......
...@@ -34,17 +34,19 @@ public class ShiroServiceImpl implements ShiroService { ...@@ -34,17 +34,19 @@ public class ShiroServiceImpl implements ShiroService {
filterChainDefinitionMap.put("/fonts/**", ANON); filterChainDefinitionMap.put("/fonts/**", ANON);
filterChainDefinitionMap.put("/favicon.ico", ANON); filterChainDefinitionMap.put("/favicon.ico", ANON);
filterChainDefinitionMap.put("/", ANON); filterChainDefinitionMap.put("/", ANON);
filterChainDefinitionMap.put("/login", ANON);
filterChainDefinitionMap.put("/link/**", ANON);
filterChainDefinitionMap.put("/test/**", ANON);
filterChainDefinitionMap.put("/index.html", ANON); filterChainDefinitionMap.put("/index.html", ANON);
filterChainDefinitionMap.put("/link.html", ANON);
filterChainDefinitionMap.put("/api/auth/login", ANON); filterChainDefinitionMap.put("/api/auth/login", ANON);
filterChainDefinitionMap.put("/unauth", ANON); filterChainDefinitionMap.put("/unauth", ANON);
filterChainDefinitionMap.put("/display/**", ANON); filterChainDefinitionMap.put("/display/**", ANON);
filterChainDefinitionMap.put("/tokenExpired", ANON); filterChainDefinitionMap.put("/tokenExpired", ANON);
filterChainDefinitionMap.put("/downline", ANON); filterChainDefinitionMap.put("/downline", ANON);
filterChainDefinitionMap.put("/common-files/**", ANON); filterChainDefinitionMap.put("/common-files/**", ANON);
filterChainDefinitionMap.put("/api/auth/logout", "logout"); filterChainDefinitionMap.put("/api/auth/logout", "logout");
filterChainDefinitionMap.put("/**", "authc");
filterChainDefinitionMap.put("/**", "jwt"); filterChainDefinitionMap.put("/**", "jwt");
return filterChainDefinitionMap; return filterChainDefinitionMap;
} }
......
package io.dataease.base.domain;
import java.io.Serializable;
import lombok.Data;
@Data
public class PanelLink implements Serializable {
private String resourceId;
private Boolean enablePwd;
private String pwd;
private static final long serialVersionUID = 1L;
}
\ No newline at end of file
package io.dataease.base.mapper;
import io.dataease.base.domain.PanelLink;
import io.dataease.base.domain.PanelLinkExample;
import java.util.List;
import org.apache.ibatis.annotations.Param;
public interface PanelLinkMapper {
long countByExample(PanelLinkExample example);
int deleteByExample(PanelLinkExample example);
int deleteByPrimaryKey(String resourceId);
int insert(PanelLink record);
int insertSelective(PanelLink record);
List<PanelLink> selectByExample(PanelLinkExample example);
PanelLink selectByPrimaryKey(String resourceId);
int updateByExampleSelective(@Param("record") PanelLink record, @Param("example") PanelLinkExample example);
int updateByExample(@Param("record") PanelLink record, @Param("example") PanelLinkExample example);
int updateByPrimaryKeySelective(PanelLink record);
int updateByPrimaryKey(PanelLink record);
}
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="io.dataease.base.mapper.PanelLinkMapper">
<resultMap id="BaseResultMap" type="io.dataease.base.domain.PanelLink">
<id column="resource_id" jdbcType="VARCHAR" property="resourceId" />
<result column="enable_pwd" jdbcType="BIT" property="enablePwd" />
<result column="pwd" jdbcType="VARCHAR" property="pwd" />
</resultMap>
<sql id="Example_Where_Clause">
<where>
<foreach collection="oredCriteria" item="criteria" separator="or">
<if test="criteria.valid">
<trim prefix="(" prefixOverrides="and" suffix=")">
<foreach collection="criteria.criteria" item="criterion">
<choose>
<when test="criterion.noValue">
and ${criterion.condition}
</when>
<when test="criterion.singleValue">
and ${criterion.condition} #{criterion.value}
</when>
<when test="criterion.betweenValue">
and ${criterion.condition} #{criterion.value} and #{criterion.secondValue}
</when>
<when test="criterion.listValue">
and ${criterion.condition}
<foreach close=")" collection="criterion.value" item="listItem" open="(" separator=",">
#{listItem}
</foreach>
</when>
</choose>
</foreach>
</trim>
</if>
</foreach>
</where>
</sql>
<sql id="Update_By_Example_Where_Clause">
<where>
<foreach collection="example.oredCriteria" item="criteria" separator="or">
<if test="criteria.valid">
<trim prefix="(" prefixOverrides="and" suffix=")">
<foreach collection="criteria.criteria" item="criterion">
<choose>
<when test="criterion.noValue">
and ${criterion.condition}
</when>
<when test="criterion.singleValue">
and ${criterion.condition} #{criterion.value}
</when>
<when test="criterion.betweenValue">
and ${criterion.condition} #{criterion.value} and #{criterion.secondValue}
</when>
<when test="criterion.listValue">
and ${criterion.condition}
<foreach close=")" collection="criterion.value" item="listItem" open="(" separator=",">
#{listItem}
</foreach>
</when>
</choose>
</foreach>
</trim>
</if>
</foreach>
</where>
</sql>
<sql id="Base_Column_List">
resource_id, enable_pwd, pwd
</sql>
<select id="selectByExample" parameterType="io.dataease.base.domain.PanelLinkExample" resultMap="BaseResultMap">
select
<if test="distinct">
distinct
</if>
<include refid="Base_Column_List" />
from panel_link
<if test="_parameter != null">
<include refid="Example_Where_Clause" />
</if>
<if test="orderByClause != null">
order by ${orderByClause}
</if>
</select>
<select id="selectByPrimaryKey" parameterType="java.lang.String" resultMap="BaseResultMap">
select
<include refid="Base_Column_List" />
from panel_link
where resource_id = #{resourceId,jdbcType=VARCHAR}
</select>
<delete id="deleteByPrimaryKey" parameterType="java.lang.String">
delete from panel_link
where resource_id = #{resourceId,jdbcType=VARCHAR}
</delete>
<delete id="deleteByExample" parameterType="io.dataease.base.domain.PanelLinkExample">
delete from panel_link
<if test="_parameter != null">
<include refid="Example_Where_Clause" />
</if>
</delete>
<insert id="insert" parameterType="io.dataease.base.domain.PanelLink">
insert into panel_link (resource_id, enable_pwd, pwd
)
values (#{resourceId,jdbcType=VARCHAR}, #{enablePwd,jdbcType=BIT}, #{pwd,jdbcType=VARCHAR}
)
</insert>
<insert id="insertSelective" parameterType="io.dataease.base.domain.PanelLink">
insert into panel_link
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="resourceId != null">
resource_id,
</if>
<if test="enablePwd != null">
enable_pwd,
</if>
<if test="pwd != null">
pwd,
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="resourceId != null">
#{resourceId,jdbcType=VARCHAR},
</if>
<if test="enablePwd != null">
#{enablePwd,jdbcType=BIT},
</if>
<if test="pwd != null">
#{pwd,jdbcType=VARCHAR},
</if>
</trim>
</insert>
<select id="countByExample" parameterType="io.dataease.base.domain.PanelLinkExample" resultType="java.lang.Long">
select count(*) from panel_link
<if test="_parameter != null">
<include refid="Example_Where_Clause" />
</if>
</select>
<update id="updateByExampleSelective" parameterType="map">
update panel_link
<set>
<if test="record.resourceId != null">
resource_id = #{record.resourceId,jdbcType=VARCHAR},
</if>
<if test="record.enablePwd != null">
enable_pwd = #{record.enablePwd,jdbcType=BIT},
</if>
<if test="record.pwd != null">
pwd = #{record.pwd,jdbcType=VARCHAR},
</if>
</set>
<if test="_parameter != null">
<include refid="Update_By_Example_Where_Clause" />
</if>
</update>
<update id="updateByExample" parameterType="map">
update panel_link
set resource_id = #{record.resourceId,jdbcType=VARCHAR},
enable_pwd = #{record.enablePwd,jdbcType=BIT},
pwd = #{record.pwd,jdbcType=VARCHAR}
<if test="_parameter != null">
<include refid="Update_By_Example_Where_Clause" />
</if>
</update>
<update id="updateByPrimaryKeySelective" parameterType="io.dataease.base.domain.PanelLink">
update panel_link
<set>
<if test="enablePwd != null">
enable_pwd = #{enablePwd,jdbcType=BIT},
</if>
<if test="pwd != null">
pwd = #{pwd,jdbcType=VARCHAR},
</if>
</set>
where resource_id = #{resourceId,jdbcType=VARCHAR}
</update>
<update id="updateByPrimaryKey" parameterType="io.dataease.base.domain.PanelLink">
update panel_link
set enable_pwd = #{enablePwd,jdbcType=BIT},
pwd = #{pwd,jdbcType=VARCHAR}
where resource_id = #{resourceId,jdbcType=VARCHAR}
</update>
</mapper>
\ No newline at end of file
...@@ -2,6 +2,7 @@ package io.dataease.controller; ...@@ -2,6 +2,7 @@ package io.dataease.controller;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
@Controller @Controller
...@@ -15,11 +16,18 @@ public class IndexController { ...@@ -15,11 +16,18 @@ public class IndexController {
@GetMapping(value = "/login") @GetMapping(value = "/login")
public String login() { public String login() {
// if (SessionUtils.getUser() == null) { return "index.html";
if (null == null) { }
return "login.html";
} else { @GetMapping("/link")
return "redirect:/"; public String link() {
} return "link.html";
} }
@GetMapping("/test")
public String test() {
return "test.html";
}
} }
package io.dataease.controller.panel.api;
import io.dataease.controller.request.panel.link.LinkRequest;
import io.dataease.controller.request.panel.link.PasswordRequest;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.*;
@Api(tags = "仪表板:链接管理")
@RequestMapping("/api/link")
public interface LinkApi {
@ApiOperation("设置密码")
@PostMapping("/replacePwd")
void replacePwd(PasswordRequest request);
@ApiOperation("生成")
@PostMapping("/generate")
void generateLink(LinkRequest request);
}
package io.dataease.controller.panel.server;
import io.dataease.base.domain.PanelLink;
import io.dataease.commons.utils.ServletUtils;
import io.dataease.controller.panel.api.LinkApi;
import io.dataease.controller.request.panel.link.LinkRequest;
import io.dataease.controller.request.panel.link.PasswordRequest;
import io.dataease.service.panel.PanelLinkService;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@RestController
public class LinkServer implements LinkApi {
@Autowired
private PanelLinkService panelLinkService;
@Override
public void replacePwd(@RequestBody PasswordRequest request) {
panelLinkService.password(request);
}
@Override
public void generateLink(@RequestBody LinkRequest request) {
panelLinkService.generator(request);
}
}
package io.dataease.controller.request.panel.link;
import lombok.Data;
@Data
public class LinkRequest {
private String resourceId;
private String password;
private Boolean enablePwd;
private String uri;
}
package io.dataease.controller.request.panel.link;
import lombok.Data;
@Data
public class PasswordRequest {
private String resourceId;
private String password;
}
...@@ -2,6 +2,8 @@ package io.dataease.dto.chart; ...@@ -2,6 +2,8 @@ package io.dataease.dto.chart;
import lombok.Data; import lombok.Data;
import java.util.List;
/** /**
* @Author gin * @Author gin
* @Date 2021/3/11 1:18 下午 * @Date 2021/3/11 1:18 下午
...@@ -29,4 +31,6 @@ public class ChartViewFieldDTO { ...@@ -29,4 +31,6 @@ public class ChartViewFieldDTO {
private String summary; private String summary;
private String sort; private String sort;
private List<ChartViewFieldFilterDTO> filter;
} }
package io.dataease.dto.chart;
import lombok.Getter;
import lombok.Setter;
/**
* @Author gin
* @Date 2021/3/25 10:31 上午
*/
@Getter
@Setter
public class ChartViewFieldFilterDTO {
private String term;
private String value;
}
package io.dataease.dto.panel;
public class PanelLinkDto {
}
...@@ -2,9 +2,12 @@ package io.dataease.service.chart; ...@@ -2,9 +2,12 @@ package io.dataease.service.chart;
import io.dataease.base.domain.ChartGroup; import io.dataease.base.domain.ChartGroup;
import io.dataease.base.domain.ChartGroupExample; import io.dataease.base.domain.ChartGroupExample;
import io.dataease.base.domain.DatasetGroup;
import io.dataease.base.domain.DatasetTable;
import io.dataease.base.mapper.ChartGroupMapper; import io.dataease.base.mapper.ChartGroupMapper;
import io.dataease.commons.utils.BeanUtils; import io.dataease.commons.utils.BeanUtils;
import io.dataease.controller.request.chart.ChartGroupRequest; import io.dataease.controller.request.chart.ChartGroupRequest;
import io.dataease.controller.request.dataset.DataSetTableRequest;
import io.dataease.dto.chart.ChartGroupDTO; import io.dataease.dto.chart.ChartGroupDTO;
import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
...@@ -21,6 +24,8 @@ import java.util.stream.Collectors; ...@@ -21,6 +24,8 @@ import java.util.stream.Collectors;
public class ChartGroupService { public class ChartGroupService {
@Resource @Resource
private ChartGroupMapper chartGroupMapper; private ChartGroupMapper chartGroupMapper;
@Resource
private ChartViewService chartViewService;
public ChartGroupDTO save(ChartGroup chartGroup) { public ChartGroupDTO save(ChartGroup chartGroup) {
if (StringUtils.isEmpty(chartGroup.getId())) { if (StringUtils.isEmpty(chartGroup.getId())) {
...@@ -28,7 +33,7 @@ public class ChartGroupService { ...@@ -28,7 +33,7 @@ public class ChartGroupService {
chartGroup.setCreateTime(System.currentTimeMillis()); chartGroup.setCreateTime(System.currentTimeMillis());
chartGroupMapper.insert(chartGroup); chartGroupMapper.insert(chartGroup);
} else { } else {
chartGroupMapper.updateByPrimaryKey(chartGroup); chartGroupMapper.updateByPrimaryKeySelective(chartGroup);
} }
ChartGroupDTO ChartGroupDTO = new ChartGroupDTO(); ChartGroupDTO ChartGroupDTO = new ChartGroupDTO();
BeanUtils.copyBean(ChartGroupDTO, chartGroup); BeanUtils.copyBean(ChartGroupDTO, chartGroup);
...@@ -45,6 +50,14 @@ public class ChartGroupService { ...@@ -45,6 +50,14 @@ public class ChartGroupService {
ChartGroupExample ChartGroupExample = new ChartGroupExample(); ChartGroupExample ChartGroupExample = new ChartGroupExample();
ChartGroupExample.createCriteria().andIdIn(ids); ChartGroupExample.createCriteria().andIdIn(ids);
chartGroupMapper.deleteByExample(ChartGroupExample); chartGroupMapper.deleteByExample(ChartGroupExample);
// 删除所有chart
deleteChart(ids);
}
public void deleteChart(List<String> sceneIds) {
for (String sceneId : sceneIds) {
chartViewService.deleteBySceneId(sceneId);
}
} }
public ChartGroup getScene(String id) { public ChartGroup getScene(String id) {
......
...@@ -45,7 +45,7 @@ public class ChartViewService { ...@@ -45,7 +45,7 @@ public class ChartViewService {
public ChartViewWithBLOBs save(ChartViewWithBLOBs chartView) { public ChartViewWithBLOBs save(ChartViewWithBLOBs chartView) {
long timestamp = System.currentTimeMillis(); long timestamp = System.currentTimeMillis();
chartView.setUpdateTime(timestamp); chartView.setUpdateTime(timestamp);
int i = chartViewMapper.updateByPrimaryKeyWithBLOBs(chartView); int i = chartViewMapper.updateByPrimaryKeySelective(chartView);
if (i == 0) { if (i == 0) {
chartView.setId(UUID.randomUUID().toString()); chartView.setId(UUID.randomUUID().toString());
chartView.setCreateTime(timestamp); chartView.setCreateTime(timestamp);
...@@ -75,6 +75,12 @@ public class ChartViewService { ...@@ -75,6 +75,12 @@ public class ChartViewService {
chartViewMapper.deleteByPrimaryKey(id); chartViewMapper.deleteByPrimaryKey(id);
} }
public void deleteBySceneId(String sceneId) {
ChartViewExample chartViewExample = new ChartViewExample();
chartViewExample.createCriteria().andSceneIdEqualTo(sceneId);
chartViewMapper.deleteByExample(chartViewExample);
}
public ChartViewDTO getData(String id) throws Exception { public ChartViewDTO getData(String id) throws Exception {
ChartViewWithBLOBs view = chartViewMapper.selectByPrimaryKey(id); ChartViewWithBLOBs view = chartViewMapper.selectByPrimaryKey(id);
List<ChartViewFieldDTO> xAxis = new Gson().fromJson(view.getXAxis(), new TypeToken<List<ChartViewFieldDTO>>() { List<ChartViewFieldDTO> xAxis = new Gson().fromJson(view.getXAxis(), new TypeToken<List<ChartViewFieldDTO>>() {
...@@ -174,6 +180,41 @@ public class ChartViewService { ...@@ -174,6 +180,41 @@ public class ChartViewService {
sql = sql.substring(0, sql.length() - 1); sql = sql.substring(0, sql.length() - 1);
} }
// 如果是对结果字段过滤,则再包裹一层sql // 如果是对结果字段过滤,则再包裹一层sql
return sql; String[] resultFilter = yAxis.stream().filter(y -> CollectionUtils.isNotEmpty(y.getFilter()) && y.getFilter().size() > 0)
.map(y -> {
String[] s = y.getFilter().stream().map(f -> "AND _" + y.getSummary() + "_" + y.getOriginName() + transMysqlFilterTerm(f.getTerm()) + f.getValue()).toArray(String[]::new);
return StringUtils.join(s, " ");
}).toArray(String[]::new);
if (resultFilter.length == 0) {
return sql;
} else {
String filterSql = MessageFormat.format("SELECT * FROM {0} WHERE 1=1 {1}",
"(" + sql + ") AS tmp",
StringUtils.join(resultFilter, " "));
return filterSql;
}
}
public String transMysqlFilterTerm(String term) {
switch (term) {
case "eq":
return " = ";
case "not_eq":
return " <> ";
case "lt":
return " < ";
case "le":
return " <= ";
case "gt":
return " > ";
case "ge":
return " >= ";
case "null":
return " IS NULL ";
case "not_null":
return " IS NOT NULL ";
default:
return "";
}
} }
} }
...@@ -35,7 +35,7 @@ public class DataSetGroupService { ...@@ -35,7 +35,7 @@ public class DataSetGroupService {
datasetGroup.setCreateTime(System.currentTimeMillis()); datasetGroup.setCreateTime(System.currentTimeMillis());
datasetGroupMapper.insert(datasetGroup); datasetGroupMapper.insert(datasetGroup);
} else { } else {
datasetGroupMapper.updateByPrimaryKey(datasetGroup); datasetGroupMapper.updateByPrimaryKeySelective(datasetGroup);
} }
DataSetGroupDTO dataSetGroupDTO = new DataSetGroupDTO(); DataSetGroupDTO dataSetGroupDTO = new DataSetGroupDTO();
BeanUtils.copyBean(dataSetGroupDTO, datasetGroup); BeanUtils.copyBean(dataSetGroupDTO, datasetGroup);
...@@ -52,10 +52,8 @@ public class DataSetGroupService { ...@@ -52,10 +52,8 @@ public class DataSetGroupService {
DatasetGroupExample datasetGroupExample = new DatasetGroupExample(); DatasetGroupExample datasetGroupExample = new DatasetGroupExample();
datasetGroupExample.createCriteria().andIdIn(ids); datasetGroupExample.createCriteria().andIdIn(ids);
datasetGroupMapper.deleteByExample(datasetGroupExample); datasetGroupMapper.deleteByExample(datasetGroupExample);
// 获取type为scene的id,删除场景下的表和字段 // 删除场景下的表和字段
deleteTableAndField(tree.stream().filter(ele -> { deleteTableAndField(ids);
return StringUtils.equalsIgnoreCase(ele.getType(), "scene");
}).map(DatasetGroup::getId).collect(Collectors.toList()));
} }
public DatasetGroup getScene(String id) { public DatasetGroup getScene(String id) {
......
...@@ -31,7 +31,7 @@ public class DataSetTableFieldsService { ...@@ -31,7 +31,7 @@ public class DataSetTableFieldsService {
datasetTableField.setId(UUID.randomUUID().toString()); datasetTableField.setId(UUID.randomUUID().toString());
datasetTableFieldMapper.insert(datasetTableField); datasetTableFieldMapper.insert(datasetTableField);
} else { } else {
datasetTableFieldMapper.updateByPrimaryKey(datasetTableField); datasetTableFieldMapper.updateByPrimaryKeySelective(datasetTableField);
} }
return datasetTableField; return datasetTableField;
} }
......
...@@ -62,7 +62,7 @@ public class DataSetTableService { ...@@ -62,7 +62,7 @@ public class DataSetTableService {
saveTableField(datasetTable); saveTableField(datasetTable);
} }
} else { } else {
datasetTableMapper.updateByPrimaryKeyWithBLOBs(datasetTable); datasetTableMapper.updateByPrimaryKeySelective(datasetTable);
} }
return datasetTable; return datasetTable;
} }
......
...@@ -29,7 +29,7 @@ public class DataSetTableTaskLogService { ...@@ -29,7 +29,7 @@ public class DataSetTableTaskLogService {
datasetTableTaskLog.setCreateTime(System.currentTimeMillis()); datasetTableTaskLog.setCreateTime(System.currentTimeMillis());
datasetTableTaskLogMapper.insert(datasetTableTaskLog); datasetTableTaskLogMapper.insert(datasetTableTaskLog);
} else { } else {
datasetTableTaskLogMapper.updateByPrimaryKey(datasetTableTaskLog); datasetTableTaskLogMapper.updateByPrimaryKeySelective(datasetTableTaskLog);
} }
return datasetTableTaskLog; return datasetTableTaskLog;
} }
......
...@@ -39,7 +39,7 @@ public class DataSetTableTaskService { ...@@ -39,7 +39,7 @@ public class DataSetTableTaskService {
datasetTableTask.setCreateTime(System.currentTimeMillis()); datasetTableTask.setCreateTime(System.currentTimeMillis());
datasetTableTaskMapper.insert(datasetTableTask); datasetTableTaskMapper.insert(datasetTableTask);
} else { } else {
datasetTableTaskMapper.updateByPrimaryKey(datasetTableTask); datasetTableTaskMapper.updateByPrimaryKeySelective(datasetTableTask);
} }
scheduleService.addSchedule(datasetTableTask); scheduleService.addSchedule(datasetTableTask);
return datasetTableTask; return datasetTableTask;
......
package io.dataease.service.panel;
import io.dataease.base.domain.PanelLink;
import io.dataease.base.mapper.PanelLinkMapper;
import io.dataease.controller.request.panel.link.LinkRequest;
import io.dataease.controller.request.panel.link.PasswordRequest;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
@Service
public class PanelLinkService {
@Resource
private PanelLinkMapper mapper;
public void generator(LinkRequest request){
String resourceId = request.getResourceId();
PanelLink panelLink = mapper.selectByPrimaryKey(resourceId);
PanelLink po = new PanelLink();
po.setResourceId(resourceId);
po.setEnablePwd(request.getEnablePwd());
po.setPwd(request.getPassword());
if (ObjectUtils.isEmpty(panelLink)){
mapper.insert(po);
}else{
mapper.updateByPrimaryKey(po);
}
}
public void password(PasswordRequest request){
PanelLink po = new PanelLink();
po.setResourceId(request.getResourceId());
po.setPwd(request.getPassword());
mapper.updateByPrimaryKeySelective(po);
}
public PanelLink findOne(String resourceId){
PanelLink panelLink = mapper.selectByPrimaryKey(resourceId);
return panelLink;
}
}
...@@ -60,6 +60,8 @@ logging.level.org.springframework.boot.web=trace ...@@ -60,6 +60,8 @@ logging.level.org.springframework.boot.web=trace
spring.mvc.log-request-details=true spring.mvc.log-request-details=true
pagehelper.PageRowBounds=true pagehelper.PageRowBounds=true
front-url=http://localhost:9528
...@@ -134,3 +134,12 @@ INSERT INTO `file_metadata` VALUES ('VIEW_DEFAULT_IMAGE', 'view-demo.png', 'PNG' ...@@ -134,3 +134,12 @@ INSERT INTO `file_metadata` VALUES ('VIEW_DEFAULT_IMAGE', 'view-demo.png', 'PNG'
COMMIT; COMMIT;
SET FOREIGN_KEY_CHECKS = 1; SET FOREIGN_KEY_CHECKS = 1;
DROP TABLE IF EXISTS `panel_link`;
CREATE TABLE `panel_link` (
`resource_id` varchar(50) NOT NULL COMMENT '资源ID',
`enable_pwd` tinyint(1) default 0 COMMENT '启用密码',
`pwd` varchar(255) DEFAULT NULL COMMENT '密码',
PRIMARY KEY (`resource_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='仪表板链接';
...@@ -19,7 +19,8 @@ if (process.env.npm_config_preview || rawArgv.includes('--preview')) { ...@@ -19,7 +19,8 @@ if (process.env.npm_config_preview || rawArgv.includes('--preview')) {
app.use( app.use(
publicPath, publicPath,
serveStatic('./dist', { serveStatic('./dist', {
index: ['index.html', '/'] index: ['index.html', '/'],
link: ['link.html']
}) })
) )
......
...@@ -37,6 +37,7 @@ ...@@ -37,6 +37,7 @@
"vue-uuid": "2.0.2", "vue-uuid": "2.0.2",
"vuedraggable": "^2.24.3", "vuedraggable": "^2.24.3",
"vuex": "3.1.0", "vuex": "3.1.0",
"vue-clipboard2": "0.3.1",
"webpack": "^4.46.0" "webpack": "^4.46.0"
}, },
"devDependencies": { "devDependencies": {
......
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="shortcut icon" href="<%= BASE_URL %>favicon.ico">
<title>DataEase</title>
</head>
<body>
<div id="link"></div>
</body>
</html>
import request from '@/utils/request'
export function validate(param) {
return request({
url: 'api/link/validate',
method: 'post',
loading: true,
param
})
}
export function generate(param) {
return request({
url: 'api/link/generate',
method: 'post',
param
})
}
...@@ -21,7 +21,7 @@ export default { ...@@ -21,7 +21,7 @@ export default {
props: { props: {
width: { width: {
type: String, type: String,
default: '300px' default: '260px'
}, },
enableAsideHidden: { enableAsideHidden: {
type: Boolean, type: Boolean,
......
...@@ -681,7 +681,19 @@ export default { ...@@ -681,7 +681,19 @@ export default {
filter: '过滤', filter: '过滤',
none: '无', none: '无',
background: '背景', background: '背景',
alpha: '透明度' alpha: '透明度',
add_filter: '添加过滤',
no_limit: '无限制',
filter_eq: '等于',
filter_not_eq: '不等于',
filter_lt: '小于',
filter_le: '小于等于',
filter_gt: '大于',
filter_ge: '大于等于',
filter_null: '为空',
filter_not_null: '不为空',
filter_include: '包含',
filter_not_include: '不包含'
}, },
dataset: { dataset: {
datalist: '数据集', datalist: '数据集',
...@@ -756,7 +768,8 @@ export default { ...@@ -756,7 +768,8 @@ export default {
incremental_delete: '增量删除', incremental_delete: '增量删除',
last_update_time: '上次更新时间', last_update_time: '上次更新时间',
current_update_time: '当前更新时间', current_update_time: '当前更新时间',
param: '参数' param: '参数',
edit_sql: '编辑SQL'
}, },
datasource: { datasource: {
create: '新建数据连接', create: '新建数据连接',
......
<template>
<div id="link"><router-view />
</div>
</template>
<script>
export default {
data() {
return {
}
}
}
</script>
<style scoped>
</style>
import Vue from 'vue'
import Router from 'vue-router'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/',
name: 'home',
component: () =>
import('../views/link/index.vue'),
meta: {
title: '首页'
}
}
]
})
import Vue from 'vue'
import Link from './Link.vue'
import router from './link-router'
Vue.config.productionTip = false
new Vue({
router,
render: h => h(Link)
}).$mount('#link')
...@@ -162,3 +162,14 @@ export function formatCondition(param) { ...@@ -162,3 +162,14 @@ export function formatCondition(param) {
} }
return result return result
} }
export function getQueryVariable(variable) {
const query = window.location.search.substring(1)
const vars = query.split('&')
for (var i = 0; i < vars.length; i++) {
const pair = vars[i].split('=')
if (pair[0] === variable) { return pair[1] }
}
return (false)
}
...@@ -9,9 +9,9 @@ ...@@ -9,9 +9,9 @@
<el-col> <el-col>
<el-form ref="colorForm" :model="colorForm" label-width="80px" size="mini"> <el-form ref="colorForm" :model="colorForm" label-width="80px" size="mini">
<el-form-item :label="$t('chart.color')" class="form-item"> <el-form-item :label="$t('chart.color')" class="form-item">
<colorPicker v-model="colorForm.color" style="margin-top: 6px;cursor: pointer;z-index: 999;border: solid 1px black" @change="changeBackgroundStyle" /> <colorPicker v-model="colorForm.color" style="margin-top: 6px;cursor: pointer;z-index: 1004;border: solid 1px black" @change="changeBackgroundStyle" />
</el-form-item> </el-form-item>
<el-form-item :label="$t('chart.alpha')" class="form-item"> <el-form-item :label="$t('chart.not_alpha')" class="form-item form-item-slider">
<el-slider v-model="colorForm.alpha" show-input :show-input-controls="false" input-size="mini" @change="changeBackgroundStyle" /> <el-slider v-model="colorForm.alpha" show-input :show-input-controls="false" input-size="mini" @change="changeBackgroundStyle" />
</el-form-item> </el-form-item>
</el-form> </el-form>
......
...@@ -15,18 +15,6 @@ ...@@ -15,18 +15,6 @@
</el-dropdown-menu> </el-dropdown-menu>
</span> </span>
</el-dropdown> </el-dropdown>
<el-dialog :title="$t('chart.show_name_set')" :visible="renameItem" :show-close="false" width="30%">
<el-form ref="itemForm" :model="itemForm" :rules="itemFormRules">
<el-form-item :label="$t('commons.name')" prop="name">
<el-input v-model="itemForm.name" size="mini" />
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button size="mini" @click="closeRename()">{{ $t('chart.cancel') }}</el-button>
<el-button type="primary" size="mini" @click="saveRename(itemForm)">{{ $t('chart.confirm') }}</el-button>
</div>
</el-dialog>
</span> </span>
</template> </template>
...@@ -45,15 +33,6 @@ export default { ...@@ -45,15 +33,6 @@ export default {
}, },
data() { data() {
return { return {
renameItem: false,
itemForm: {
name: ''
},
itemFormRules: {
name: [
{ required: true, message: this.$t('commons.input_content'), trigger: 'change' }
]
}
} }
}, },
mounted() { mounted() {
...@@ -80,22 +59,9 @@ export default { ...@@ -80,22 +59,9 @@ export default {
} }
}, },
showRename() { showRename() {
this.itemForm.name = this.item.name this.item.index = this.index
this.renameItem = true this.item.renameType = 'dimension'
}, this.$emit('onNameEdit', this.item)
closeRename() {
this.renameItem = false
this.resetRename()
},
saveRename(param) {
this.item.name = param.name
this.$emit('onDimensionItemChange', this.item)
this.closeRename()
},
resetRename() {
this.itemForm = {
name: ''
}
}, },
removeItem() { removeItem() {
this.item.index = this.index this.item.index = this.index
......
...@@ -59,7 +59,7 @@ ...@@ -59,7 +59,7 @@
</el-dropdown-menu> </el-dropdown-menu>
</el-dropdown> </el-dropdown>
</el-dropdown-item> </el-dropdown-item>
<el-dropdown-item icon="el-icon-files"> <el-dropdown-item icon="el-icon-files" :command="beforeClickItem('filter')">
<span>{{ $t('chart.filter') }}...</span> <span>{{ $t('chart.filter') }}...</span>
</el-dropdown-item> </el-dropdown-item>
<el-dropdown-item icon="el-icon-edit-outline" divided :command="beforeClickItem('rename')"> <el-dropdown-item icon="el-icon-edit-outline" divided :command="beforeClickItem('rename')">
...@@ -71,18 +71,6 @@ ...@@ -71,18 +71,6 @@
</el-dropdown-menu> </el-dropdown-menu>
</span> </span>
</el-dropdown> </el-dropdown>
<el-dialog :title="$t('chart.show_name_set')" :visible="renameItem" :show-close="false" width="30%">
<el-form ref="itemForm" :model="itemForm" :rules="itemFormRules">
<el-form-item :label="$t('commons.name')" prop="name">
<el-input v-model="itemForm.name" size="mini" />
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button size="mini" @click="closeRename()">{{ $t('chart.cancel') }}</el-button>
<el-button type="primary" size="mini" @click="saveRename(itemForm)">{{ $t('chart.confirm') }}</el-button>
</div>
</el-dialog>
</span> </span>
</template> </template>
...@@ -101,15 +89,6 @@ export default { ...@@ -101,15 +89,6 @@ export default {
}, },
data() { data() {
return { return {
renameItem: false,
itemForm: {
name: ''
},
itemFormRules: {
name: [
{ required: true, message: this.$t('commons.input_content'), trigger: 'change' }
]
}
} }
}, },
mounted() { mounted() {
...@@ -127,6 +106,9 @@ export default { ...@@ -127,6 +106,9 @@ export default {
case 'remove': case 'remove':
this.removeItem() this.removeItem()
break break
case 'filter':
this.editFilter()
break
default: default:
break break
} }
...@@ -167,28 +149,18 @@ export default { ...@@ -167,28 +149,18 @@ export default {
type: type type: type
} }
}, },
showRename() { showRename() {
this.itemForm.name = this.item.name this.item.index = this.index
this.renameItem = true this.item.renameType = 'quota'
}, this.$emit('onNameEdit', this.item)
closeRename() {
this.renameItem = false
this.resetRename()
},
saveRename(param) {
this.item.name = param.name
this.$emit('onQuotaItemChange', this.item)
this.closeRename()
},
resetRename() {
this.itemForm = {
name: ''
}
}, },
removeItem() { removeItem() {
this.item.index = this.index this.item.index = this.index
this.$emit('onQuotaItemRemove', this.item) this.$emit('onQuotaItemRemove', this.item)
},
editFilter() {
this.item.index = this.index
this.$emit('editItemFilter', this.item)
} }
} }
} }
......
<template>
<el-col>
<el-button icon="el-icon-plus" circle size="mini" style="margin-bottom: 10px;" @click="addFilter" />
<el-row v-for="(f,index) in item.filter" :key="index" class="filter-item">
<el-col :span="4">
<span>{{ item.name }} ({{ $t('chart.'+item.summary) }})</span>
</el-col>
<el-col :span="8">
<el-select v-model="f.term" size="mini">
<el-option-group
v-for="(group,idx) in options"
:key="idx"
:label="group.label"
>
<el-option
v-for="opt in group.options"
:key="opt.value"
:label="opt.label"
:value="opt.value"
/>
</el-option-group>
</el-select>
</el-col>
<el-col :span="6">
<el-input v-model="f.value" class="value-item" :placeholder="$t('chart.no_limit')" size="mini" clearable />
</el-col>
<el-col :span="6">
<el-button type="text" icon="el-icon-delete" circle style="float: right" @click="removeFilter(index)" />
</el-col>
</el-row>
</el-col>
</template>
<script>
export default {
name: 'QuotaFilterEditor',
props: {
item: {
type: Object,
required: true
}
},
data() {
return {
options: [{
label: '',
options: [{
value: 'eq',
label: this.$t('chart.filter_eq')
}, {
value: 'not_eq',
label: this.$t('chart.filter_not_eq')
}]
}, {
label: '',
options: [{
value: 'lt',
label: this.$t('chart.filter_lt')
}, {
value: 'gt',
label: this.$t('chart.filter_gt')
}]
},
{
label: '',
options: [{
value: 'le',
label: this.$t('chart.filter_le')
}, {
value: 'ge',
label: this.$t('chart.filter_ge')
}]
},
{
label: '',
options: [{
value: 'null',
label: this.$t('chart.filter_null')
}, {
value: 'not_null',
label: this.$t('chart.filter_not_null')
}]
}]
}
},
mounted() {
},
methods: {
addFilter() {
this.item.filter.push({
term: 'eq',
value: ''
})
},
removeFilter(index) {
this.item.filter.splice(index, 1)
}
}
}
</script>
<style scoped lang="scss">
.filter-item{
width: 100%;
border-radius: 4px;
border: 1px solid #DCDFE6;
padding: 4px 14px;
margin-bottom: 10px;
display: flex;
justify-content: left;
align-items: center;
}
.form-item>>>.el-form-item__label{
font-size: 12px;
}
span{
font-size: 12px;
}
.value-item>>>.el-input{
position: relative;
display: inline-block;
width: 80px!important;
}
.el-select-dropdown__item{
padding: 0 20px;
font-size: 12px;
}
</style>
...@@ -528,7 +528,7 @@ export default { ...@@ -528,7 +528,7 @@ export default {
yAxis: DEFAULT_YAXIS_STYLE, yAxis: DEFAULT_YAXIS_STYLE,
background: DEFAULT_BACKGROUND_COLOR background: DEFAULT_BACKGROUND_COLOR
}) })
view.customFilter = JSON.stringify({}) view.customFilter = JSON.stringify([])
post('/chart/view/save', view).then(response => { post('/chart/view/save', view).then(response => {
this.selectTableFlag = false this.selectTableFlag = false
this.$store.dispatch('chart/setTableId', null) this.$store.dispatch('chart/setTableId', null)
......
...@@ -15,18 +15,18 @@ ...@@ -15,18 +15,18 @@
<!-- </el-button>--> <!-- </el-button>-->
</span> </span>
</el-row> </el-row>
<el-row style="display: flex;height: 100%"> <el-row class="view-panel">
<el-col <el-col
style="height: 100%;width: 20%;min-width: 180px;max-width:220px;border: 1px solid #E6E6E6;border-left: 0 solid;" style="height: 100%;width: 20%;min-width: 180px;max-width:220px;border: 1px solid #E6E6E6;border-left: 0 solid;"
> >
<div style="height: 45%;border-bottom: 1px solid #E6E6E6;" class="padding-lr"> <div style="height: 50%;border-bottom: 1px solid #E6E6E6;" class="padding-lr">
<span>{{ $t('chart.dimension') }}</span> <span>{{ $t('chart.dimension') }}</span>
<draggable <draggable
v-model="dimension" v-model="dimension"
:options="{group:{name: 'dimension',pull:'clone'},sort: true}" :options="{group:{name: 'dimension',pull:'clone'},sort: true}"
animation="300" animation="300"
:move="onMove" :move="onMove"
style="height: 90%;overflow:auto" class="drag-list"
@end="end1" @end="end1"
@start="start1" @start="start1"
> >
...@@ -35,14 +35,14 @@ ...@@ -35,14 +35,14 @@
</transition-group> </transition-group>
</draggable> </draggable>
</div> </div>
<div style="height: 45%;" class="padding-lr"> <div style="height: 50%;" class="padding-lr">
<span>{{ $t('chart.quota') }}</span> <span>{{ $t('chart.quota') }}</span>
<draggable <draggable
v-model="quota" v-model="quota"
:options="{group:{name: 'quota',pull:'clone'},sort: true}" :options="{group:{name: 'quota',pull:'clone'},sort: true}"
animation="300" animation="300"
:move="onMove" :move="onMove"
style="height: 90%;overflow:auto" class="drag-list"
@end="end1" @end="end1"
@start="start1" @start="start1"
> >
...@@ -54,7 +54,7 @@ ...@@ -54,7 +54,7 @@
</el-col> </el-col>
<el-col <el-col
style="height: 100%;width: 25%;min-width: 200px;max-width:220px;border: 1px solid #E6E6E6;border-left: 0 solid;" style="height: 100%;width: 30%;min-width: 200px;max-width:220px;border: 1px solid #E6E6E6;border-left: 0 solid;"
> >
<div style="border-bottom: 1px solid #E6E6E6;overflow-y:hidden;height: 62px;" class="padding-lr"> <div style="border-bottom: 1px solid #E6E6E6;overflow-y:hidden;height: 62px;" class="padding-lr">
<el-row> <el-row>
...@@ -73,7 +73,7 @@ ...@@ -73,7 +73,7 @@
</el-form-item> </el-form-item>
</el-form> </el-form>
</div> </div>
<div style="height: 25%;overflow:auto" class="padding-lr"> <div style="height: 30%;overflow:auto" class="padding-lr">
<span>{{ $t('chart.chart_type') }}</span> <span>{{ $t('chart.chart_type') }}</span>
<el-row> <el-row>
<div class="chart-type"> <div class="chart-type">
...@@ -151,7 +151,7 @@ ...@@ -151,7 +151,7 @@
@end="end2" @end="end2"
> >
<transition-group class="draggable-group"> <transition-group class="draggable-group">
<dimension-item v-for="(item,index) in view.xaxis" :key="item.id" :index="index" :item="item" @onDimensionItemChange="dimensionItemChange" @onDimensionItemRemove="dimensionItemRemove" /> <dimension-item v-for="(item,index) in view.xaxis" :key="item.id" :index="index" :item="item" @onDimensionItemChange="dimensionItemChange" @onDimensionItemRemove="dimensionItemRemove" @onNameEdit="showRename" />
</transition-group> </transition-group>
</draggable> </draggable>
</el-row> </el-row>
...@@ -166,16 +166,44 @@ ...@@ -166,16 +166,44 @@
@end="end2" @end="end2"
> >
<transition-group class="draggable-group"> <transition-group class="draggable-group">
<quota-item v-for="(item,index) in view.yaxis" :key="item.id" :index="index" :item="item" @onQuotaItemChange="quotaItemChange" @onQuotaItemRemove="quotaItemRemove" /> <quota-item v-for="(item,index) in view.yaxis" :key="item.id" :index="index" :item="item" @onQuotaItemChange="quotaItemChange" @onQuotaItemRemove="quotaItemRemove" @editItemFilter="showEditFilter" @onNameEdit="showRename" />
</transition-group> </transition-group>
</draggable> </draggable>
</el-row> </el-row>
</el-row> </el-row>
<chart-component :chart-id="chart.id" :chart="chart" style="padding: 10px" class="chart-class" /> <chart-component :chart-id="chart.id" :chart="chart" class="chart-class" />
</el-row> </el-row>
</el-col> </el-col>
</el-row> </el-row>
<!--显示名修改-->
<el-dialog :title="$t('chart.show_name_set')" :visible="renameItem" :show-close="false" width="30%">
<el-form ref="itemForm" :model="itemForm" :rules="itemFormRules">
<el-form-item :label="$t('commons.name')" prop="name">
<el-input v-model="itemForm.name" size="mini" clearable />
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button size="mini" @click="closeRename()">{{ $t('chart.cancel') }}</el-button>
<el-button type="primary" size="mini" @click="saveRename">{{ $t('chart.confirm') }}</el-button>
</div>
</el-dialog>
<!--指标过滤器-->
<el-dialog
:title="$t('chart.add_filter')"
:visible="filterEdit"
:show-close="false"
width="800px"
class="dialog-css"
>
<quota-filter-editor :item="quotaItem" />
<div slot="footer" class="dialog-footer">
<el-button size="mini" @click="closeQuotaFilter">{{ $t('chart.cancel') }}</el-button>
<el-button type="primary" size="mini" @click="saveQuotaFilter">{{ $t('chart.confirm') }}</el-button>
</div>
</el-dialog>
</el-row> </el-row>
</template> </template>
...@@ -207,10 +235,11 @@ import TooltipSelector from '../components/shape-attr/TooltipSelector' ...@@ -207,10 +235,11 @@ import TooltipSelector from '../components/shape-attr/TooltipSelector'
import XAxisSelector from '../components/component-style/XAxisSelector' import XAxisSelector from '../components/component-style/XAxisSelector'
import YAxisSelector from '../components/component-style/YAxisSelector' import YAxisSelector from '../components/component-style/YAxisSelector'
import BackgroundColorSelector from '../components/component-style/BackgroundColorSelector' import BackgroundColorSelector from '../components/component-style/BackgroundColorSelector'
import QuotaFilterEditor from '../components/filter/QuotaFilterEditor'
export default { export default {
name: 'ChartEdit', name: 'ChartEdit',
components: { BackgroundColorSelector, FilterItem, XAxisSelector, YAxisSelector, TooltipSelector, LabelSelector, LegendSelector, TitleSelector, SizeSelector, ColorSelector, ChartComponent, QuotaItem, DimensionItem, draggable }, components: { QuotaFilterEditor, BackgroundColorSelector, FilterItem, XAxisSelector, YAxisSelector, TooltipSelector, LabelSelector, LegendSelector, TitleSelector, SizeSelector, ColorSelector, ChartComponent, QuotaItem, DimensionItem, draggable },
data() { data() {
return { return {
table: {}, table: {},
...@@ -240,6 +269,17 @@ export default { ...@@ -240,6 +269,17 @@ export default {
moveId: -1, moveId: -1,
chart: { chart: {
id: 'echart' id: 'echart'
},
filterEdit: false,
quotaItem: {},
renameItem: false,
itemForm: {
name: ''
},
itemFormRules: {
name: [
{ required: true, message: this.$t('commons.input_content'), trigger: 'change' }
]
} }
} }
}, },
...@@ -305,6 +345,9 @@ export default { ...@@ -305,6 +345,9 @@ export default {
if (!ele.sort || ele.sort === '') { if (!ele.sort || ele.sort === '') {
ele.sort = 'none' ele.sort = 'none'
} }
if (!ele.filter) {
ele.filter = []
}
}) })
if (view.type.startsWith('pie') || view.type.startsWith('funnel')) { if (view.type.startsWith('pie') || view.type.startsWith('funnel')) {
if (view.yaxis.length > 1) { if (view.yaxis.length > 1) {
...@@ -490,6 +533,40 @@ export default { ...@@ -490,6 +533,40 @@ export default {
onChangeBackgroundForm(val) { onChangeBackgroundForm(val) {
this.view.customStyle.background = val this.view.customStyle.background = val
this.save() this.save()
},
showEditFilter(item) {
this.quotaItem = JSON.parse(JSON.stringify(item))
this.filterEdit = true
},
closeQuotaFilter() {
this.filterEdit = false
},
saveQuotaFilter() {
this.view.yaxis[this.quotaItem.index].filter = this.quotaItem.filter
this.save()
this.closeQuotaFilter()
},
showRename(val) {
this.itemForm = JSON.parse(JSON.stringify(val))
this.renameItem = true
},
saveRename() {
if (this.itemForm.renameType === 'quota') {
this.view.yaxis[this.itemForm.index].name = this.itemForm.name
} else if (this.itemForm.renameType === 'dimension') {
this.view.xaxis[this.itemForm.index].name = this.itemForm.name
}
this.save()
this.closeRename()
},
closeRename() {
this.renameItem = false
this.resetRename()
},
resetRename() {
// this.itemForm = {}
} }
} }
} }
...@@ -518,6 +595,16 @@ export default { ...@@ -518,6 +595,16 @@ export default {
margin-left: 10px; margin-left: 10px;
} }
.view-panel {
display: flex;
height: calc(100% - 40px);
}
.drag-list {
height: calc(100% - 26px);
overflow:auto;
}
.item { .item {
padding: 2px 10px; padding: 2px 10px;
margin: 2px 2px 0 2px; margin: 2px 2px 0 2px;
...@@ -621,6 +708,17 @@ export default { ...@@ -621,6 +708,17 @@ export default {
} }
.chart-class{ .chart-class{
height: calc(100% - 124px); height: calc(100% - 84px);
padding: 10px;
}
.dialog-css>>>.el-dialog__title {
font-size: 14px;
}
.dialog-css >>> .el-dialog__header {
padding: 20px 20px 0;
}
.dialog-css >>> .el-dialog__body {
padding: 10px 20px 20px;
} }
</style> </style>
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
<el-row> <el-row>
<el-row style="height: 26px;"> <el-row style="height: 26px;">
<span style="line-height: 26px;"> <span style="line-height: 26px;">
{{ $t('dataset.add_sql_table') }} {{ param.tableId?$t('dataset.edit_sql'):$t('dataset.add_sql_table') }}
</span> </span>
<el-row style="float: right"> <el-row style="float: right">
<el-button size="mini" @click="cancel"> <el-button size="mini" @click="cancel">
...@@ -85,6 +85,7 @@ ...@@ -85,6 +85,7 @@
<script> <script>
import { post, listDatasource } from '@/api/dataset/dataset' import { post, listDatasource } from '@/api/dataset/dataset'
import { codemirror } from 'vue-codemirror' import { codemirror } from 'vue-codemirror'
import { getTable } from '@/api/dataset/dataset'
// 核心样式 // 核心样式
import 'codemirror/lib/codemirror.css' import 'codemirror/lib/codemirror.css'
// 引入主题后还需要在 options 中指定主题才会生效 // 引入主题后还需要在 options 中指定主题才会生效
...@@ -145,7 +146,13 @@ export default { ...@@ -145,7 +146,13 @@ export default {
return this.$refs.myCm.codemirror return this.$refs.myCm.codemirror
} }
}, },
watch: {}, watch: {
'param.tableId': {
handler: function() {
this.initTableInfo()
}
}
},
mounted() { mounted() {
window.onresize = () => { window.onresize = () => {
return (() => { return (() => {
...@@ -157,6 +164,8 @@ export default { ...@@ -157,6 +164,8 @@ export default {
this.$refs.myCm.codemirror.on('keypress', () => { this.$refs.myCm.codemirror.on('keypress', () => {
this.$refs.myCm.codemirror.showHint() this.$refs.myCm.codemirror.showHint()
}) })
this.initTableInfo()
}, },
methods: { methods: {
initDataSource() { initDataSource() {
...@@ -165,6 +174,20 @@ export default { ...@@ -165,6 +174,20 @@ export default {
}) })
}, },
initTableInfo() {
if (this.param.tableId) {
getTable(this.param.tableId).then(response => {
const table = response.data
this.name = table.name
this.dataSource = table.dataSourceId
this.mode = table.mode + ''
this.sql = JSON.parse(table.info.replace(/\n/g, '\\n').replace(/\r/g, '\\r')).sql
this.getSQLPreview()
})
}
},
getSQLPreview() { getSQLPreview() {
if (!this.dataSource || this.datasource === '') { if (!this.dataSource || this.datasource === '') {
this.$message({ this.$message({
...@@ -204,6 +227,7 @@ export default { ...@@ -204,6 +227,7 @@ export default {
return return
} }
const table = { const table = {
id: this.param.tableId,
name: this.name, name: this.name,
sceneId: this.param.id, sceneId: this.param.id,
dataSourceId: this.dataSource, dataSourceId: this.dataSource,
......
...@@ -195,9 +195,9 @@ ...@@ -195,9 +195,9 @@
<el-row style="height: 26px;"> <el-row style="height: 26px;">
<el-row> <el-row>
<el-col :span="6"><div>{{ $t('dataset.incremental_update_type') }}:</div></el-col> <el-col :span="4"><span>{{ $t('dataset.incremental_update_type') }}:</span></el-col>
<el-col :span="18"> <el-col :span="18">
<el-radio-group v-model="incrementalUpdateType" size="small" @change="incrementalUpdateTypeChange"> <el-radio-group v-model="incrementalUpdateType" size="mini" @change="incrementalUpdateTypeChange">
<el-radio label="incrementalAdd">{{ $t('dataset.incremental_add') }}</el-radio> <el-radio label="incrementalAdd">{{ $t('dataset.incremental_add') }}</el-radio>
<el-radio label="incrementalDelete">{{ $t('dataset.incremental_delete') }}</el-radio> <el-radio label="incrementalDelete">{{ $t('dataset.incremental_delete') }}</el-radio>
</el-radio-group> </el-radio-group>
...@@ -207,10 +207,10 @@ ...@@ -207,10 +207,10 @@
<el-row style="height: 26px;"> <el-row style="height: 26px;">
<el-row> <el-row>
<el-col :span="6" style="height: 26px;"><div style="height: 26px;">{{ $t('dataset.param') }}:</div></el-col> <el-col :span="4" style="height: 26px;"><span style="display: inline-block;height: 26px;line-height: 26px;">{{ $t('dataset.param') }}:</span></el-col>
<el-col :span="18"> <el-col :span="18">
<el-button type="text" @click="insertParamToCodeMirror('${__last_update_time__}')">{{ $t('dataset.last_update_time') }}</el-button> <el-button type="text" size="mini" @click="insertParamToCodeMirror('${__last_update_time__}')">{{ $t('dataset.last_update_time') }}</el-button>
<el-button type="text" @click="insertParamToCodeMirror('${__current_update_time__}')">{{ $t('dataset.current_update_time') }}</el-button> <el-button type="text" size="mini" @click="insertParamToCodeMirror('${__current_update_time__}')">{{ $t('dataset.current_update_time') }}</el-button>
</el-col> </el-col>
</el-row> </el-row>
</el-row> </el-row>
...@@ -504,7 +504,18 @@ export default { ...@@ -504,7 +504,18 @@ export default {
} }
</script> </script>
<style scoped> <style scoped lang="scss">
.el-divider--horizontal {
margin: 12px 0;
}
.el-radio{
margin-right: 10px;
>>>.el-radio__label{
font-size: 12px;
}
}
.dialog-css >>> .el-dialog__header { .dialog-css >>> .el-dialog__header {
padding: 20px 20px 0; padding: 20px 20px 0;
} }
...@@ -525,4 +536,8 @@ export default { ...@@ -525,4 +536,8 @@ export default {
height: 100px; height: 100px;
overflow-y: auto; overflow-y: auto;
} }
span{
font-size: 12px;
}
</style> </style>
...@@ -7,6 +7,9 @@ ...@@ -7,6 +7,9 @@
{{ table.name }} {{ table.name }}
</span> </span>
<el-row style="float: right"> <el-row style="float: right">
<el-button v-if="table.type ==='sql'" size="mini" @click="editSql">
{{ $t('dataset.edit_sql') }}
</el-button>
<el-button size="mini" @click="edit"> <el-button size="mini" @click="edit">
{{ $t('dataset.edit') }} {{ $t('dataset.edit') }}
</el-button> </el-button>
...@@ -29,7 +32,7 @@ ...@@ -29,7 +32,7 @@
</el-tab-pane> </el-tab-pane>
</el-tabs> </el-tabs>
<el-dialog :title="table.name" :visible.sync="editField" :fullscreen="true" :show-close="false"> <el-dialog :title="table.name" :visible.sync="editField" :fullscreen="true" :show-close="false" class="dialog-css">
<el-table :data="tableFields" size="mini" max-height="600px"> <el-table :data="tableFields" size="mini" max-height="600px">
<el-table-column property="type" :label="$t('dataset.field_type')" width="100"> <el-table-column property="type" :label="$t('dataset.field_type')" width="100">
<template slot-scope="scope"> <template slot-scope="scope">
...@@ -146,6 +149,10 @@ export default { ...@@ -146,6 +149,10 @@ export default {
closeEdit() { closeEdit() {
this.editField = false this.editField = false
this.tableFields = [] this.tableFields = []
},
editSql() {
this.$emit('switchComponent', { name: 'AddSQL', param: { id: this.table.sceneId, tableId: this.table.id }})
} }
} }
} }
...@@ -159,4 +166,17 @@ export default { ...@@ -159,4 +166,17 @@ export default {
.form-item { .form-item {
margin-bottom: 6px; margin-bottom: 6px;
} }
.dialog-css>>>.el-dialog__title {
font-size: 14px;
}
.dialog-css >>> .el-dialog__header {
padding: 20px 20px 0;
}
.dialog-css >>> .el-dialog__body {
padding: 10px 20px;
}
.dialog-css >>> .el-dialog__footer {
padding-top: 30px;
}
</style> </style>
<template>
<div>
我是错误页面
</div>
</template>
<script>
export default {
name: 'LinkError',
data() {
return {
}
},
methods: {
}
}
</script>
<template>
<div>
<el-form ref="createOrganization" inline :model="form" size="small" label-width="80px">
<el-form-item label="链接分享">
<el-switch
v-model="valid"
style="width: 370px;"
:active-value="true"
:inactive-value="false"
/>
</el-form-item>
<el-form-item label=" ">
<el-link class="de-link" style="width: 370px;" disabled>开启链接后,任何人可通过此链接访问仪表板。</el-link>
</el-form-item>
<el-form-item v-if="valid" label="链接">
<el-input
v-model.number="form.uri"
disabled
style="width: 370px;"
/>
</el-form-item>
<el-form-item v-if="valid" label=" ">
<el-checkbox v-model="form.enablePwd">密码保护</el-checkbox>
<span v-if="form.enablePwd" class="de-span">{{ form.pwd }}</span>
<span v-if="form.enablePwd" class="de-span"><el-link :underline="false" type="primary">重置</el-link></span>
</el-form-item>
<div v-if="valid" class="auth-root-class">
<span slot="footer">
<el-button v-if="!form.enablePwd" v-clipboard:copy="form.uri" v-clipboard:success="onCopy" v-clipboard:error="onError" type="primary">复制链接及</el-button>
<el-button v-if="form.enablePwd" v-clipboard:copy="form.uri + ' 密码: '+ form.pwd" v-clipboard:success="onCopy" v-clipboard:error="onError" type="primary">复制链接及密码</el-button>
</span>
</div>
</el-form>
</div>
</template>
<script>
export default {
name: 'LinkGenerate',
components: {
},
props: {
resourceId: {
type: String,
default: null
}
},
data() {
return {
valid: false,
form: {},
defaultForm: { enablePwd: false, pwd: '000000', uri: 'http://baidu.com' }
}
},
created() {
this.form = this.defaultForm
},
methods: {
onCopy(e) {
// alert('You just copied: ' + e.text)
},
onError(e) {
// alert('Failed to copy texts')
}
}
}
</script>
<style lang="scss" scoped>
.de-link{
justify-content: left !important;
}
.de-span {
margin: 0 15px;
}
.auth-root-class {
margin: 15px 0px 5px;
text-align: right;
}
</style>
<template>
<div>
<link-error v-if="showIndex===0" />
<link-pwd v-if="showIndex===1" />
<link-view v-if="showIndex===2" />
</div>
</template>
<script>
import { getQueryVariable } from '@/utils/index'
import { validate } from '@/api/link'
import LinkView from './view'
import LinkError from './error'
import LinkPwd from './pwd'
export default {
components: {
LinkError, LinkPwd, LinkView
},
data() {
return {
PARAMKEY: 'link',
link: null,
showIndex: -1
}
},
created() {
this.loadInit()
},
methods: {
loadInit() {
this.link = getQueryVariable(this.PARAMKEY)
validate(this.buildParam()).then(res => {
const { valid, enablePwd, passPwd } = res.data
// 如果链接无效 直接显示无效页面
!valid && this.showError()
// 如果未启用密码 直接显示视图页面
!enablePwd && this.showView()
// 如果启用密码 但是未通过密码验证 显示密码框
!passPwd && this.showPwd()
this.showView()
})
console.log(this.link)
},
buildParam() {
return {}
},
// 显示无效链接
showError() {
this.showIndex = 0
},
// 显示密码框
showPwd() {
this.showIndex = 1
},
// 显示仪表板
showView() {
this.showIndex = 2
}
}
}
</script>
<template>
<div>
我是密码页面
</div>
</template>
<script>
export default {
name: 'LinkPwd',
data() {
return {
}
},
methods: {
}
}
</script>
<template>
<div>
我是视图7u页面
</div>
</template>
<script>
export default {
name: 'LinkView',
data() {
return {
}
},
methods: {
}
}
</script>
...@@ -91,6 +91,10 @@ ...@@ -91,6 +91,10 @@
<el-dropdown-item v-if="data.nodeType==='panel'" icon="el-icon-edit" :command="beforeClickMore('edit',data,node)"> <el-dropdown-item v-if="data.nodeType==='panel'" icon="el-icon-edit" :command="beforeClickMore('edit',data,node)">
{{ $t('panel.edit') }} {{ $t('panel.edit') }}
</el-dropdown-item> </el-dropdown-item>
<el-dropdown-item v-if="data.nodeType==='panel'" icon="el-icon-paperclip" :command="beforeClickMore('link',data,node)">
创建公共链接
</el-dropdown-item>
</el-dropdown-menu> </el-dropdown-menu>
</el-dropdown> </el-dropdown>
</span> </span>
...@@ -124,19 +128,35 @@ ...@@ -124,19 +128,35 @@
<el-button type="primary" @click="authVisible = false">确 定</el-button> <el-button type="primary" @click="authVisible = false">确 定</el-button>
</span> --> </span> -->
</el-dialog> </el-dialog>
<el-dialog
:title="linkTitle"
:visible.sync="linkVisible"
custom-class="de-dialog"
@closed="removeLink"
>
<link-generate v-if="linkVisible" :resource-id="linkResourceId" />
<!-- <span slot="footer" class="dialog-footer">
<el-button @click="copyUri">复制链接</el-button>
</span> -->
</el-dialog>
</el-col> </el-col>
</el-col> </el-col>
</template> </template>
<script> <script>
import GrantAuth from '../GrantAuth' import GrantAuth from '../GrantAuth'
import LinkGenerate from '@/views/link/generate'
import { loadTable, getScene, addGroup, delGroup, addTable, delTable, groupTree, defaultTree } from '@/api/panel/panel' import { loadTable, getScene, addGroup, delGroup, addTable, delTable, groupTree, defaultTree } from '@/api/panel/panel'
export default { export default {
name: 'PanelList', name: 'PanelList',
components: { GrantAuth }, components: { GrantAuth, LinkGenerate },
data() { data() {
return { return {
linkTitle: '链接分享',
linkVisible: false,
linkResourceId: null,
authTitle: null, authTitle: null,
authResourceId: null, authResourceId: null,
authVisible: false, authVisible: false,
...@@ -235,6 +255,9 @@ export default { ...@@ -235,6 +255,9 @@ export default {
case 'edit': case 'edit':
this.edit(param.data) this.edit(param.data)
break break
case 'link':
this.link(param.data)
break
} }
}, },
...@@ -497,6 +520,14 @@ export default { ...@@ -497,6 +520,14 @@ export default {
edit(data) { edit(data) {
this.$store.dispatch('panel/setPanelInfo', data) this.$store.dispatch('panel/setPanelInfo', data)
this.$router.replace('/panelEdit') this.$router.replace('/panelEdit')
},
link(data) {
this.linkVisible = true
this.linkResourceId = data.id
},
removeLink() {
this.linkVisible = false
this.linkResourceId = null
} }
} }
} }
......
...@@ -15,9 +15,9 @@ module.exports = { ...@@ -15,9 +15,9 @@ module.exports = {
devServer: { devServer: {
port: port, port: port,
proxy: { proxy: {
['^(?!/login)']: { '^(?!/login)': {
target: 'http://localhost:8081/', target: 'http://localhost:8081/',
ws: false, ws: false
} }
}, },
open: true, open: true,
...@@ -27,6 +27,18 @@ module.exports = { ...@@ -27,6 +27,18 @@ module.exports = {
}, },
before: require('./mock/mock-server.js') before: require('./mock/mock-server.js')
}, },
pages: {
index: {
entry: 'src/main.js',
template: 'public/index.html',
filename: 'index.html'
},
link: {
entry: 'src/link/link.js',
template: 'public/link.html',
filename: 'link.html'
}
},
configureWebpack: { configureWebpack: {
name: name, name: name,
devtool: 'source-map', devtool: 'source-map',
...@@ -54,105 +66,3 @@ module.exports = { ...@@ -54,105 +66,3 @@ module.exports = {
} }
} }
// module.exports = {
// publicPath: '/',
// outputDir: 'dist',
// assetsDir: 'static',
// lintOnSave: process.env.NODE_ENV === 'development',
// productionSourceMap: false,
// css: {
// sourceMap: true // 开启 CSS source maps
// },
// devServer: {
// port: port,
// open: true,
// overlay: {
// warnings: false,
// errors: true
// },
// before: require('./mock/mock-server.js')
// },
// configureWebpack: {
// name: name,
// resolve: {
// alias: {
// '@': resolve('src')
// }
// }
// },
// chainWebpack(config) {
// config.plugins.delete('preload') // TODO: need test
// config.plugins.delete('prefetch') // TODO: need test
// config.module
// .rule('svg')
// .exclude.add(resolve('src/icons'))
// .end()
// config.module
// .rule('icons')
// .test(/\.svg$/)
// .include.add(resolve('src/icons'))
// .end()
// .use('svg-sprite-loader')
// .loader('svg-sprite-loader')
// .options({
// symbolId: 'icon-[name]'
// })
// .end()
// config.module
// .rule('vue')
// .use('vue-loader')
// .loader('vue-loader')
// .tap(options => {
// options.compilerOptions.preserveWhitespace = true
// return options
// })
// .end()
// config
// .when(process.env.NODE_ENV === 'development',
// config => config.devtool('source-map')
// )
// config
// .when(process.env.NODE_ENV !== 'development',
// config => {
// config
// .plugin('ScriptExtHtmlWebpackPlugin')
// .after('html')
// .use('script-ext-html-webpack-plugin', [{
// inline: /runtime\..*\.js$/
// }])
// .end()
// config
// .optimization.splitChunks({
// chunks: 'all',
// cacheGroups: {
// libs: {
// name: 'chunk-libs',
// test: /[\\/]node_modules[\\/]/,
// priority: 10,
// chunks: 'initial' // only package third parties that are initially dependent
// },
// elementUI: {
// name: 'chunk-elementUI', // split elementUI into a single package
// priority: 20, // the weight needs to be larger than libs and app or it will be packaged into libs or app
// test: /[\\/]node_modules[\\/]_?element-ui(.*)/ // in order to adapt to cnpm
// },
// commons: {
// name: 'chunk-commons',
// test: resolve('src/components'), // can customize your rules
// minChunks: 3, // minimum common number
// priority: 5,
// reuseExistingChunk: true
// }
// }
// })
// config.optimization.runtimeChunk('single')
// }
// )
// }
// }
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论