diff --git a/backend/src/main/java/io/dataease/base/domain/ChartGroup.java b/backend/src/main/java/io/dataease/base/domain/ChartGroup.java new file mode 100644 index 0000000000..4d2128a4b6 --- /dev/null +++ b/backend/src/main/java/io/dataease/base/domain/ChartGroup.java @@ -0,0 +1,23 @@ +package io.dataease.base.domain; + +import java.io.Serializable; +import lombok.Data; + +@Data +public class ChartGroup implements Serializable { + private String id; + + private String name; + + private String pid; + + private Integer level; + + private String type; + + private String createBy; + + private Long createTime; + + private static final long serialVersionUID = 1L; +} \ No newline at end of file diff --git a/backend/src/main/java/io/dataease/base/domain/ChartGroupExample.java b/backend/src/main/java/io/dataease/base/domain/ChartGroupExample.java new file mode 100644 index 0000000000..c3bf4973e6 --- /dev/null +++ b/backend/src/main/java/io/dataease/base/domain/ChartGroupExample.java @@ -0,0 +1,670 @@ +package io.dataease.base.domain; + +import java.util.ArrayList; +import java.util.List; + +public class ChartGroupExample { + protected String orderByClause; + + protected boolean distinct; + + protected List oredCriteria; + + public ChartGroupExample() { + oredCriteria = new ArrayList(); + } + + public void setOrderByClause(String orderByClause) { + this.orderByClause = orderByClause; + } + + public String getOrderByClause() { + return orderByClause; + } + + public void setDistinct(boolean distinct) { + this.distinct = distinct; + } + + public boolean isDistinct() { + return distinct; + } + + public List getOredCriteria() { + return oredCriteria; + } + + public void or(Criteria criteria) { + oredCriteria.add(criteria); + } + + public Criteria or() { + Criteria criteria = createCriteriaInternal(); + oredCriteria.add(criteria); + return criteria; + } + + public Criteria createCriteria() { + Criteria criteria = createCriteriaInternal(); + if (oredCriteria.size() == 0) { + oredCriteria.add(criteria); + } + return criteria; + } + + protected Criteria createCriteriaInternal() { + Criteria criteria = new Criteria(); + return criteria; + } + + public void clear() { + oredCriteria.clear(); + orderByClause = null; + distinct = false; + } + + protected abstract static class GeneratedCriteria { + protected List criteria; + + protected GeneratedCriteria() { + super(); + criteria = new ArrayList(); + } + + public boolean isValid() { + return criteria.size() > 0; + } + + public List getAllCriteria() { + return criteria; + } + + public List getCriteria() { + return criteria; + } + + protected void addCriterion(String condition) { + if (condition == null) { + throw new RuntimeException("Value for condition cannot be null"); + } + criteria.add(new Criterion(condition)); + } + + protected void addCriterion(String condition, Object value, String property) { + if (value == null) { + throw new RuntimeException("Value for " + property + " cannot be null"); + } + criteria.add(new Criterion(condition, value)); + } + + protected void addCriterion(String condition, Object value1, Object value2, String property) { + if (value1 == null || value2 == null) { + throw new RuntimeException("Between values for " + property + " cannot be null"); + } + criteria.add(new Criterion(condition, value1, value2)); + } + + public Criteria andIdIsNull() { + addCriterion("id is null"); + return (Criteria) this; + } + + public Criteria andIdIsNotNull() { + addCriterion("id is not null"); + return (Criteria) this; + } + + public Criteria andIdEqualTo(String value) { + addCriterion("id =", value, "id"); + return (Criteria) this; + } + + public Criteria andIdNotEqualTo(String value) { + addCriterion("id <>", value, "id"); + return (Criteria) this; + } + + public Criteria andIdGreaterThan(String value) { + addCriterion("id >", value, "id"); + return (Criteria) this; + } + + public Criteria andIdGreaterThanOrEqualTo(String value) { + addCriterion("id >=", value, "id"); + return (Criteria) this; + } + + public Criteria andIdLessThan(String value) { + addCriterion("id <", value, "id"); + return (Criteria) this; + } + + public Criteria andIdLessThanOrEqualTo(String value) { + addCriterion("id <=", value, "id"); + return (Criteria) this; + } + + public Criteria andIdLike(String value) { + addCriterion("id like", value, "id"); + return (Criteria) this; + } + + public Criteria andIdNotLike(String value) { + addCriterion("id not like", value, "id"); + return (Criteria) this; + } + + public Criteria andIdIn(List values) { + addCriterion("id in", values, "id"); + return (Criteria) this; + } + + public Criteria andIdNotIn(List values) { + addCriterion("id not in", values, "id"); + return (Criteria) this; + } + + public Criteria andIdBetween(String value1, String value2) { + addCriterion("id between", value1, value2, "id"); + return (Criteria) this; + } + + public Criteria andIdNotBetween(String value1, String value2) { + addCriterion("id not between", value1, value2, "id"); + return (Criteria) this; + } + + public Criteria andNameIsNull() { + addCriterion("`name` is null"); + return (Criteria) this; + } + + public Criteria andNameIsNotNull() { + addCriterion("`name` is not null"); + return (Criteria) this; + } + + public Criteria andNameEqualTo(String value) { + addCriterion("`name` =", value, "name"); + return (Criteria) this; + } + + public Criteria andNameNotEqualTo(String value) { + addCriterion("`name` <>", value, "name"); + return (Criteria) this; + } + + public Criteria andNameGreaterThan(String value) { + addCriterion("`name` >", value, "name"); + return (Criteria) this; + } + + public Criteria andNameGreaterThanOrEqualTo(String value) { + addCriterion("`name` >=", value, "name"); + return (Criteria) this; + } + + public Criteria andNameLessThan(String value) { + addCriterion("`name` <", value, "name"); + return (Criteria) this; + } + + public Criteria andNameLessThanOrEqualTo(String value) { + addCriterion("`name` <=", value, "name"); + return (Criteria) this; + } + + public Criteria andNameLike(String value) { + addCriterion("`name` like", value, "name"); + return (Criteria) this; + } + + public Criteria andNameNotLike(String value) { + addCriterion("`name` not like", value, "name"); + return (Criteria) this; + } + + public Criteria andNameIn(List values) { + addCriterion("`name` in", values, "name"); + return (Criteria) this; + } + + public Criteria andNameNotIn(List values) { + addCriterion("`name` not in", values, "name"); + return (Criteria) this; + } + + public Criteria andNameBetween(String value1, String value2) { + addCriterion("`name` between", value1, value2, "name"); + return (Criteria) this; + } + + public Criteria andNameNotBetween(String value1, String value2) { + addCriterion("`name` not between", value1, value2, "name"); + return (Criteria) this; + } + + public Criteria andPidIsNull() { + addCriterion("pid is null"); + return (Criteria) this; + } + + public Criteria andPidIsNotNull() { + addCriterion("pid is not null"); + return (Criteria) this; + } + + public Criteria andPidEqualTo(String value) { + addCriterion("pid =", value, "pid"); + return (Criteria) this; + } + + public Criteria andPidNotEqualTo(String value) { + addCriterion("pid <>", value, "pid"); + return (Criteria) this; + } + + public Criteria andPidGreaterThan(String value) { + addCriterion("pid >", value, "pid"); + return (Criteria) this; + } + + public Criteria andPidGreaterThanOrEqualTo(String value) { + addCriterion("pid >=", value, "pid"); + return (Criteria) this; + } + + public Criteria andPidLessThan(String value) { + addCriterion("pid <", value, "pid"); + return (Criteria) this; + } + + public Criteria andPidLessThanOrEqualTo(String value) { + addCriterion("pid <=", value, "pid"); + return (Criteria) this; + } + + public Criteria andPidLike(String value) { + addCriterion("pid like", value, "pid"); + return (Criteria) this; + } + + public Criteria andPidNotLike(String value) { + addCriterion("pid not like", value, "pid"); + return (Criteria) this; + } + + public Criteria andPidIn(List values) { + addCriterion("pid in", values, "pid"); + return (Criteria) this; + } + + public Criteria andPidNotIn(List values) { + addCriterion("pid not in", values, "pid"); + return (Criteria) this; + } + + public Criteria andPidBetween(String value1, String value2) { + addCriterion("pid between", value1, value2, "pid"); + return (Criteria) this; + } + + public Criteria andPidNotBetween(String value1, String value2) { + addCriterion("pid not between", value1, value2, "pid"); + return (Criteria) this; + } + + public Criteria andLevelIsNull() { + addCriterion("`level` is null"); + return (Criteria) this; + } + + public Criteria andLevelIsNotNull() { + addCriterion("`level` is not null"); + return (Criteria) this; + } + + public Criteria andLevelEqualTo(Integer value) { + addCriterion("`level` =", value, "level"); + return (Criteria) this; + } + + public Criteria andLevelNotEqualTo(Integer value) { + addCriterion("`level` <>", value, "level"); + return (Criteria) this; + } + + public Criteria andLevelGreaterThan(Integer value) { + addCriterion("`level` >", value, "level"); + return (Criteria) this; + } + + public Criteria andLevelGreaterThanOrEqualTo(Integer value) { + addCriterion("`level` >=", value, "level"); + return (Criteria) this; + } + + public Criteria andLevelLessThan(Integer value) { + addCriterion("`level` <", value, "level"); + return (Criteria) this; + } + + public Criteria andLevelLessThanOrEqualTo(Integer value) { + addCriterion("`level` <=", value, "level"); + return (Criteria) this; + } + + public Criteria andLevelIn(List values) { + addCriterion("`level` in", values, "level"); + return (Criteria) this; + } + + public Criteria andLevelNotIn(List values) { + addCriterion("`level` not in", values, "level"); + return (Criteria) this; + } + + public Criteria andLevelBetween(Integer value1, Integer value2) { + addCriterion("`level` between", value1, value2, "level"); + return (Criteria) this; + } + + public Criteria andLevelNotBetween(Integer value1, Integer value2) { + addCriterion("`level` not between", value1, value2, "level"); + return (Criteria) this; + } + + public Criteria andTypeIsNull() { + addCriterion("`type` is null"); + return (Criteria) this; + } + + public Criteria andTypeIsNotNull() { + addCriterion("`type` is not null"); + return (Criteria) this; + } + + public Criteria andTypeEqualTo(String value) { + addCriterion("`type` =", value, "type"); + return (Criteria) this; + } + + public Criteria andTypeNotEqualTo(String value) { + addCriterion("`type` <>", value, "type"); + return (Criteria) this; + } + + public Criteria andTypeGreaterThan(String value) { + addCriterion("`type` >", value, "type"); + return (Criteria) this; + } + + public Criteria andTypeGreaterThanOrEqualTo(String value) { + addCriterion("`type` >=", value, "type"); + return (Criteria) this; + } + + public Criteria andTypeLessThan(String value) { + addCriterion("`type` <", value, "type"); + return (Criteria) this; + } + + public Criteria andTypeLessThanOrEqualTo(String value) { + addCriterion("`type` <=", value, "type"); + return (Criteria) this; + } + + public Criteria andTypeLike(String value) { + addCriterion("`type` like", value, "type"); + return (Criteria) this; + } + + public Criteria andTypeNotLike(String value) { + addCriterion("`type` not like", value, "type"); + return (Criteria) this; + } + + public Criteria andTypeIn(List values) { + addCriterion("`type` in", values, "type"); + return (Criteria) this; + } + + public Criteria andTypeNotIn(List values) { + addCriterion("`type` not in", values, "type"); + return (Criteria) this; + } + + public Criteria andTypeBetween(String value1, String value2) { + addCriterion("`type` between", value1, value2, "type"); + return (Criteria) this; + } + + public Criteria andTypeNotBetween(String value1, String value2) { + addCriterion("`type` not between", value1, value2, "type"); + return (Criteria) this; + } + + public Criteria andCreateByIsNull() { + addCriterion("create_by is null"); + return (Criteria) this; + } + + public Criteria andCreateByIsNotNull() { + addCriterion("create_by is not null"); + return (Criteria) this; + } + + public Criteria andCreateByEqualTo(String value) { + addCriterion("create_by =", value, "createBy"); + return (Criteria) this; + } + + public Criteria andCreateByNotEqualTo(String value) { + addCriterion("create_by <>", value, "createBy"); + return (Criteria) this; + } + + public Criteria andCreateByGreaterThan(String value) { + addCriterion("create_by >", value, "createBy"); + return (Criteria) this; + } + + public Criteria andCreateByGreaterThanOrEqualTo(String value) { + addCriterion("create_by >=", value, "createBy"); + return (Criteria) this; + } + + public Criteria andCreateByLessThan(String value) { + addCriterion("create_by <", value, "createBy"); + return (Criteria) this; + } + + public Criteria andCreateByLessThanOrEqualTo(String value) { + addCriterion("create_by <=", value, "createBy"); + return (Criteria) this; + } + + public Criteria andCreateByLike(String value) { + addCriterion("create_by like", value, "createBy"); + return (Criteria) this; + } + + public Criteria andCreateByNotLike(String value) { + addCriterion("create_by not like", value, "createBy"); + return (Criteria) this; + } + + public Criteria andCreateByIn(List values) { + addCriterion("create_by in", values, "createBy"); + return (Criteria) this; + } + + public Criteria andCreateByNotIn(List values) { + addCriterion("create_by not in", values, "createBy"); + return (Criteria) this; + } + + public Criteria andCreateByBetween(String value1, String value2) { + addCriterion("create_by between", value1, value2, "createBy"); + return (Criteria) this; + } + + public Criteria andCreateByNotBetween(String value1, String value2) { + addCriterion("create_by not between", value1, value2, "createBy"); + return (Criteria) this; + } + + public Criteria andCreateTimeIsNull() { + addCriterion("create_time is null"); + return (Criteria) this; + } + + public Criteria andCreateTimeIsNotNull() { + addCriterion("create_time is not null"); + return (Criteria) this; + } + + public Criteria andCreateTimeEqualTo(Long value) { + addCriterion("create_time =", value, "createTime"); + return (Criteria) this; + } + + public Criteria andCreateTimeNotEqualTo(Long value) { + addCriterion("create_time <>", value, "createTime"); + return (Criteria) this; + } + + public Criteria andCreateTimeGreaterThan(Long value) { + addCriterion("create_time >", value, "createTime"); + return (Criteria) this; + } + + public Criteria andCreateTimeGreaterThanOrEqualTo(Long value) { + addCriterion("create_time >=", value, "createTime"); + return (Criteria) this; + } + + public Criteria andCreateTimeLessThan(Long value) { + addCriterion("create_time <", value, "createTime"); + return (Criteria) this; + } + + public Criteria andCreateTimeLessThanOrEqualTo(Long value) { + addCriterion("create_time <=", value, "createTime"); + return (Criteria) this; + } + + public Criteria andCreateTimeIn(List values) { + addCriterion("create_time in", values, "createTime"); + return (Criteria) this; + } + + public Criteria andCreateTimeNotIn(List values) { + addCriterion("create_time not in", values, "createTime"); + return (Criteria) this; + } + + public Criteria andCreateTimeBetween(Long value1, Long value2) { + addCriterion("create_time between", value1, value2, "createTime"); + return (Criteria) this; + } + + public Criteria andCreateTimeNotBetween(Long value1, Long value2) { + addCriterion("create_time not between", value1, value2, "createTime"); + return (Criteria) this; + } + } + + public static class Criteria extends GeneratedCriteria { + + protected Criteria() { + super(); + } + } + + public static class Criterion { + private String condition; + + private Object value; + + private Object secondValue; + + private boolean noValue; + + private boolean singleValue; + + private boolean betweenValue; + + private boolean listValue; + + private String typeHandler; + + public String getCondition() { + return condition; + } + + public Object getValue() { + return value; + } + + public Object getSecondValue() { + return secondValue; + } + + public boolean isNoValue() { + return noValue; + } + + public boolean isSingleValue() { + return singleValue; + } + + public boolean isBetweenValue() { + return betweenValue; + } + + public boolean isListValue() { + return listValue; + } + + public String getTypeHandler() { + return typeHandler; + } + + protected Criterion(String condition) { + super(); + this.condition = condition; + this.typeHandler = null; + this.noValue = true; + } + + protected Criterion(String condition, Object value, String typeHandler) { + super(); + this.condition = condition; + this.value = value; + this.typeHandler = typeHandler; + if (value instanceof List) { + this.listValue = true; + } else { + this.singleValue = true; + } + } + + protected Criterion(String condition, Object value) { + this(condition, value, null); + } + + protected Criterion(String condition, Object value, Object secondValue, String typeHandler) { + super(); + this.condition = condition; + this.value = value; + this.secondValue = secondValue; + this.typeHandler = typeHandler; + this.betweenValue = true; + } + + protected Criterion(String condition, Object value, Object secondValue) { + this(condition, value, secondValue, null); + } + } +} \ No newline at end of file diff --git a/backend/src/main/java/io/dataease/base/mapper/ChartGroupMapper.java b/backend/src/main/java/io/dataease/base/mapper/ChartGroupMapper.java new file mode 100644 index 0000000000..92e6264833 --- /dev/null +++ b/backend/src/main/java/io/dataease/base/mapper/ChartGroupMapper.java @@ -0,0 +1,30 @@ +package io.dataease.base.mapper; + +import io.dataease.base.domain.ChartGroup; +import io.dataease.base.domain.ChartGroupExample; +import java.util.List; +import org.apache.ibatis.annotations.Param; + +public interface ChartGroupMapper { + long countByExample(ChartGroupExample example); + + int deleteByExample(ChartGroupExample example); + + int deleteByPrimaryKey(String id); + + int insert(ChartGroup record); + + int insertSelective(ChartGroup record); + + List selectByExample(ChartGroupExample example); + + ChartGroup selectByPrimaryKey(String id); + + int updateByExampleSelective(@Param("record") ChartGroup record, @Param("example") ChartGroupExample example); + + int updateByExample(@Param("record") ChartGroup record, @Param("example") ChartGroupExample example); + + int updateByPrimaryKeySelective(ChartGroup record); + + int updateByPrimaryKey(ChartGroup record); +} \ No newline at end of file diff --git a/backend/src/main/java/io/dataease/base/mapper/ChartGroupMapper.xml b/backend/src/main/java/io/dataease/base/mapper/ChartGroupMapper.xml new file mode 100644 index 0000000000..58f37d6da4 --- /dev/null +++ b/backend/src/main/java/io/dataease/base/mapper/ChartGroupMapper.xml @@ -0,0 +1,243 @@ + + + + + + + + + + + + + + + + + + + + + and ${criterion.condition} + + + and ${criterion.condition} #{criterion.value} + + + and ${criterion.condition} #{criterion.value} and #{criterion.secondValue} + + + and ${criterion.condition} + + #{listItem} + + + + + + + + + + + + + + + + + + and ${criterion.condition} + + + and ${criterion.condition} #{criterion.value} + + + and ${criterion.condition} #{criterion.value} and #{criterion.secondValue} + + + and ${criterion.condition} + + #{listItem} + + + + + + + + + + + id, `name`, pid, `level`, `type`, create_by, create_time + + + + + delete from chart_group + where id = #{id,jdbcType=VARCHAR} + + + delete from chart_group + + + + + + insert into chart_group (id, `name`, pid, + `level`, `type`, create_by, + create_time) + values (#{id,jdbcType=VARCHAR}, #{name,jdbcType=VARCHAR}, #{pid,jdbcType=VARCHAR}, + #{level,jdbcType=INTEGER}, #{type,jdbcType=VARCHAR}, #{createBy,jdbcType=VARCHAR}, + #{createTime,jdbcType=BIGINT}) + + + insert into chart_group + + + id, + + + `name`, + + + pid, + + + `level`, + + + `type`, + + + create_by, + + + create_time, + + + + + #{id,jdbcType=VARCHAR}, + + + #{name,jdbcType=VARCHAR}, + + + #{pid,jdbcType=VARCHAR}, + + + #{level,jdbcType=INTEGER}, + + + #{type,jdbcType=VARCHAR}, + + + #{createBy,jdbcType=VARCHAR}, + + + #{createTime,jdbcType=BIGINT}, + + + + + + update chart_group + + + id = #{record.id,jdbcType=VARCHAR}, + + + `name` = #{record.name,jdbcType=VARCHAR}, + + + pid = #{record.pid,jdbcType=VARCHAR}, + + + `level` = #{record.level,jdbcType=INTEGER}, + + + `type` = #{record.type,jdbcType=VARCHAR}, + + + create_by = #{record.createBy,jdbcType=VARCHAR}, + + + create_time = #{record.createTime,jdbcType=BIGINT}, + + + + + + + + update chart_group + set id = #{record.id,jdbcType=VARCHAR}, + `name` = #{record.name,jdbcType=VARCHAR}, + pid = #{record.pid,jdbcType=VARCHAR}, + `level` = #{record.level,jdbcType=INTEGER}, + `type` = #{record.type,jdbcType=VARCHAR}, + create_by = #{record.createBy,jdbcType=VARCHAR}, + create_time = #{record.createTime,jdbcType=BIGINT} + + + + + + update chart_group + + + `name` = #{name,jdbcType=VARCHAR}, + + + pid = #{pid,jdbcType=VARCHAR}, + + + `level` = #{level,jdbcType=INTEGER}, + + + `type` = #{type,jdbcType=VARCHAR}, + + + create_by = #{createBy,jdbcType=VARCHAR}, + + + create_time = #{createTime,jdbcType=BIGINT}, + + + where id = #{id,jdbcType=VARCHAR} + + + update chart_group + set `name` = #{name,jdbcType=VARCHAR}, + pid = #{pid,jdbcType=VARCHAR}, + `level` = #{level,jdbcType=INTEGER}, + `type` = #{type,jdbcType=VARCHAR}, + create_by = #{createBy,jdbcType=VARCHAR}, + create_time = #{createTime,jdbcType=BIGINT} + where id = #{id,jdbcType=VARCHAR} + + \ No newline at end of file diff --git a/backend/src/main/java/io/dataease/controller/chart/ChartController.java b/backend/src/main/java/io/dataease/controller/chart/ChartController.java new file mode 100644 index 0000000000..8c752f76dd --- /dev/null +++ b/backend/src/main/java/io/dataease/controller/chart/ChartController.java @@ -0,0 +1,26 @@ +package io.dataease.controller.chart; + +import com.alibaba.fastjson.JSON; +import io.dataease.base.domain.DatasetTable; +import io.dataease.controller.request.dataset.DataSetTableRequest; +import io.dataease.datasource.dto.TableFiled; +import io.dataease.service.dataset.DataSetTableService; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +@RestController +@RequestMapping("chart/table") +public class ChartController { + + + + @PostMapping("list") + public List list(@RequestBody DataSetTableRequest dataSetTableRequest) { + return new ArrayList<>(); + } + +} diff --git a/backend/src/main/java/io/dataease/controller/chart/ChartGroupController.java b/backend/src/main/java/io/dataease/controller/chart/ChartGroupController.java new file mode 100644 index 0000000000..2c642886c5 --- /dev/null +++ b/backend/src/main/java/io/dataease/controller/chart/ChartGroupController.java @@ -0,0 +1,32 @@ +package io.dataease.controller.chart; + +import io.dataease.base.domain.ChartGroup; +import io.dataease.controller.request.chart.ChartGroupRequest; +import io.dataease.dto.chart.ChartGroupDTO; +import io.dataease.service.chart.ChartGroupService; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import java.util.List; + +@RestController +@RequestMapping("chart/group") +public class ChartGroupController { + @Resource + private ChartGroupService chartGroupService; + + @PostMapping("/save") + public ChartGroupDTO save(@RequestBody ChartGroup ChartGroup) { + return chartGroupService.save(ChartGroup); + } + + @PostMapping("/tree") + public List tree(@RequestBody ChartGroupRequest ChartGroup) { + return chartGroupService.tree(ChartGroup); + } + + @PostMapping("/delete/{id}") + public void tree(@PathVariable String id) { + chartGroupService.delete(id); + } +} diff --git a/backend/src/main/java/io/dataease/controller/request/chart/ChartGroupRequest.java b/backend/src/main/java/io/dataease/controller/request/chart/ChartGroupRequest.java new file mode 100644 index 0000000000..27b0d12b9a --- /dev/null +++ b/backend/src/main/java/io/dataease/controller/request/chart/ChartGroupRequest.java @@ -0,0 +1,11 @@ +package io.dataease.controller.request.chart; + +import io.dataease.base.domain.ChartGroup; +import io.dataease.base.domain.DatasetGroup; +import lombok.Data; + + +@Data +public class ChartGroupRequest extends ChartGroup { + private String sort; +} diff --git a/backend/src/main/java/io/dataease/dto/chart/ChartGroupDTO.java b/backend/src/main/java/io/dataease/dto/chart/ChartGroupDTO.java new file mode 100644 index 0000000000..1542759994 --- /dev/null +++ b/backend/src/main/java/io/dataease/dto/chart/ChartGroupDTO.java @@ -0,0 +1,13 @@ +package io.dataease.dto.chart; + +import io.dataease.base.domain.DatasetGroup; +import lombok.Data; + +import java.util.List; + + +@Data +public class ChartGroupDTO extends DatasetGroup { + private String label; + private List children; +} diff --git a/backend/src/main/java/io/dataease/notice/controller/NoticeController.java b/backend/src/main/java/io/dataease/notice/controller/NoticeController.java new file mode 100644 index 0000000000..05ab59215c --- /dev/null +++ b/backend/src/main/java/io/dataease/notice/controller/NoticeController.java @@ -0,0 +1,36 @@ +package io.dataease.notice.controller; + +import io.dataease.notice.domain.MessageDetail; +import io.dataease.notice.service.NoticeService; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import java.util.List; + +@RestController +@RequestMapping("notice") +public class NoticeController { + @Resource + private NoticeService noticeService; + + @PostMapping("save/message/task") + public void saveMessage(@RequestBody MessageDetail messageDetail) { + noticeService.saveMessageTask(messageDetail); + } + + @GetMapping("/search/message/type/{type}") + public List searchMessage(@PathVariable String type) { + return noticeService.searchMessageByType(type); + } + + @GetMapping("/search/message/{testId}") + public List searchMessageSchedule(@PathVariable String testId) { + return noticeService.searchMessageByTestId(testId); + } + + @GetMapping("/delete/message/{identification}") + public int deleteMessage(@PathVariable String identification) { + return noticeService.delMessage(identification); + } +} + diff --git a/backend/src/main/java/io/dataease/notice/controller/request/MessageRequest.java b/backend/src/main/java/io/dataease/notice/controller/request/MessageRequest.java new file mode 100644 index 0000000000..b6642a8657 --- /dev/null +++ b/backend/src/main/java/io/dataease/notice/controller/request/MessageRequest.java @@ -0,0 +1,11 @@ +package io.dataease.notice.controller.request; + +import io.dataease.notice.domain.MessageDetail; +import lombok.Data; + +import java.util.List; + +@Data +public class MessageRequest { + private List messageDetail; +} diff --git a/backend/src/main/java/io/dataease/notice/domain/Mail.java b/backend/src/main/java/io/dataease/notice/domain/Mail.java new file mode 100644 index 0000000000..309bbe1368 --- /dev/null +++ b/backend/src/main/java/io/dataease/notice/domain/Mail.java @@ -0,0 +1,18 @@ +package io.dataease.notice.domain; + +import lombok.Data; + +@Data +public class Mail { + // 发送给谁 + private String to; + + // 发送主题 + private String subject; + + // 发送内容 + private String content; + + // 附件地址 + private String filePath; +} diff --git a/backend/src/main/java/io/dataease/notice/domain/MailInfo.java b/backend/src/main/java/io/dataease/notice/domain/MailInfo.java new file mode 100644 index 0000000000..d2f942a125 --- /dev/null +++ b/backend/src/main/java/io/dataease/notice/domain/MailInfo.java @@ -0,0 +1,15 @@ +package io.dataease.notice.domain; + +import lombok.Data; + +@Data +public class MailInfo { + private String host; + private String port; + private String account; + private String password; + private String ssl; + private String tls; + private String recipient; + +} diff --git a/backend/src/main/java/io/dataease/notice/domain/MessageDetail.java b/backend/src/main/java/io/dataease/notice/domain/MessageDetail.java new file mode 100644 index 0000000000..96d0a7d572 --- /dev/null +++ b/backend/src/main/java/io/dataease/notice/domain/MessageDetail.java @@ -0,0 +1,21 @@ +package io.dataease.notice.domain; + +import lombok.Data; + +import java.util.ArrayList; +import java.util.List; + +@Data +public class MessageDetail { + private List userIds = new ArrayList<>(); + private String event; + private String taskType; + private String webhook; + private String type; + private String identification; + private String organizationId; + private Boolean isSet; + private String testId; + private Long createTime; + private String template; +} diff --git a/backend/src/main/java/io/dataease/notice/domain/MessageSettingDetail.java b/backend/src/main/java/io/dataease/notice/domain/MessageSettingDetail.java new file mode 100644 index 0000000000..07ef6ad484 --- /dev/null +++ b/backend/src/main/java/io/dataease/notice/domain/MessageSettingDetail.java @@ -0,0 +1,13 @@ +package io.dataease.notice.domain; + +import lombok.Data; + +import java.util.List; + +@Data +public class MessageSettingDetail { + private List jenkinsTask; + private List testCasePlanTask; + private List reviewTask; + private List defectTask; +} diff --git a/backend/src/main/java/io/dataease/notice/domain/UserDetail.java b/backend/src/main/java/io/dataease/notice/domain/UserDetail.java new file mode 100644 index 0000000000..91d080b042 --- /dev/null +++ b/backend/src/main/java/io/dataease/notice/domain/UserDetail.java @@ -0,0 +1,9 @@ +package io.dataease.notice.domain; + +import lombok.Data; + +@Data +public class UserDetail { + private String email; + private String phone; +} diff --git a/backend/src/main/java/io/dataease/notice/message/LinkMessage.java b/backend/src/main/java/io/dataease/notice/message/LinkMessage.java new file mode 100644 index 0000000000..b2712564c8 --- /dev/null +++ b/backend/src/main/java/io/dataease/notice/message/LinkMessage.java @@ -0,0 +1,45 @@ +package io.dataease.notice.message; + +import com.alibaba.fastjson.JSON; +import org.apache.commons.lang3.StringUtils; + +import java.util.HashMap; +import java.util.Map; + + +public class LinkMessage implements Message { + + private String title; + private String text; + private String picUrl; + private String messageUrl; + + public String toJsonString() { + Map items = new HashMap(); + items.put("msgtype", "link"); + + Map linkContent = new HashMap(); + if (StringUtils.isBlank(title)) { + throw new IllegalArgumentException("title should not be blank"); + } + linkContent.put("title", title); + + if (StringUtils.isBlank(messageUrl)) { + throw new IllegalArgumentException("messageUrl should not be blank"); + } + linkContent.put("messageUrl", messageUrl); + + if (StringUtils.isBlank(text)) { + throw new IllegalArgumentException("text should not be blank"); + } + linkContent.put("text", text); + + if (StringUtils.isNotBlank(picUrl)) { + linkContent.put("picUrl", picUrl); + } + + items.put("link", linkContent); + + return JSON.toJSONString(items); + } +} diff --git a/backend/src/main/java/io/dataease/notice/message/Message.java b/backend/src/main/java/io/dataease/notice/message/Message.java new file mode 100644 index 0000000000..5dbad90764 --- /dev/null +++ b/backend/src/main/java/io/dataease/notice/message/Message.java @@ -0,0 +1,5 @@ +package io.dataease.notice.message; + +public interface Message { + String toJsonString(); +} diff --git a/backend/src/main/java/io/dataease/notice/message/TextMessage.java b/backend/src/main/java/io/dataease/notice/message/TextMessage.java new file mode 100644 index 0000000000..91caa7e4d6 --- /dev/null +++ b/backend/src/main/java/io/dataease/notice/message/TextMessage.java @@ -0,0 +1,64 @@ +package io.dataease.notice.message; + +import com.alibaba.fastjson.JSON; +import org.apache.commons.lang3.StringUtils; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + + +public class TextMessage implements Message { + private String text; + private List mentionedMobileList; + private boolean isAtAll; + + public TextMessage(String text) { + this.text = text; + } + + public String getText() { + return text; + } + + public void setText(String text) { + this.text = text; + } + + public boolean isAtAll() { + return isAtAll; + } + + public void setIsAtAll(boolean isAtAll) { + this.isAtAll = isAtAll; + } + + public List getMentionedMobileList() { + return mentionedMobileList; + } + + public void setMentionedMobileList(List mentionedMobileList) { + this.mentionedMobileList = mentionedMobileList; + } + + public String toJsonString() { + Map items = new HashMap(); + items.put("msgtype", "text"); + + Map textContent = new HashMap(); + if (StringUtils.isBlank(text)) { + throw new IllegalArgumentException("text should not be blank"); + } + textContent.put("content", text); + if (isAtAll) { + if (mentionedMobileList == null) mentionedMobileList = new ArrayList(); + mentionedMobileList.add("@all"); + } + if (mentionedMobileList != null && !mentionedMobileList.isEmpty()) { + textContent.put("mentioned_mobile_list", mentionedMobileList); + } + items.put("text", textContent); + return JSON.toJSONString(items); + } +} diff --git a/backend/src/main/java/io/dataease/notice/sender/AbstractNoticeSender.java b/backend/src/main/java/io/dataease/notice/sender/AbstractNoticeSender.java new file mode 100644 index 0000000000..099dc84ce4 --- /dev/null +++ b/backend/src/main/java/io/dataease/notice/sender/AbstractNoticeSender.java @@ -0,0 +1,150 @@ +package io.dataease.notice.sender; + +import io.dataease.commons.constants.NoticeConstants; +import io.dataease.commons.utils.LogUtil; +import io.dataease.notice.domain.MessageDetail; +import io.dataease.notice.domain.UserDetail; +import io.dataease.service.UserService; +import org.apache.commons.collections4.MapUtils; +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.RegExUtils; +import org.apache.commons.lang3.StringUtils; + +import javax.annotation.Resource; +import java.io.IOException; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +public abstract class AbstractNoticeSender implements NoticeSender { + @Resource + private UserService userService; + + protected String getContext(MessageDetail messageDetail, NoticeModel noticeModel) { + // 如果配置了模版就直接使用模版 + if (StringUtils.isNotBlank(messageDetail.getTemplate())) { + return getContent(messageDetail.getTemplate(), noticeModel.getParamMap()); + } + // 处理 userIds 中包含的特殊值 + List realUserIds = getRealUserIds(messageDetail.getUserIds(), noticeModel.getRelatedUsers(), messageDetail.getEvent()); + messageDetail.setUserIds(realUserIds); + + // 处理 WeCom Ding context + String context = ""; + switch (messageDetail.getEvent()) { + case NoticeConstants.Event.CREATE: + case NoticeConstants.Event.UPDATE: + case NoticeConstants.Event.DELETE: + case NoticeConstants.Event.COMMENT: + context = noticeModel.getContext(); + break; + case NoticeConstants.Event.EXECUTE_FAILED: + context = noticeModel.getFailedContext(); + break; + case NoticeConstants.Event.EXECUTE_SUCCESSFUL: + context = noticeModel.getSuccessContext(); + break; + default: + break; + } + return context; + } + + protected String getHtmlContext(MessageDetail messageDetail, NoticeModel noticeModel) { + // 如果配置了模版就直接使用模版 + if (StringUtils.isNotBlank(messageDetail.getTemplate())) { + return getContent(messageDetail.getTemplate(), noticeModel.getParamMap()); + } + // 处理 userIds 中包含的特殊值 + List realUserIds = getRealUserIds(messageDetail.getUserIds(), noticeModel.getRelatedUsers(), messageDetail.getEvent()); + messageDetail.setUserIds(realUserIds); + + // 处理 mail context + String context = ""; + try { + switch (messageDetail.getEvent()) { + case NoticeConstants.Event.CREATE: + case NoticeConstants.Event.UPDATE: + case NoticeConstants.Event.DELETE: + case NoticeConstants.Event.COMMENT: + URL resource = this.getClass().getResource("/mail/" + noticeModel.getMailTemplate() + ".html"); + context = IOUtils.toString(resource, StandardCharsets.UTF_8); + break; + case NoticeConstants.Event.EXECUTE_FAILED: + URL resource1 = this.getClass().getResource("/mail/" + noticeModel.getFailedMailTemplate() + ".html"); + context = IOUtils.toString(resource1, StandardCharsets.UTF_8); + break; + case NoticeConstants.Event.EXECUTE_SUCCESSFUL: + URL resource2 = this.getClass().getResource("/mail/" + noticeModel.getSuccessMailTemplate() + ".html"); + context = IOUtils.toString(resource2, StandardCharsets.UTF_8); + break; + default: + break; + } + } catch (IOException e) { + LogUtil.error(e); + } + return getContent(context, noticeModel.getParamMap()); + } + + protected String getContent(String template, Map context) { + if (MapUtils.isNotEmpty(context)) { + for (String k : context.keySet()) { + if (context.get(k) != null) { + template = RegExUtils.replaceAll(template, "\\$\\{" + k + "}", context.get(k).toString()); + } else { + template = RegExUtils.replaceAll(template, "\\$\\{" + k + "}", "未设置"); + } + } + } + return template; + } + + protected List getUserPhones(List userIds) { + List list = userService.queryTypeByIds(userIds); + List phoneList = new ArrayList<>(); + list.forEach(u -> phoneList.add(u.getPhone())); + LogUtil.info("收件人地址: " + phoneList); + return phoneList.stream().distinct().collect(Collectors.toList()); + } + + protected List getUserEmails(List userIds) { + List list = userService.queryTypeByIds(userIds); + List phoneList = new ArrayList<>(); + list.forEach(u -> phoneList.add(u.getEmail())); + LogUtil.info("收件人地址: " + phoneList); + return phoneList.stream().distinct().collect(Collectors.toList()); + } + + private List getRealUserIds(List userIds, List relatedUsers, String event) { + List toUserIds = new ArrayList<>(); + for (String userId : userIds) { + switch (userId) { + case NoticeConstants.RelatedUser.EXECUTOR: + if (StringUtils.equals(NoticeConstants.Event.CREATE, event)) { + toUserIds.addAll(relatedUsers); + } + break; + case NoticeConstants.RelatedUser.FOUNDER: + if (StringUtils.equals(NoticeConstants.Event.UPDATE, event) + || StringUtils.equals(NoticeConstants.Event.DELETE, event)) { + toUserIds.addAll(relatedUsers); + } + break; + case NoticeConstants.RelatedUser.MAINTAINER: + if (StringUtils.equals(NoticeConstants.Event.COMMENT, event)) { + toUserIds.addAll(relatedUsers); + } + break; + default: + toUserIds.add(userId); + break; + } + } + + return toUserIds; + } +} diff --git a/backend/src/main/java/io/dataease/notice/sender/NoticeModel.java b/backend/src/main/java/io/dataease/notice/sender/NoticeModel.java new file mode 100644 index 0000000000..2dc6f7d47a --- /dev/null +++ b/backend/src/main/java/io/dataease/notice/sender/NoticeModel.java @@ -0,0 +1,51 @@ +package io.dataease.notice.sender; + +import lombok.Builder; +import lombok.Data; + +import java.util.List; +import java.util.Map; + +@Data +@Builder +public class NoticeModel { + /** + * 保存 测试id + */ + private String testId; + /** + * 保存状态 + */ + private String status; + /** + * Event + */ + private String event; + /** + * 消息主题 + */ + private String subject; + /** + * 消息内容 + */ + private String context; + private String successContext; + private String failedContext; + + /** + * html 消息模版 + */ + private String mailTemplate; + private String failedMailTemplate; + private String successMailTemplate; + + /** + * 保存特殊的用户 + */ + private List relatedUsers; + + /** + * 模版里的参数信息 + */ + private Map paramMap; +} diff --git a/backend/src/main/java/io/dataease/notice/sender/NoticeSender.java b/backend/src/main/java/io/dataease/notice/sender/NoticeSender.java new file mode 100644 index 0000000000..8958d71006 --- /dev/null +++ b/backend/src/main/java/io/dataease/notice/sender/NoticeSender.java @@ -0,0 +1,9 @@ +package io.dataease.notice.sender; + +import io.dataease.notice.domain.MessageDetail; +import org.springframework.scheduling.annotation.Async; + +public interface NoticeSender { + @Async + void send(MessageDetail messageDetail, NoticeModel noticeModel); +} diff --git a/backend/src/main/java/io/dataease/notice/sender/impl/MailNoticeSender.java b/backend/src/main/java/io/dataease/notice/sender/impl/MailNoticeSender.java new file mode 100644 index 0000000000..e82b56c66f --- /dev/null +++ b/backend/src/main/java/io/dataease/notice/sender/impl/MailNoticeSender.java @@ -0,0 +1,50 @@ +package io.dataease.notice.sender.impl; + + +import io.dataease.commons.utils.LogUtil; +import io.dataease.notice.domain.MessageDetail; +import io.dataease.notice.sender.AbstractNoticeSender; +import io.dataease.notice.sender.NoticeModel; +import io.dataease.notice.service.MailService; +import org.springframework.mail.javamail.JavaMailSenderImpl; +import org.springframework.mail.javamail.MimeMessageHelper; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; +import javax.mail.MessagingException; +import javax.mail.internet.MimeMessage; +import java.util.List; + +@Component +public class MailNoticeSender extends AbstractNoticeSender { + @Resource + private MailService mailService; + + private void sendMail(MessageDetail messageDetail, String context, NoticeModel noticeModel) throws MessagingException { + LogUtil.info("发送邮件开始 "); + JavaMailSenderImpl javaMailSender = mailService.getMailSender(); + MimeMessage mimeMessage = javaMailSender.createMimeMessage(); + MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true); + helper.setFrom(javaMailSender.getUsername()); + LogUtil.info("发件人地址"+javaMailSender.getUsername()); + LogUtil.info("helper"+helper); + helper.setSubject("MeterSphere " + noticeModel.getSubject()); + List emails = super.getUserEmails(messageDetail.getUserIds()); + String[] users = emails.toArray(new String[0]); + LogUtil.info("收件人地址: " + emails); + helper.setText(context, true); + helper.setTo(users); + javaMailSender.send(mimeMessage); + } + + @Override + public void send(MessageDetail messageDetail, NoticeModel noticeModel) { + String context = super.getHtmlContext(messageDetail, noticeModel); + try { + sendMail(messageDetail, context, noticeModel); + LogUtil.info("发送邮件结束"); + } catch (Exception e) { + LogUtil.error(e); + } + } +} diff --git a/backend/src/main/java/io/dataease/notice/sender/impl/WeComNoticeSender.java b/backend/src/main/java/io/dataease/notice/sender/impl/WeComNoticeSender.java new file mode 100644 index 0000000000..1bd43b5664 --- /dev/null +++ b/backend/src/main/java/io/dataease/notice/sender/impl/WeComNoticeSender.java @@ -0,0 +1,39 @@ +package io.dataease.notice.sender.impl; + +import io.dataease.notice.sender.AbstractNoticeSender; +import io.dataease.commons.utils.LogUtil; +import io.dataease.notice.domain.MessageDetail; +import io.dataease.notice.message.TextMessage; +import io.dataease.notice.sender.NoticeModel; +import io.dataease.notice.util.WxChatbotClient; +import org.apache.commons.collections4.CollectionUtils; +import org.springframework.stereotype.Component; + +import java.io.IOException; +import java.util.List; + +@Component +public class WeComNoticeSender extends AbstractNoticeSender { + + + public void sendWechatRobot(MessageDetail messageDetail, String context) { + List userIds = messageDetail.getUserIds(); + if (CollectionUtils.isEmpty(userIds)) { + return; + } + TextMessage message = new TextMessage(context); + List phoneLists = super.getUserPhones(userIds); + message.setMentionedMobileList(phoneLists); + try { + WxChatbotClient.send(messageDetail.getWebhook(), message); + } catch (IOException e) { + LogUtil.error(e.getMessage(), e); + } + } + + @Override + public void send(MessageDetail messageDetail, NoticeModel noticeModel) { + String context = super.getContext(messageDetail, noticeModel); + sendWechatRobot(messageDetail, context); + } +} diff --git a/backend/src/main/java/io/dataease/notice/service/MailService.java b/backend/src/main/java/io/dataease/notice/service/MailService.java new file mode 100644 index 0000000000..bd33b23f25 --- /dev/null +++ b/backend/src/main/java/io/dataease/notice/service/MailService.java @@ -0,0 +1,79 @@ +package io.dataease.notice.service; + +import io.dataease.base.domain.SystemParameter; +import io.dataease.commons.constants.ParamConstants; +import io.dataease.commons.utils.EncryptUtils; +import io.dataease.service.system.SystemParameterService; +import org.apache.commons.lang3.BooleanUtils; +import org.springframework.mail.javamail.JavaMailSenderImpl; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Propagation; +import org.springframework.transaction.annotation.Transactional; + +import javax.annotation.Resource; +import java.util.List; +import java.util.Properties; + +@Service +@Transactional(propagation = Propagation.NOT_SUPPORTED) +public class MailService { + @Resource + private SystemParameterService systemParameterService; + + public JavaMailSenderImpl getMailSender() { + Properties props = new Properties(); + JavaMailSenderImpl javaMailSender = new JavaMailSenderImpl(); + List paramList = systemParameterService.getParamList(ParamConstants.Classify.MAIL.getValue()); + javaMailSender.setDefaultEncoding("UTF-8"); + javaMailSender.setProtocol("smtp"); + props.put("mail.smtp.auth", "true"); + + for (SystemParameter p : paramList) { + switch (p.getParamKey()) { + case "smtp.host": + javaMailSender.setHost(p.getParamValue()); + break; + case "smtp.port": + javaMailSender.setPort(Integer.parseInt(p.getParamValue())); + break; + case "smtp.account": + javaMailSender.setUsername(p.getParamValue()); + break; + case "smtp.password": + javaMailSender.setPassword(EncryptUtils.aesDecrypt(p.getParamValue()).toString()); + break; + case "smtp.ssl": + if (BooleanUtils.toBoolean(p.getParamValue())) { + javaMailSender.setProtocol("smtps"); + props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory"); + } + break; + case "smtp.tls": + String result = BooleanUtils.toString(BooleanUtils.toBoolean(p.getParamValue()), "true", "false"); + props.put("mail.smtp.starttls.enable", result); + props.put("mail.smtp.starttls.required", result); + break; + /* case "smtp.anon": + boolean isAnon = BooleanUtils.toBoolean(p.getParamValue()); + if (isAnon) { + props.put("mail.smtp.auth", "false"); + javaMailSender.setUsername(null); + javaMailSender.setPassword(null); + } + break;*/ + default: + break; + } + } + + props.put("mail.smtp.timeout", "30000"); + props.put("mail.smtp.connectiontimeout", "5000"); + javaMailSender.setJavaMailProperties(props); + return javaMailSender; + } +} + + + + + diff --git a/backend/src/main/java/io/dataease/notice/service/NoticeSendService.java b/backend/src/main/java/io/dataease/notice/service/NoticeSendService.java new file mode 100644 index 0000000000..7ab13e1fbb --- /dev/null +++ b/backend/src/main/java/io/dataease/notice/service/NoticeSendService.java @@ -0,0 +1,63 @@ +package io.dataease.notice.service; + +import io.dataease.commons.constants.NoticeConstants; +import io.dataease.notice.domain.MessageDetail; +import io.dataease.notice.sender.NoticeModel; +import io.dataease.notice.sender.NoticeSender; +import io.dataease.notice.sender.impl.MailNoticeSender; +import io.dataease.notice.sender.impl.WeComNoticeSender; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; +import java.util.List; + +@Component +public class NoticeSendService { + @Resource + private MailNoticeSender mailNoticeSender; + @Resource + private WeComNoticeSender weComNoticeSender; + + @Resource + private NoticeService noticeService; + + private NoticeSender getNoticeSender(MessageDetail messageDetail) { + NoticeSender noticeSender = null; + switch (messageDetail.getType()) { + case NoticeConstants.Type.EMAIL: + noticeSender = mailNoticeSender; + break; + case NoticeConstants.Type.WECHAT_ROBOT: + noticeSender = weComNoticeSender; + break; +// case NoticeConstants.Type.NAIL_ROBOT: +// noticeSender = dingNoticeSender; +// break; + default: + break; + } + + return noticeSender; + } + + public void send(String taskType, NoticeModel noticeModel) { + List messageDetails; + switch (taskType) { + case NoticeConstants.Mode.API: + messageDetails = noticeService.searchMessageByType(NoticeConstants.TaskType.JENKINS_TASK); + break; + case NoticeConstants.Mode.SCHEDULE: + messageDetails = noticeService.searchMessageByTestId(noticeModel.getTestId()); + break; + default: + messageDetails = noticeService.searchMessageByType(taskType); + break; + } + messageDetails.forEach(messageDetail -> { + if (StringUtils.equals(messageDetail.getEvent(), noticeModel.getEvent())) { + this.getNoticeSender(messageDetail).send(messageDetail, noticeModel); + } + }); + } +} diff --git a/backend/src/main/java/io/dataease/notice/service/NoticeService.java b/backend/src/main/java/io/dataease/notice/service/NoticeService.java new file mode 100644 index 0000000000..e7c2a8d027 --- /dev/null +++ b/backend/src/main/java/io/dataease/notice/service/NoticeService.java @@ -0,0 +1,160 @@ +package io.dataease.notice.service; + +import io.dataease.base.domain.MessageTask; +import io.dataease.base.domain.MessageTaskExample; +import io.dataease.base.mapper.MessageTaskMapper; +import io.dataease.commons.exception.DEException; +import io.dataease.commons.user.SessionUser; +import io.dataease.commons.utils.SessionUtils; +import io.dataease.i18n.Translator; +import io.dataease.notice.domain.MessageDetail; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import javax.annotation.Resource; +import java.util.*; +import java.util.stream.Collectors; + +@Service +@Transactional(rollbackFor = Exception.class) +public class NoticeService { + @Resource + private MessageTaskMapper messageTaskMapper; + + public void saveMessageTask(MessageDetail messageDetail) { + MessageTaskExample example = new MessageTaskExample(); + example.createCriteria().andIdentificationEqualTo(messageDetail.getIdentification()); + List messageTaskLists = messageTaskMapper.selectByExample(example); + if (messageTaskLists.size() > 0) { + delMessage(messageDetail.getIdentification()); + } + SessionUser user = SessionUtils.getUser(); + String orgId = user.getLastOrganizationId(); + long time = System.currentTimeMillis(); + String identification = messageDetail.getIdentification(); + if (StringUtils.isBlank(identification)) { + identification = UUID.randomUUID().toString(); + } + for (String userId : messageDetail.getUserIds()) { + checkUserIdExist(userId, messageDetail, orgId); + MessageTask messageTask = new MessageTask(); + messageTask.setId(UUID.randomUUID().toString()); + messageTask.setEvent(messageDetail.getEvent()); + messageTask.setTaskType(messageDetail.getTaskType()); + messageTask.setUserId(userId); + messageTask.setType(messageDetail.getType()); + messageTask.setWebhook(messageDetail.getWebhook()); + messageTask.setIdentification(identification); + messageTask.setIsSet(false); + messageTask.setOrganizationId(orgId); + messageTask.setTestId(messageDetail.getTestId()); + messageTask.setCreateTime(time); + setTemplate(messageDetail, messageTask); + messageTaskMapper.insert(messageTask); + } + } + + private void setTemplate(MessageDetail messageDetail, MessageTask messageTask) { + if (StringUtils.isNotBlank(messageDetail.getTemplate())) { + messageTask.setTemplate(messageDetail.getTemplate()); + } + } + + private void checkUserIdExist(String userId, MessageDetail list, String orgId) { + MessageTaskExample example = new MessageTaskExample(); + if (StringUtils.isBlank(list.getTestId())) { + example.createCriteria() + .andUserIdEqualTo(userId) + .andEventEqualTo(list.getEvent()) + .andTypeEqualTo(list.getType()) + .andTaskTypeEqualTo(list.getTaskType()) + .andWebhookEqualTo(list.getWebhook()) + .andOrganizationIdEqualTo(orgId); + } else { + example.createCriteria() + .andUserIdEqualTo(userId) + .andEventEqualTo(list.getEvent()) + .andTypeEqualTo(list.getType()) + .andTaskTypeEqualTo(list.getTaskType()) + .andWebhookEqualTo(list.getWebhook()) + .andTestIdEqualTo(list.getTestId()) + .andOrganizationIdEqualTo(orgId); + } + if (messageTaskMapper.countByExample(example) > 0) { + DEException.throwException(Translator.get("message_task_already_exists")); + } + } + + public List searchMessageByTestId(String testId) { + MessageTaskExample example = new MessageTaskExample(); + example.createCriteria().andTestIdEqualTo(testId); + List messageTaskLists = messageTaskMapper.selectByExampleWithBLOBs(example); + List scheduleMessageTask = new ArrayList<>(); + Map> MessageTaskMap = messageTaskLists.stream().collect(Collectors.groupingBy(MessageTask::getIdentification)); + MessageTaskMap.forEach((k, v) -> { + MessageDetail messageDetail = getMessageDetail(v); + scheduleMessageTask.add(messageDetail); + }); + scheduleMessageTask.sort(Comparator.comparing(MessageDetail::getCreateTime, Comparator.nullsLast(Long::compareTo)).reversed()); + return scheduleMessageTask; + } + + public List searchMessageByType(String type) { + SessionUser user = SessionUtils.getUser(); + String orgId = user.getLastOrganizationId(); + List messageDetails = new ArrayList<>(); + + MessageTaskExample example = new MessageTaskExample(); + example.createCriteria() + .andTaskTypeEqualTo(type) + .andOrganizationIdEqualTo(orgId); + List messageTaskLists = messageTaskMapper.selectByExampleWithBLOBs(example); + + Map> messageTaskMap = messageTaskLists.stream() + .collect(Collectors.groupingBy(NoticeService::fetchGroupKey)); + messageTaskMap.forEach((k, v) -> { + MessageDetail messageDetail = getMessageDetail(v); + messageDetails.add(messageDetail); + }); + + return messageDetails.stream() + .sorted(Comparator.comparing(MessageDetail::getCreateTime, Comparator.nullsLast(Long::compareTo)).reversed()) + .collect(Collectors.toList()) + .stream() + .distinct() + .collect(Collectors.toList()); + } + + private MessageDetail getMessageDetail(List messageTasks) { + Set userIds = new HashSet<>(); + + MessageDetail messageDetail = new MessageDetail(); + for (MessageTask m : messageTasks) { + userIds.add(m.getUserId()); + messageDetail.setEvent(m.getEvent()); + messageDetail.setTaskType(m.getTaskType()); + messageDetail.setWebhook(m.getWebhook()); + messageDetail.setIdentification(m.getIdentification()); + messageDetail.setType(m.getType()); + messageDetail.setIsSet(m.getIsSet()); + messageDetail.setCreateTime(m.getCreateTime()); + messageDetail.setTemplate(m.getTemplate()); + } + if (CollectionUtils.isNotEmpty(userIds)) { + messageDetail.setUserIds(new ArrayList<>(userIds)); + } + return messageDetail; + } + + private static String fetchGroupKey(MessageTask messageTask) { + return messageTask.getTaskType() + "#" + messageTask.getIdentification(); + } + + public int delMessage(String identification) { + MessageTaskExample example = new MessageTaskExample(); + example.createCriteria().andIdentificationEqualTo(identification); + return messageTaskMapper.deleteByExample(example); + } +} diff --git a/backend/src/main/java/io/dataease/notice/util/SendResult.java b/backend/src/main/java/io/dataease/notice/util/SendResult.java new file mode 100644 index 0000000000..6b154bdd3a --- /dev/null +++ b/backend/src/main/java/io/dataease/notice/util/SendResult.java @@ -0,0 +1,47 @@ +package io.dataease.notice.util; + +import com.alibaba.fastjson.JSON; + +import java.util.HashMap; +import java.util.Map; + +/** + * + */ +public class SendResult { + private boolean isSuccess; + private Integer errorCode; + private String errorMsg; + + public boolean isSuccess() { + return isSuccess; + } + + public void setIsSuccess(boolean isSuccess) { + this.isSuccess = isSuccess; + } + + public Integer getErrorCode() { + return errorCode; + } + + public void setErrorCode(Integer errorCode) { + this.errorCode = errorCode; + } + + public String getErrorMsg() { + return errorMsg; + } + + public void setErrorMsg(String errorMsg) { + this.errorMsg = errorMsg; + } + + public String toString() { + Map items = new HashMap(); + items.put("errorCode", errorCode); + items.put("errorMsg", errorMsg); + items.put("isSuccess", isSuccess); + return JSON.toJSONString(items); + } +} diff --git a/backend/src/main/java/io/dataease/notice/util/WxChatbotClient.java b/backend/src/main/java/io/dataease/notice/util/WxChatbotClient.java new file mode 100644 index 0000000000..192e9c42e1 --- /dev/null +++ b/backend/src/main/java/io/dataease/notice/util/WxChatbotClient.java @@ -0,0 +1,50 @@ +package io.dataease.notice.util; + +import com.alibaba.fastjson.JSONObject; +import io.dataease.notice.message.Message; +import org.apache.commons.lang3.StringUtils; +import org.apache.http.HttpResponse; +import org.apache.http.HttpStatus; +import org.apache.http.client.HttpClient; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.util.EntityUtils; + +import java.io.IOException; + +/** + * + */ +public class WxChatbotClient { + + static HttpClient httpclient = HttpClients.createDefault(); + + public static SendResult send(String webhook, Message message) throws IOException { + + if (StringUtils.isBlank(webhook)) { + return new SendResult(); + } + HttpPost httppost = new HttpPost(webhook); + httppost.addHeader("Content-Type", "application/json; charset=utf-8"); + StringEntity se = new StringEntity(message.toJsonString(), "utf-8"); + httppost.setEntity(se); + + SendResult sendResult = new SendResult(); + HttpResponse response = httpclient.execute(httppost); + if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) { + String result = EntityUtils.toString(response.getEntity()); + JSONObject obj = JSONObject.parseObject(result); + + Integer errcode = obj.getInteger("errcode"); + sendResult.setErrorCode(errcode); + sendResult.setErrorMsg(obj.getString("errmsg")); + sendResult.setIsSuccess(errcode.equals(0)); + } + + return sendResult; + } + +} + + diff --git a/backend/src/main/java/io/dataease/service/chart/ChartGroupService.java b/backend/src/main/java/io/dataease/service/chart/ChartGroupService.java new file mode 100644 index 0000000000..0b4f68389e --- /dev/null +++ b/backend/src/main/java/io/dataease/service/chart/ChartGroupService.java @@ -0,0 +1,111 @@ +package io.dataease.service.chart; + +import io.dataease.base.domain.ChartGroup; +import io.dataease.base.domain.ChartGroupExample; +import io.dataease.base.mapper.ChartGroupMapper; +import io.dataease.commons.utils.BeanUtils; +import io.dataease.controller.request.chart.ChartGroupRequest; +import io.dataease.dto.chart.ChartGroupDTO; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; +import java.util.stream.Collectors; + + +@Service +public class ChartGroupService { + @Resource + private ChartGroupMapper chartGroupMapper; + + public ChartGroupDTO save(ChartGroup chartGroup) { + if (StringUtils.isEmpty(chartGroup.getId())) { + chartGroup.setId(UUID.randomUUID().toString()); + chartGroup.setCreateTime(System.currentTimeMillis()); + chartGroupMapper.insert(chartGroup); + } else { + chartGroupMapper.updateByPrimaryKey(chartGroup); + } + ChartGroupDTO ChartGroupDTO = new ChartGroupDTO(); + BeanUtils.copyBean(ChartGroupDTO, chartGroup); + ChartGroupDTO.setLabel(ChartGroupDTO.getName()); + return ChartGroupDTO; + } + + public void delete(String id) { + ChartGroupRequest ChartGroup = new ChartGroupRequest(); + ChartGroup.setId(id); + List tree = tree(ChartGroup); + List ids = new ArrayList<>(); + getAllId(tree, ids); + ChartGroupExample ChartGroupExample = new ChartGroupExample(); + ChartGroupExample.createCriteria().andIdIn(ids); + chartGroupMapper.deleteByExample(ChartGroupExample); + } + + public List tree(ChartGroupRequest ChartGroup) { + ChartGroupExample ChartGroupExample = new ChartGroupExample(); + ChartGroupExample.Criteria criteria = ChartGroupExample.createCriteria(); + if (StringUtils.isNotEmpty(ChartGroup.getName())) { + criteria.andNameLike("%" + ChartGroup.getName() + "%"); + } + if (StringUtils.isNotEmpty(ChartGroup.getType())) { + criteria.andTypeEqualTo(ChartGroup.getType()); + } + if (StringUtils.isNotEmpty(ChartGroup.getId())) { + criteria.andIdEqualTo(ChartGroup.getId()); + } else { + criteria.andLevelEqualTo(0); + } + ChartGroupExample.setOrderByClause(ChartGroup.getSort()); + List ChartGroups = chartGroupMapper.selectByExample(ChartGroupExample); + List DTOs = ChartGroups.stream().map(ele -> { + ChartGroupDTO dto = new ChartGroupDTO(); + BeanUtils.copyBean(dto, ele); + dto.setLabel(ele.getName()); + return dto; + }).collect(Collectors.toList()); + getAll(DTOs, ChartGroup); + return DTOs; + } + + public void getAll(List list, ChartGroupRequest ChartGroup) { + for (ChartGroupDTO obj : list) { + ChartGroupExample ChartGroupExample = new ChartGroupExample(); + ChartGroupExample.Criteria criteria = ChartGroupExample.createCriteria(); + if (StringUtils.isNotEmpty(ChartGroup.getName())) { + criteria.andNameLike("%" + ChartGroup.getName() + "%"); + } + if (StringUtils.isNotEmpty(ChartGroup.getType())) { + criteria.andTypeEqualTo(ChartGroup.getType()); + } + criteria.andPidEqualTo(obj.getId()); + ChartGroupExample.setOrderByClause(ChartGroup.getSort()); + List ChartGroups = chartGroupMapper.selectByExample(ChartGroupExample); + List DTOs = ChartGroups.stream().map(ele -> { + ChartGroupDTO dto = new ChartGroupDTO(); + BeanUtils.copyBean(dto, ele); + dto.setLabel(ele.getName()); + return dto; + }).collect(Collectors.toList()); + obj.setChildren(DTOs); + if (CollectionUtils.isNotEmpty(DTOs)) { + getAll(DTOs, ChartGroup); + } + } + } + + public List getAllId(List list, List ids) { + for (ChartGroupDTO dto : list) { + ids.add(dto.getId()); + if (CollectionUtils.isNotEmpty(dto.getChildren())) { + getAllId(dto.getChildren(), ids); + } + } + return ids; + } +} diff --git a/backend/src/main/resources/db/migration/V10__chart.sql b/backend/src/main/resources/db/migration/V10__chart.sql new file mode 100644 index 0000000000..3d4e563eb4 --- /dev/null +++ b/backend/src/main/resources/db/migration/V10__chart.sql @@ -0,0 +1,12 @@ +-- chart start +CREATE TABLE IF NOT EXISTS `chart_group` ( + `id` varchar(50) NOT NULL COMMENT 'ID', + `name` varchar(64) NOT NULL COMMENT '名称', + `pid` varchar(50) COMMENT '父级ID', + `level` int(10) COMMENT '当前分组处于第几级', + `type` varchar(50) COMMENT 'group or scene', + `create_by` varchar(50) COMMENT '创建人ID', + `create_time` bigint(13) COMMENT '创建时间', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; +-- chart end diff --git a/frontend/src/assets/favicon.ico b/frontend/src/assets/favicon.ico new file mode 100644 index 0000000000..9dc173ff67 Binary files /dev/null and b/frontend/src/assets/favicon.ico differ diff --git a/frontend/src/business/components/chart/Chart.vue b/frontend/src/business/components/chart/Chart.vue new file mode 100644 index 0000000000..bc27092c0b --- /dev/null +++ b/frontend/src/business/components/chart/Chart.vue @@ -0,0 +1,45 @@ + + + + + diff --git a/frontend/src/business/components/chart/data/AddDB.vue b/frontend/src/business/components/chart/data/AddDB.vue new file mode 100644 index 0000000000..bdc47a0553 --- /dev/null +++ b/frontend/src/business/components/chart/data/AddDB.vue @@ -0,0 +1,148 @@ + + + + + diff --git a/frontend/src/business/components/chart/data/ChartHome.vue b/frontend/src/business/components/chart/data/ChartHome.vue new file mode 100644 index 0000000000..a3e454d98f --- /dev/null +++ b/frontend/src/business/components/chart/data/ChartHome.vue @@ -0,0 +1,25 @@ + + + + + diff --git a/frontend/src/business/components/chart/data/TabDataPreview.vue b/frontend/src/business/components/chart/data/TabDataPreview.vue new file mode 100644 index 0000000000..8a8e52eb13 --- /dev/null +++ b/frontend/src/business/components/chart/data/TabDataPreview.vue @@ -0,0 +1,62 @@ + + + + + diff --git a/frontend/src/business/components/chart/data/ViewTable.vue b/frontend/src/business/components/chart/data/ViewTable.vue new file mode 100644 index 0000000000..38a9ad1408 --- /dev/null +++ b/frontend/src/business/components/chart/data/ViewTable.vue @@ -0,0 +1,122 @@ + + + + + diff --git a/frontend/src/business/components/chart/group/Group.vue b/frontend/src/business/components/chart/group/Group.vue new file mode 100644 index 0000000000..d2a4b6f563 --- /dev/null +++ b/frontend/src/business/components/chart/group/Group.vue @@ -0,0 +1,540 @@ + + + + + diff --git a/frontend/src/business/components/chart/router.js b/frontend/src/business/components/chart/router.js new file mode 100644 index 0000000000..579847c8fb --- /dev/null +++ b/frontend/src/business/components/chart/router.js @@ -0,0 +1,18 @@ +const Chart = () => import('@/business/components/chart/Chart'); +const ChartHome = () => import('@/business/components/chart/data/ChartHome'); + +export default { + path: "/chart", + name: "ChartGroup", + redirect: "/chart/home", + components: { + content: Chart, + }, + children: [ + { + path: 'home', + name: 'home', + component: ChartHome, + } + ] +}