Merge branch 'dev' into pr@dev@feat_relationship_analyze

This commit is contained in:
wisonic-s 2022-12-21 12:15:02 +08:00
commit dbceeac4ff
189 changed files with 8158 additions and 2440 deletions

View File

@ -48,6 +48,9 @@ DataEase 是开源的数据可视化分析工具,帮助用户快速分析数
<img src="https://dataease.io/images/dataSource/TiDB.jpg" alt="TiDB" border="0" width="155" height="107"/>
<img src="https://dataease.io/images/dataSource/StarRocks.jpg" alt="StarRocks" border="0" width="155" height="107"/>
<img src="https://dataease.io/images/dataSource/PrestoDB.jpg" alt="PrestoDB" border="0" width="155" height="107"/>
<img src="https://dataease.io/images/dataSource/dm.jpg" alt="dm" border="0" width="155" height="107"/>
<img src="https://dataease.io/images/dataSource/kingbase.jpg" alt="KingBase" border="0" width="155" height="107"/>
<img src="https://dataease.io/images/dataSource/kylin.jpg" alt="Kylin" border="0" width="180" height="107"/>
</p>
> 更多数据源支持持续增加中...

View File

@ -1,6 +1,5 @@
package io.dataease.auth.filter;
import cn.hutool.core.util.URLUtil;
import com.auth0.jwt.algorithms.Algorithm;
import io.dataease.auth.entity.ASKToken;
import io.dataease.auth.entity.JWTToken;
@ -24,10 +23,8 @@ import org.springframework.web.bind.annotation.RequestMethod;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.nio.charset.Charset;
public class JWTFilter extends BasicHttpAuthenticationFilter {
@ -161,18 +158,4 @@ public class JWTFilter extends BasicHttpAuthenticationFilter {
httpServletResponse.setHeader("authentication-status", "login_expire");
}
@Override
protected boolean onAccessDenied(ServletRequest req, ServletResponse res, Object mappedValue) throws Exception {
HttpServletResponse response = (HttpServletResponse) res;
HttpServletRequest request = (HttpServletRequest) req;
String requestURI = request.getRequestURI();
String msg = requestURI + " has been denied";
String encode = URLUtil.encode(msg, Charset.forName("UTF-8"));
Cookie cookie_error = new Cookie("onAccessDeniedMsg", encode);
cookie_error.setPath("/");
response.addCookie(cookie_error);
response.sendRedirect("/");
return false;
}
}

View File

@ -20,9 +20,9 @@ public class PanelConstants {
public final static String PANEL_NODE_TYPE_PANEL = "panel";
public final static String OPT_TYPE_INSERT="insert";
public final static String OPT_TYPE_INSERT = "insert";
public final static String OPT_TYPE_UPDATE="update";
public final static String OPT_TYPE_UPDATE = "update";
public final static String PANEL_GATHER_DEFAULT_PANEL = "default_panel";
@ -68,4 +68,16 @@ public class PanelConstants {
}
//应用数据源来源
public static final class APP_DATASOURCE_FROM {
// 新建
public static final String NEW = "new";
// 复用
public static final String HISTORY = "history";
}
}

View File

@ -3,6 +3,7 @@ package io.dataease.commons.utils;
import org.apache.commons.lang3.StringUtils;
import javax.servlet.http.HttpServletRequest;
import java.net.InetAddress;
import java.util.Arrays;
public class IPUtils {
@ -42,4 +43,12 @@ public class IPUtils {
ipStr = Arrays.stream(ipStr.split(",")).filter(item -> StringUtils.isNotBlank(item) && !StringUtils.equalsIgnoreCase(UNKNOWN, item.trim())).findFirst().orElse(ipStr);
return StringUtils.equals(LOCAL_IP_KEY, ipStr) ? LOCAL_IP_VAL : ipStr;
}
public static String domain() {
try {
return InetAddress.getLocalHost().getHostAddress();
} catch (Exception e) {
return LOCAL_IP_VAL;
}
}
}

View File

@ -247,6 +247,12 @@ public class DataSetTableController {
return dataSetTableService.paramsWithIds(type, viewIds);
}
@ApiOperation("数据集的SQL变量")
@PostMapping("/params/{id}/{type}")
List<SqlVariableDetails> paramsWithIds(@PathVariable String type, @PathVariable String id) {
return dataSetTableService.datasetParams(type, id);
}
@ApiOperation("根据数据集文件夹ID查询数据集名称")
@PostMapping("/getDatasetNameFromGroup/{sceneId}")
public List<String> getDatasetNameFromGroup(@PathVariable String sceneId) {

View File

@ -200,6 +200,7 @@ public class DataSetTableFieldController {
}
List<Object> list = results.stream().distinct().collect(Collectors.toList());
list = dataSetFieldService.chineseSort(list, multFieldValuesRequest.getSort());
return list;
}
@ -246,7 +247,7 @@ public class DataSetTableFieldController {
@DePermission(type = DePermissionType.DATASET)
@ApiOperation("时间格式")
@PostMapping("dateformats/{tableId}")
public List<Dateformat> dateformats(@PathVariable String tableId) throws Exception{
public List<Dateformat> dateformats(@PathVariable String tableId) throws Exception {
DatasetTable datasetTable = dataSetTableService.get(tableId);
Datasource ds = datasetTable.getMode() == 0 ? datasourceService.get(datasetTable.getDataSourceId()) : engineService.getDeEngine();
QueryProvider qp = ProviderFactory.getQueryProvider(ds.getType());

View File

@ -19,7 +19,6 @@ import io.dataease.plugins.common.base.domain.Datasource;
import io.dataease.service.datasource.DatasourceService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.web.bind.annotation.*;
@ -49,10 +48,24 @@ public class DatasourceController {
positionIndex = 0, positionKey = "type",
value = "id"
)
public Datasource addDatasource(@RequestBody Datasource datasource) throws Exception {
public Datasource addDatasource(@RequestBody DatasourceDTO datasource) throws Exception {
return datasourceService.addDatasource(datasource);
}
@RequiresPermissions("datasource:read")
@DePermission(type = DePermissionType.DATASOURCE, value = "id", level = ResourceAuthLevel.DATASOURCE_LEVEL_MANAGE)
@ApiOperation("更新数据源")
@PostMapping("/update")
@DeLog(
operatetype = SysLogConstants.OPERATE_TYPE.MODIFY,
sourcetype = SysLogConstants.SOURCE_TYPE.DATASOURCE,
positionIndex = 0, positionKey = "type",
value = "id"
)
public void updateDatasource(@RequestBody UpdataDsRequest dsRequest) throws Exception {
datasourceService.updateDatasource(dsRequest);
}
@RequiresPermissions("datasource:read")
@ApiOperation("数据源类型")
@GetMapping("/types")
@ -62,7 +75,7 @@ public class DatasourceController {
@ApiIgnore
@PostMapping("/validate")
public ResultHolder validate(@RequestBody Datasource datasource) throws Exception {
public ResultHolder validate(@RequestBody DatasourceDTO datasource) throws Exception {
return datasourceService.validate(datasource);
}
@ -107,20 +120,6 @@ public class DatasourceController {
return resultHolder;
}
@RequiresPermissions("datasource:read")
@DePermission(type = DePermissionType.DATASOURCE, value = "id", level = ResourceAuthLevel.DATASOURCE_LEVEL_MANAGE)
@ApiOperation("更新数据源")
@PostMapping("/update")
@DeLog(
operatetype = SysLogConstants.OPERATE_TYPE.MODIFY,
sourcetype = SysLogConstants.SOURCE_TYPE.DATASOURCE,
positionIndex = 0, positionKey = "type",
value = "id"
)
public void updateDatasource(@RequestBody UpdataDsRequest dsRequest) throws Exception {
datasourceService.updateDatasource(dsRequest);
}
@DePermission(type = DePermissionType.DATASOURCE)
@ApiOperation("查询数据源下属所有表")
@PostMapping("/getTables/{id}")
@ -130,7 +129,7 @@ public class DatasourceController {
@ApiIgnore
@PostMapping("/getSchema")
public List<String> getSchema(@RequestBody Datasource datasource) throws Exception {
public List<String> getSchema(@RequestBody DatasourceDTO datasource) throws Exception {
return datasourceService.getSchema(datasource);
}

View File

@ -15,4 +15,5 @@ public class UpdataDsRequest {
private String type;
@ApiModelProperty(value = "配置详情", required = true)
private String configuration;
private boolean configurationEncryption = false;
}

View File

@ -1,6 +1,6 @@
package io.dataease.controller.request.panel;
import io.dataease.plugins.common.base.domain.Datasource;
import io.dataease.dto.DatasourceDTO;
import lombok.Data;
import java.util.List;
@ -29,5 +29,9 @@ public class PanelAppTemplateApplyRequest {
private String appTemplateId;
private List<Datasource> datasourceList;
private String datasourceFrom;
private String datasourceHistoryId;
private List<DatasourceDTO> datasourceList;
}

View File

@ -19,6 +19,8 @@ public class DatasourceDTO extends Datasource {
@ApiModelProperty("权限")
private String privileges;
private List<ApiDefinition> apiConfiguration;
private String apiConfigurationStr;
private String typeDesc;
private DatasourceCalculationMode calculationMode;
private boolean isConfigurationEncryption = false;
}

View File

@ -16,40 +16,42 @@
</resultMap>
<select id="query" parameterType="io.dataease.service.panel.applog.AppLogQueryParam" resultMap="BaseResultMapDTO">
select
logInfo.*,
get_auths(logInfo.dataset_group_id,'dataset',#{userId}) as `dataset_privileges`,
get_auths(logInfo.panel_id,'panel',#{userId}) as `panel_privileges`,
get_auths(logInfo.datasource_id,'link',#{userId}) as `datasource_privileges`
from
logInfo.*,
get_auths(logInfo.dataset_group_id,'dataset',#{userId}) as `dataset_privileges`,
get_auths(logInfo.panel_id,'panel',#{userId}) as `panel_privileges`,
get_auths(logInfo.datasource_id,'link',#{userId}) as `datasource_privileges`
from
(select * from
(SELECT
panel_app_template_log.id,
panel_app_template_log.app_template_id,
panel_app_template_log.app_template_name,
datasource.id as datasource_id,
panel_app_template_log.source_datasource_name,
dataset_group.id as dataset_group_id,
panel_app_template_log.source_dataset_group_name,
panel_group.id as panel_id,
panel_app_template_log.source_panel_name,
panel_app_template_log.apply_time,
panel_app_template_log.apply_persion,
panel_app_template_log.is_success,
panel_app_template_log.remark,
panel_group.pid as panel_group_pid,
datasource.type as datasource_type,
dataset_group.pid as dataset_group_pid,
IFNULL(panel_app_template.name,CONCAT(panel_app_template_log.app_template_name,'(Deleted)')) as app_name,
IFNULL(panel_group.name,CONCAT(panel_app_template_log.source_panel_name,'(Deleted)')) as panel_name,
IFNULL(dataset_group.name,CONCAT(panel_app_template_log.source_dataset_group_name,'(Deleted)')) as dataset_group_name,
IFNULL(datasource.`name`,CONCAT(panel_app_template_log.source_datasource_name,'(Deleted)')) as datasource_name
FROM
panel_app_template_log
LEFT JOIN panel_group ON panel_app_template_log.panel_id = panel_group.id
left join dataset_group on panel_app_template_log.dataset_group_id = dataset_group.id
left join datasource on panel_app_template_log.datasource_id = datasource.id
left join panel_app_template on panel_app_template_log.app_template_id = panel_app_template.id
) t
(SELECT
panel_app_template_log.id,
panel_app_template_log.app_template_id,
panel_app_template_log.app_template_name,
datasource.id as datasource_id,
panel_app_template_log.source_datasource_name,
panel_app_template_log.datasource_from,
dataset_group.id as dataset_group_id,
panel_app_template_log.source_dataset_group_name,
panel_group.id as panel_id,
panel_app_template_log.source_panel_name,
panel_app_template_log.apply_time,
panel_app_template_log.apply_persion,
panel_app_template_log.is_success,
panel_app_template_log.remark,
panel_group.pid as panel_group_pid,
datasource.type as datasource_type,
dataset_group.pid as dataset_group_pid,
IFNULL(panel_app_template.name,CONCAT(panel_app_template_log.app_template_name,'(Deleted)')) as app_name,
IFNULL(panel_group.name,CONCAT(panel_app_template_log.source_panel_name,'(Deleted)')) as panel_name,
IFNULL(dataset_group.name,CONCAT(panel_app_template_log.source_dataset_group_name,'(Deleted)')) as
dataset_group_name,
IFNULL(datasource.`name`,CONCAT(panel_app_template_log.source_datasource_name,'(Deleted)')) as datasource_name
FROM
panel_app_template_log
LEFT JOIN panel_group ON panel_app_template_log.panel_id = panel_group.id
left join dataset_group on panel_app_template_log.dataset_group_id = dataset_group.id
left join datasource on panel_app_template_log.datasource_id = datasource.id
left join panel_app_template on panel_app_template_log.app_template_id = panel_app_template.id
) t
where 1=1
<if test="extendCondition != null">
and

View File

@ -8,14 +8,11 @@
<result column="privileges" property="privileges"/>
</resultMap>
<select id ="findByPanelId" resultMap="BaseResultMapDTO">
SELECT
chart_view.*
FROM
chart_view
LEFT JOIN panel_view ON chart_view.id = panel_view.chart_view_id
WHERE
panel_view.panel_id = #{panelId}
<select id="findByPanelId" resultMap="BaseResultMapDTO">
SELECT chart_view.*
FROM chart_view
LEFT JOIN panel_view ON chart_view.id = panel_view.chart_view_id
WHERE panel_view.panel_id = #{panelId}
</select>
<select id="searchOneWithPrivileges" resultMap="BaseResultMapDTO">
@ -25,198 +22,210 @@
</select>
<select id="searchOne" resultMap="BaseResultMapDTO">
select
chart_view.*
from chart_view where id = #{id}
select chart_view.*
from chart_view
where id = #{id}
</select>
<insert id="copyToCache">
INSERT INTO chart_view_cache (
id,
`name`,
title,
scene_id,
table_id,
`type`,
render,
result_count,
result_mode,
create_by,
create_time,
update_time,
style_priority,
chart_type,
is_plugin,
x_axis,
x_axis_ext,
y_axis,
y_axis_ext,
ext_stack,
ext_bubble,
custom_attr,
custom_style,
custom_filter,
drill_fields,
senior,
SNAPSHOT,
data_from
) SELECT
id,
`name`,
title,
scene_id,
table_id,
`type`,
render,
result_count,
result_mode,
create_by,
create_time,
update_time,
style_priority,
chart_type,
is_plugin,
x_axis,
x_axis_ext,
y_axis,
y_axis_ext,
ext_stack,
ext_bubble,
custom_attr,
custom_style,
custom_filter,
drill_fields,
senior,
SNAPSHOT,
data_from from chart_view
WHERE
chart_view.id = #{id}
INSERT INTO chart_view_cache (id,
`name`,
title,
scene_id,
table_id,
`type`,
render,
result_count,
result_mode,
create_by,
create_time,
update_time,
style_priority,
chart_type,
is_plugin,
x_axis,
x_axis_ext,
y_axis,
y_axis_ext,
ext_stack,
ext_bubble,
custom_attr,
custom_style,
custom_filter,
drill_fields,
senior,
SNAPSHOT,
data_from,
refresh_view_enable,
refresh_unit,
refresh_time)
SELECT id,
`name`,
title,
scene_id,
table_id,
`type`,
render,
result_count,
result_mode,
create_by,
create_time,
update_time,
style_priority,
chart_type,
is_plugin,
x_axis,
x_axis_ext,
y_axis,
y_axis_ext,
ext_stack,
ext_bubble,
custom_attr,
custom_style,
custom_filter,
drill_fields,
senior,
SNAPSHOT,
data_from,
refresh_view_enable,
refresh_unit,
refresh_time
from chart_view
WHERE chart_view.id = #{id}
</insert>
<insert id="copyCache">
INSERT INTO chart_view_cache (
id,
`name`,
title,
scene_id,
table_id,
`type`,
render,
result_count,
result_mode,
create_by,
create_time,
update_time,
style_priority,
chart_type,
is_plugin,
x_axis,
x_axis_ext,
y_axis,
y_axis_ext,
ext_stack,
ext_bubble,
custom_attr,
custom_style,
custom_filter,
drill_fields,
senior,
SNAPSHOT,
data_from
) SELECT
#{newViewId} as id,
`name`,
title,
scene_id,
table_id,
`type`,
render,
result_count,
result_mode,
create_by,
create_time,
update_time,
style_priority,
chart_type,
is_plugin,
x_axis,
x_axis_ext,
y_axis,
y_axis_ext,
ext_stack,
ext_bubble,
custom_attr,
custom_style,
custom_filter,
drill_fields,
senior,
SNAPSHOT,
data_from from chart_view_cache
WHERE
chart_view_cache.id = #{sourceViewId}
INSERT INTO chart_view_cache (id,
`name`,
title,
scene_id,
table_id,
`type`,
render,
result_count,
result_mode,
create_by,
create_time,
update_time,
style_priority,
chart_type,
is_plugin,
x_axis,
x_axis_ext,
y_axis,
y_axis_ext,
ext_stack,
ext_bubble,
custom_attr,
custom_style,
custom_filter,
drill_fields,
senior,
SNAPSHOT,
data_from,
refresh_view_enable,
refresh_unit,
refresh_time)
SELECT #{newViewId} as id,
`name`,
title,
scene_id,
table_id,
`type`,
render,
result_count,
result_mode,
create_by,
create_time,
update_time,
style_priority,
chart_type,
is_plugin,
x_axis,
x_axis_ext,
y_axis,
y_axis_ext,
ext_stack,
ext_bubble,
custom_attr,
custom_style,
custom_filter,
drill_fields,
senior,
SNAPSHOT,
data_from,
refresh_view_enable,
refresh_unit,
refresh_time
from chart_view_cache
WHERE chart_view_cache.id = #{sourceViewId}
</insert>
<insert id="initPanelChartViewCache">
INSERT INTO chart_view_cache (
id,
`name`,
title,
scene_id,
table_id,
`type`,
render,
result_count,
result_mode,
create_by,
create_time,
update_time,
style_priority,
chart_type,
is_plugin,
x_axis,
x_axis_ext,
y_axis,
y_axis_ext,
ext_stack,
ext_bubble,
custom_attr,
custom_style,
custom_filter,
drill_fields,
senior,
SNAPSHOT,
data_from
) SELECT
id,
`name`,
title,
scene_id,
table_id,
`type`,
render,
result_count,
result_mode,
create_by,
create_time,
update_time,
style_priority,
chart_type,
is_plugin,
x_axis,
x_axis_ext,
y_axis,
y_axis_ext,
ext_stack,
ext_bubble,
custom_attr,
custom_style,
custom_filter,
drill_fields,
senior,
SNAPSHOT,
data_from from chart_view
WHERE
chart_view.scene_id = #{panelId}
INSERT INTO chart_view_cache (id,
`name`,
title,
scene_id,
table_id,
`type`,
render,
result_count,
result_mode,
create_by,
create_time,
update_time,
style_priority,
chart_type,
is_plugin,
x_axis,
x_axis_ext,
y_axis,
y_axis_ext,
ext_stack,
ext_bubble,
custom_attr,
custom_style,
custom_filter,
drill_fields,
senior,
SNAPSHOT,
data_from,
refresh_view_enable,
refresh_unit,
refresh_time)
SELECT id,
`name`,
title,
scene_id,
table_id,
`type`,
render,
result_count,
result_mode,
create_by,
create_time,
update_time,
style_priority,
chart_type,
is_plugin,
x_axis,
x_axis_ext,
y_axis,
y_axis_ext,
ext_stack,
ext_bubble,
custom_attr,
custom_style,
custom_filter,
drill_fields,
senior,
SNAPSHOT,
data_from,
refresh_view_enable,
refresh_unit,
refresh_time
from chart_view
WHERE chart_view.scene_id = #{panelId}
</insert>
<select id="search" resultMap="BaseResultMapDTO">
@ -299,11 +308,11 @@
`senior`,
`data_from`)
SELECT #{newChartId},
GET_CHART_VIEW_COPY_NAME(#{oldChartId},#{panelId}) as `name`,
GET_CHART_VIEW_COPY_NAME(#{oldChartId}, #{panelId}) as `name`,
#{panelId},
`table_id`,
`type`,
GET_CHART_VIEW_COPY_NAME(#{oldChartId},#{panelId}) as `title`,
GET_CHART_VIEW_COPY_NAME(#{oldChartId}, #{panelId}) as `title`,
`x_axis`,
`x_axis_ext`,
`y_axis`,
@ -312,8 +321,8 @@
`custom_filter`,
`drill_fields`,
`create_by`,
unix_timestamp()*1000 as `create_time`,
unix_timestamp()*1000 as `update_time`,
unix_timestamp() * 1000 as `create_time`,
unix_timestamp() * 1000 as `update_time`,
`snapshot`,
`style_priority`,
`ext_stack`,
@ -405,13 +414,11 @@
SNAPSHOT,
senior,
data_from
FROM (
SELECT panel_id,
copy_from_view,
chart_view_id
FROM panel_view
WHERE copy_id = #{copyId}
) pv_copy
FROM (SELECT panel_id,
copy_from_view,
chart_view_id
FROM panel_view
WHERE copy_id = #{copyId}) pv_copy
INNER JOIN chart_view ON chart_view.id = pv_copy.copy_from_view
</insert>
@ -459,16 +466,11 @@
<select id="searchViewsWithPanelId" resultMap="BaseResultMapDTO">
SELECT * FROM chart_view
WHERE
id IN (
SELECT
chart_view_id
FROM
panel_view
WHERE
panel_id = #{panelId}
)
SELECT *
FROM chart_view
WHERE id IN (SELECT chart_view_id
FROM panel_view
WHERE panel_id = #{panelId})
</select>
<delete id="deleteCacheWithPanel">
@ -480,10 +482,12 @@
#{viewId}
</foreach>
</if>
</delete>
</delete>
<delete id="deleteViewCache">
delete from chart_view_cache where id = #{viewId}
</delete>
delete
from chart_view_cache
where id = #{viewId}
</delete>
<update id="copyCacheToView">
UPDATE chart_view cv,
@ -514,7 +518,10 @@
cv.drill_fields = cve.drill_fields,
cv.senior = cve.senior,
cv.SNAPSHOT = cve.SNAPSHOT,
cv.data_from = cve.data_from
cv.data_from = cve.data_from,
cv.refresh_view_enable = cve.refresh_view_enable,
cv.refresh_unit = cve.refresh_unit,
cv.refresh_time = cve.refresh_time
where cve.id = cv.id and cv.id in
<foreach collection="viewIds" item="viewId" open='(' separator=',' close=')'>
#{viewId}
@ -523,69 +530,75 @@
<update id="updateToCache">
UPDATE chart_view_cache cv,
chart_view cve
chart_view cve
SET cv.`name` = cve.`name`,
cv.title = cve.title,
cv.scene_id = cve.scene_id,
cv.table_id = cve.table_id,
cv.`type` = cve.`type`,
cv.render = cve.render,
cv.result_count = cve.result_count,
cv.result_mode = cve.result_mode,
cv.create_by = cve.create_by,
cv.create_time = cve.create_time,
cv.update_time = cve.update_time,
cv.style_priority = cve.style_priority,
cv.chart_type = cve.chart_type,
cv.is_plugin = cve.is_plugin,
cv.x_axis = cve.x_axis,
cv.x_axis_ext = cve.x_axis_ext,
cv.y_axis = cve.y_axis,
cv.y_axis_ext = cve.y_axis_ext,
cv.ext_stack = cve.ext_stack,
cv.ext_bubble = cve.ext_bubble,
cv.custom_attr = cve.custom_attr,
cv.custom_style = cve.custom_style,
cv.custom_filter = cve.custom_filter,
cv.drill_fields = cve.drill_fields,
cv.senior = cve.senior,
cv.SNAPSHOT = cve.SNAPSHOT,
cv.data_from = cve.data_from
where cve.id = cv.id and cv.id =#{viewId}
cv.title = cve.title,
cv.scene_id = cve.scene_id,
cv.table_id = cve.table_id,
cv.`type` = cve.`type`,
cv.render = cve.render,
cv.result_count = cve.result_count,
cv.result_mode = cve.result_mode,
cv.create_by = cve.create_by,
cv.create_time = cve.create_time,
cv.update_time = cve.update_time,
cv.style_priority = cve.style_priority,
cv.chart_type = cve.chart_type,
cv.is_plugin = cve.is_plugin,
cv.x_axis = cve.x_axis,
cv.x_axis_ext = cve.x_axis_ext,
cv.y_axis = cve.y_axis,
cv.y_axis_ext = cve.y_axis_ext,
cv.ext_stack = cve.ext_stack,
cv.ext_bubble = cve.ext_bubble,
cv.custom_attr = cve.custom_attr,
cv.custom_style = cve.custom_style,
cv.custom_filter = cve.custom_filter,
cv.drill_fields = cve.drill_fields,
cv.senior = cve.senior,
cv.SNAPSHOT = cve.SNAPSHOT,
cv.data_from = cve.data_from,
cv.refresh_view_enable = cve.refresh_view_enable,
cv.refresh_unit = cve.refresh_unit,
cv.refresh_time = cve.refresh_time
where cve.id = cv.id and cv.id =#{viewId}
</update>
<update id="updateToViewFromCache">
UPDATE chart_view_cache cve,
chart_view cv
chart_view cv
SET cv.`name` = cve.`name`,
cv.title = cve.title,
cv.scene_id = cve.scene_id,
cv.table_id = cve.table_id,
cv.`type` = cve.`type`,
cv.render = cve.render,
cv.result_count = cve.result_count,
cv.result_mode = cve.result_mode,
cv.create_by = cve.create_by,
cv.create_time = cve.create_time,
cv.update_time = cve.update_time,
cv.style_priority = cve.style_priority,
cv.chart_type = cve.chart_type,
cv.is_plugin = cve.is_plugin,
cv.x_axis = cve.x_axis,
cv.x_axis_ext = cve.x_axis_ext,
cv.y_axis = cve.y_axis,
cv.y_axis_ext = cve.y_axis_ext,
cv.ext_stack = cve.ext_stack,
cv.ext_bubble = cve.ext_bubble,
cv.custom_attr = cve.custom_attr,
cv.custom_style = cve.custom_style,
cv.custom_filter = cve.custom_filter,
cv.drill_fields = cve.drill_fields,
cv.senior = cve.senior,
cv.SNAPSHOT = cve.SNAPSHOT,
cv.data_from = cve.data_from
where cve.id = cv.id and cv.id =#{viewId}
cv.title = cve.title,
cv.scene_id = cve.scene_id,
cv.table_id = cve.table_id,
cv.`type` = cve.`type`,
cv.render = cve.render,
cv.result_count = cve.result_count,
cv.result_mode = cve.result_mode,
cv.create_by = cve.create_by,
cv.create_time = cve.create_time,
cv.update_time = cve.update_time,
cv.style_priority = cve.style_priority,
cv.chart_type = cve.chart_type,
cv.is_plugin = cve.is_plugin,
cv.x_axis = cve.x_axis,
cv.x_axis_ext = cve.x_axis_ext,
cv.y_axis = cve.y_axis,
cv.y_axis_ext = cve.y_axis_ext,
cv.ext_stack = cve.ext_stack,
cv.ext_bubble = cve.ext_bubble,
cv.custom_attr = cve.custom_attr,
cv.custom_style = cve.custom_style,
cv.custom_filter = cve.custom_filter,
cv.drill_fields = cve.drill_fields,
cv.senior = cve.senior,
cv.SNAPSHOT = cve.SNAPSHOT,
cv.data_from = cve.data_from,
cv.refresh_view_enable = cve.refresh_view_enable,
cv.refresh_unit = cve.refresh_unit,
cv.refresh_time = cve.refresh_time
where cve.id = cv.id and cv.id =#{viewId}
</update>
<delete id="deleteNoUseView">
@ -600,53 +613,49 @@
</delete>
<select id="chartOptions" resultType="io.dataease.dto.chart.ViewOption">
select id, title as name from chart_view where scene_id = #{panelId}
select id, title as name
from chart_view
where scene_id = #{panelId}
</select>
<insert id='chartFiledCopyWithPanel'>
INSERT INTO chart_view_field (
id,
table_id,
chart_id,
`name`,
dataease_name,
group_type,
`type`,
`size`,
de_type,
de_type_format,
de_extract_type,
ext_field,
`checked`,
column_index,
last_sync_time
) SELECT
uuid() AS id,
chart_view_field.table_id,
chart_view_field.pv_copy.chart_view_id AS chart_id,
chart_view_field.`name`,
chart_view_field.dataease_name,
chart_view_field.group_type,
chart_view_field.`type`,
chart_view_field.`size`,
chart_view_field.de_type,
chart_view_field.de_type_format,
chart_view_field.de_extract_type,
chart_view_field.ext_field,
chart_view_field.`checked`,
chart_view_field.column_index,
chart_view_field.last_sync_time
FROM
(
SELECT
panel_id,
copy_from_view,
chart_view_id
FROM
panel_view
WHERE
copy_id = #{copyId}
) pv_copy
INNER JOIN chart_view_field ON chart_view_field.chart_id = pv_copy.copy_from_view
INSERT INTO chart_view_field (id,
table_id,
chart_id,
origin_name,
`name`,
dataease_name,
group_type,
`type`,
`size`,
de_type,
de_type_format,
de_extract_type,
ext_field,
`checked`,
column_index,
last_sync_time)
SELECT uuid() AS id,
chart_view_field.table_id,
chart_view_field.pv_copy.chart_view_id AS chart_id,
chart_view_field.origin_name,
chart_view_field.`name`,
chart_view_field.dataease_name,
chart_view_field.group_type,
chart_view_field.`type`,
chart_view_field.`size`,
chart_view_field.de_type,
chart_view_field.de_type_format,
chart_view_field.de_extract_type,
chart_view_field.ext_field,
chart_view_field.`checked`,
chart_view_field.column_index,
chart_view_field.last_sync_time
FROM (SELECT panel_id,
copy_from_view,
chart_view_id
FROM panel_view
WHERE copy_id = #{copyId}) pv_copy
INNER JOIN chart_view_field ON chart_view_field.chart_id = pv_copy.copy_from_view
</insert>
</mapper>

View File

@ -21,6 +21,7 @@ public abstract class TaskHandler implements InitializingBean {
if (CronUtils.taskExpire(endTime)) { // 过期了就删除任务
return;
}
if (!taskEntity.getStatus()) return;
JobKey jobKey = new JobKey(taskEntity.getTaskId().toString());
TriggerKey triggerKey = new TriggerKey(taskEntity.getTaskId().toString());
Date start = new Date(taskEntity.getStartTime());

View File

@ -94,7 +94,7 @@ public class EmailTaskHandler extends TaskHandler implements Job {
Boolean isTempTask = (Boolean) jobDataMap.getOrDefault(IS_TEMP_TASK, false);
GlobalTaskEntity taskEntity = (GlobalTaskEntity) jobDataMap.get("taskEntity");
ScheduleManager scheduleManager = SpringContextUtil.getBean(ScheduleManager.class);
if (!isTempTask && CronUtils.taskExpire(taskEntity.getEndTime())) {
if (!isTempTask && (CronUtils.taskExpire(taskEntity.getEndTime()) || !taskEntity.getStatus())) {
removeTask(scheduleManager, taskEntity);
return;
}
@ -167,7 +167,7 @@ public class EmailTaskHandler extends TaskHandler implements Job {
try {
XpackEmailTemplateDTO emailTemplateDTO = emailXpackService.emailTemplate(taskInstance.getTaskId());
XpackEmailTaskRequest taskForm = emailXpackService.taskForm(taskInstance.getTaskId());
if (ObjectUtils.isEmpty(taskForm) || (!isTempTask && CronUtils.taskExpire(taskForm.getEndTime()))) {
if (ObjectUtils.isEmpty(taskForm) || (!isTempTask && (CronUtils.taskExpire(taskForm.getEndTime()) || !taskForm.getStatus()))) {
removeInstance(taskInstance);
return;
}

View File

@ -0,0 +1,20 @@
package io.dataease.plugins.entity;
import io.dataease.plugins.common.base.domain.MyPlugin;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class PluginOperate implements Serializable {
private String type;
private MyPlugin plugin;
private String senderIp;
}

View File

@ -115,6 +115,11 @@ public class XDingtalkServer {
DeLogUtils.save(SysLogConstants.OPERATE_TYPE.LOGIN, SysLogConstants.SOURCE_TYPE.USER, sysUserEntity.getUserId(), null, null, null);
Cookie cookie_token = new Cookie("Authorization", token);
if (withoutLogin) {
Cookie platformCookie = new Cookie("inOtherPlatform", "true");
platformCookie.setPath("/");
response.addCookie(platformCookie);
}
cookie_token.setPath("/");
response.addCookie(cookie_token);

View File

@ -80,7 +80,7 @@ public class XEmailTaskServer {
List<XpackTaskGridDTO> tasks = emailXpackService.taskGrid(request);
if (CollectionUtils.isNotEmpty(tasks)) {
tasks.forEach(item -> {
if (CronUtils.taskExpire(item.getEndTime())) {
if (CronUtils.taskExpire(item.getEndTime()) || !item.getStatus()) {
item.setNextExecTime(null);
} else {
GlobalTaskEntity globalTaskEntity = new GlobalTaskEntity();
@ -110,8 +110,16 @@ public class XEmailTaskServer {
EmailXpackService emailXpackService = SpringContextUtil.getBean(EmailXpackService.class);
XpackEmailTaskRequest request = emailXpackService.taskForm(taskId);
GlobalTaskEntity globalTaskEntity = BeanUtils.copyBean(new GlobalTaskEntity(), request);
Boolean invalid = false;
if (CronUtils.taskExpire(globalTaskEntity.getEndTime())) {
globalTaskEntity.setEndTime(null);
invalid = true;
}
if (!globalTaskEntity.getStatus()) {
globalTaskEntity.setStatus(true);
invalid = true;
}
if (invalid) {
scheduleService.addTempSchedule(globalTaskEntity);
return;
}
@ -270,6 +278,12 @@ public class XEmailTaskServer {
emailXpackService.stop(taskId);
}
@PostMapping("/start/{taskId}")
public Boolean start(@PathVariable Long taskId) throws Exception {
EmailXpackService emailXpackService = SpringContextUtil.getBean(EmailXpackService.class);
return emailXpackService.start(taskId);
}
@PostMapping("/queryInstancies/{goPage}/{pageSize}")
public Pager<List<XpackTaskInstanceDTO>> instancesGrid(@PathVariable int goPage, @PathVariable int pageSize,
@RequestBody XpackGridRequest request) {

View File

@ -141,6 +141,11 @@ public class XLarkServer {
cookie_token.setPath("/");
response.addCookie(cookie_token);
if (withoutLogin) {
Cookie platformCookie = new Cookie("inOtherPlatform", "true");
platformCookie.setPath("/");
response.addCookie(platformCookie);
}
} catch (Exception e) {
String msg = e.getMessage();

View File

@ -558,6 +558,12 @@ public class ChartViewService {
return data;
}
public Boolean containDetailField(ChartViewDTO view) {
List<String> detailFieldViewTypes = new ArrayList<>();
detailFieldViewTypes.add("map");
return detailFieldViewTypes.contains(view.getType());
}
public ChartViewDTO calcData(ChartViewDTO view, ChartExtRequest chartExtRequest, boolean cache) throws Exception {
ChartViewDTO chartViewDTO = new ChartViewDTO();
if (ObjectUtils.isEmpty(view)) {
@ -906,6 +912,9 @@ public class ChartViewService {
pageInfo.setGoPage(chartExtRequest.getGoPage());
pageInfo.setPageSize(chartExtRequest.getPageSize());
List<ChartViewFieldDTO> detailFieldList = new ArrayList<>();
String detailFieldSql = null;
List<String[]> detailData = new ArrayList<>();
//如果不是插件视图 走原生逻辑
if (table.getMode() == 0) {// 直连
if (ObjectUtils.isEmpty(ds)) {
@ -931,6 +940,11 @@ public class ChartViewService {
totalPageSql = qp.getResultCount(true, dataTableInfoDTO.getTable(), xAxis, fieldCustomFilter, rowPermissionsTree, extFilterList, ds, view);
} else {
querySql = qp.getSQL(dataTableInfoDTO.getTable(), xAxis, yAxis, fieldCustomFilter, rowPermissionsTree, extFilterList, ds, view);
if (containDetailField(view) && CollectionUtils.isNotEmpty(viewFields)) {
detailFieldList.addAll(xAxis);
detailFieldList.addAll(viewFields);
detailFieldSql = qp.getSQLWithPage(true, dataTableInfoDTO.getTable(), detailFieldList, fieldCustomFilter, rowPermissionsTree, extFilterList, ds, view, pageInfo);
}
}
} else if (StringUtils.equalsIgnoreCase(table.getType(), DatasetType.SQL.name())) {
String sql = dataTableInfoDTO.isBase64Encryption() ? new String(java.util.Base64.getDecoder().decode(dataTableInfoDTO.getSql())) : dataTableInfoDTO.getSql();
@ -946,6 +960,11 @@ public class ChartViewService {
totalPageSql = qp.getResultCount(false, sql, xAxis, fieldCustomFilter, rowPermissionsTree, extFilterList, ds, view);
} else {
querySql = qp.getSQLAsTmp(sql, xAxis, yAxis, fieldCustomFilter, rowPermissionsTree, extFilterList, view);
if (containDetailField(view) && CollectionUtils.isNotEmpty(viewFields)) {
detailFieldList.addAll(xAxis);
detailFieldList.addAll(viewFields);
detailFieldSql = qp.getSQLWithPage(false, sql, detailFieldList, fieldCustomFilter, rowPermissionsTree, extFilterList, ds, view, pageInfo);
}
}
} else if (StringUtils.equalsIgnoreCase(table.getType(), DatasetType.CUSTOM.name())) {
DataTableInfoDTO dt = gson.fromJson(table.getInfo(), DataTableInfoDTO.class);
@ -962,6 +981,11 @@ public class ChartViewService {
totalPageSql = qp.getResultCount(false, sql, xAxis, fieldCustomFilter, rowPermissionsTree, extFilterList, ds, view);
} else {
querySql = qp.getSQLAsTmp(sql, xAxis, yAxis, fieldCustomFilter, rowPermissionsTree, extFilterList, view);
if (containDetailField(view) && CollectionUtils.isNotEmpty(viewFields)) {
detailFieldList.addAll(xAxis);
detailFieldList.addAll(viewFields);
detailFieldSql = qp.getSQLWithPage(false, sql, detailFieldList, fieldCustomFilter, rowPermissionsTree, extFilterList, ds, view, pageInfo);
}
}
} else if (StringUtils.equalsIgnoreCase(table.getType(), DatasetType.UNION.name())) {
DataTableInfoDTO dt = gson.fromJson(table.getInfo(), DataTableInfoDTO.class);
@ -978,6 +1002,11 @@ public class ChartViewService {
totalPageSql = qp.getResultCount(false, sql, xAxis, fieldCustomFilter, rowPermissionsTree, extFilterList, ds, view);
} else {
querySql = qp.getSQLAsTmp(sql, xAxis, yAxis, fieldCustomFilter, rowPermissionsTree, extFilterList, view);
if (containDetailField(view) && CollectionUtils.isNotEmpty(viewFields)) {
detailFieldList.addAll(xAxis);
detailFieldList.addAll(viewFields);
detailFieldSql = qp.getSQLWithPage(false, sql, detailFieldList, fieldCustomFilter, rowPermissionsTree, extFilterList, ds, view, pageInfo);
}
}
}
if (StringUtils.isNotEmpty(totalPageSql) && StringUtils.equalsIgnoreCase((String) mapSize.get("tablePageMode"), "page")) {
@ -994,6 +1023,11 @@ public class ChartViewService {
logger.info(datasourceAssistRequest.getQuery());
assistData = datasourceProvider.getData(datasourceAssistRequest);
}
if (StringUtils.isNotBlank(detailFieldSql)) {
datasourceRequest.setQuery(detailFieldSql);
detailData = datasourceProvider.getData(datasourceRequest);
}
} else if (table.getMode() == 1) {// 抽取
// 连接doris构建doris数据源查询
datasourceRequest.setDatasource(ds);
@ -1010,6 +1044,11 @@ public class ChartViewService {
datasourceRequest.setQuery(qp.getSQLTableInfo(tableName, xAxis, fieldCustomFilter, rowPermissionsTree, extFilterList, ds, view));
} else {
datasourceRequest.setQuery(qp.getSQL(tableName, xAxis, yAxis, fieldCustomFilter, rowPermissionsTree, extFilterList, ds, view));
if (containDetailField(view) && CollectionUtils.isNotEmpty(viewFields)) {
detailFieldList.addAll(xAxis);
detailFieldList.addAll(viewFields);
detailFieldSql = qp.getSQLTableInfo(tableName, detailFieldList, fieldCustomFilter, rowPermissionsTree, extFilterList, ds, view);
}
}
if (CollectionUtils.isNotEmpty(assistFields)) {
datasourceAssistRequest.setQuery(assistSQL(datasourceRequest.getQuery(), assistFields));
@ -1036,6 +1075,10 @@ public class ChartViewService {
}
}
}
if (StringUtils.isNotBlank(detailFieldSql)) {
datasourceRequest.setQuery(detailFieldSql);
detailData = datasourceProvider.getData(datasourceRequest);
}
}
// 自定义排序
if (StringUtils.containsIgnoreCase(view.getType(), "stack")) {
@ -1199,7 +1242,12 @@ public class ChartViewService {
}
}
// table组件明细表也用于导出数据
Map<String, Object> mapTableNormal = ChartDataBuild.transTableNormal(xAxis, yAxis, view, data, extStack, desensitizationList);
Map<String, Object> mapTableNormal = null;
if (CollectionUtils.isNotEmpty(detailData)) {
mapTableNormal = ChartDataBuild.transTableNormalWithDetail(xAxis, yAxis, data, detailFieldList, detailData, desensitizationList);
} else {
mapTableNormal = ChartDataBuild.transTableNormal(xAxis, yAxis, view, data, extStack, desensitizationList);
}
chartViewDTO = uniteViewResult(datasourceRequest.getQuery(), mapChart, mapTableNormal, view, isDrill, drillFilters, dynamicAssistFields, assistData);
chartViewDTO.setTotalPage(totalPage);
chartViewDTO.setTotalItems(totalItems);

View File

@ -1,5 +1,6 @@
package io.dataease.service.chart.util;
import cn.hutool.core.util.ArrayUtil;
import io.dataease.plugins.common.base.domain.ChartViewWithBLOBs;
import io.dataease.dto.chart.*;
import io.dataease.plugins.common.dto.chart.ChartViewFieldDTO;
@ -14,6 +15,9 @@ import java.util.*;
import java.util.stream.Collectors;
public class ChartDataBuild {
private final static String format = "(%s)";
// AntV
public static Map<String, Object> transChartDataAntV(List<ChartViewFieldDTO> xAxis, List<ChartViewFieldDTO> yAxis, ChartViewWithBLOBs view, List<String[]> data, boolean isDrill) {
Map<String, Object> map = new HashMap<>();
@ -952,6 +956,46 @@ public class ChartDataBuild {
return transTableNormal(fields, view, data, desensitizationList);
}
public static Map<String, Object> transTableNormalWithDetail(List<ChartViewFieldDTO> xAxis, List<ChartViewFieldDTO> yAxis, List<String[]> data, List<ChartViewFieldDTO> detailFields, List<String[]> detailData, Map<String, ColumnPermissionItem> desensitizationList) {
int detailIndex = xAxis.size();
List<ChartViewFieldDTO> realDetailFields = detailFields.subList(detailIndex, detailFields.size());
List<ChartViewFieldDTO> fields = new ArrayList<>();
if (CollectionUtils.isNotEmpty(xAxis))
fields.addAll(xAxis);
if (CollectionUtils.isNotEmpty(yAxis))
fields.addAll(yAxis);
Map<String, Object> map = transTableNormal(fields, null, data, desensitizationList);
List<Map<String, Object>> tableRow = (List<Map<String, Object>>) map.get("tableRow");
final int xEndIndex = detailIndex;
Map<String, List<String[]>> groupDataList = detailData.stream().collect(Collectors.groupingBy(item -> ArrayUtil.join(ArrayUtil.sub(item, 0, xEndIndex), "-de-", "(", ")")));
tableRow.forEach(row -> {
String key = xAxis.stream().map(x -> String.format(format, row.get(x.getDataeaseName()).toString())).collect(Collectors.joining("-de-"));
List<String[]> detailFieldValueList = groupDataList.get(key);
List<Map<String, Object>> detailValueMapList = detailFieldValueList.stream().map((detailArr -> {
Map<String, Object> temp = new HashMap<>();
for (int i = 0; i < realDetailFields.size(); i++) {
ChartViewFieldDTO realDetailField = realDetailFields.get(i);
temp.put(realDetailField.getDataeaseName(), detailArr[detailIndex + i]);
}
return temp;
})).collect(Collectors.toList());
row.put("details", detailValueMapList);
});
ChartViewFieldDTO detailFieldDTO = new ChartViewFieldDTO();
detailFieldDTO.setId("DataEase-Detail");
detailFieldDTO.setName("detail");
detailFieldDTO.setDataeaseName("detail");
fields.add(detailFieldDTO);
map.put("fields", fields);
map.put("detailFields", realDetailFields);
map.put("tableRow", tableRow);
return map;
}
// 表格
public static Map<String, Object> transTableNormal(Map<String, List<ChartViewFieldDTO>> fieldMap, ChartViewWithBLOBs view, List<String[]> data, Map<String, ColumnPermissionItem> desensitizationList) {
@ -1014,7 +1058,7 @@ public class ChartDataBuild {
if (StringUtils.isEmpty(originStr) || originStr.length() <= columnPermissionItem.getDesensitizationRule().getM() + columnPermissionItem.getDesensitizationRule().getN() + 1) {
desensitizationStr = String.join("", Collections.nCopies(columnPermissionItem.getDesensitizationRule().getM(), "X")) + "***" + String.join("", Collections.nCopies(columnPermissionItem.getDesensitizationRule().getN(), "X"));
} else {
desensitizationStr = StringUtils.substring(originStr, 0, columnPermissionItem.getDesensitizationRule().getM() - 1) + "***" + StringUtils.substring(originStr, originStr.length() - columnPermissionItem.getDesensitizationRule().getN(), originStr.length() - 1);
desensitizationStr = StringUtils.substring(originStr, 0, columnPermissionItem.getDesensitizationRule().getM()) + "***" + StringUtils.substring(originStr, originStr.length() - columnPermissionItem.getDesensitizationRule().getN() - 1, originStr.length() - 1);
}
break;
case RetainMToN:

View File

@ -1,8 +1,6 @@
package io.dataease.service.dataset;
import io.dataease.dto.dataset.DeSortDTO;
import java.util.List;
@ -14,4 +12,6 @@ public interface DataSetFieldService {
List<Object> fieldValues(String fieldId, DeSortDTO sortDTO, Long userId, Boolean userPermissions, Boolean rowAndColumnMgm) throws Exception;
List<Object> fieldValues(List<String> fieldIds, DeSortDTO sortDTO, Long userId, Boolean userPermissions, Boolean needMapping, Boolean rowAndColumnMgm) throws Exception;
List<Object> chineseSort(List<Object> list, DeSortDTO sortDTO) throws Exception;
}

View File

@ -967,26 +967,15 @@ public class DataSetTableService {
return map;
}
public List<SqlVariableDetails> paramsWithIds(String type, List<String> viewIds) {
if (CollectionUtils.isEmpty(viewIds)) {
return new ArrayList<>();
}
public List<SqlVariableDetails> datasetParams(String type, String id) {
if (!Arrays.asList("DATE", "TEXT", "NUM").contains(type)) {
return new ArrayList<>();
}
ChartViewExample chartViewExample = new ChartViewExample();
chartViewExample.createCriteria().andIdIn(viewIds);
List<String> datasetIds = chartViewMapper.selectByExample(chartViewExample).stream().map(ChartView::getTableId).collect(Collectors.toList());
if (CollectionUtils.isEmpty(datasetIds)) {
return new ArrayList<>();
}
DatasetTableExample datasetTableExample = new DatasetTableExample();
datasetTableExample.createCriteria().andIdIn(datasetIds);
List<DatasetTable> datasetTables = datasetTableMapper.selectByExample(datasetTableExample);
if (CollectionUtils.isEmpty(datasetTables)) {
return new ArrayList<>();
}
DatasetTable datasetTable = datasetTableMapper.selectByPrimaryKey(id);
return getSqlVariableDetails(type, Arrays.asList(datasetTable));
}
private List<SqlVariableDetails> getSqlVariableDetails(String type, List<DatasetTable> datasetTables) {
List<SqlVariableDetails> sqlVariableDetails = new ArrayList<>();
for (DatasetTable datasetTable : datasetTables) {
if (StringUtils.isNotEmpty(datasetTable.getSqlVariableDetails())) {
@ -999,6 +988,7 @@ public class DataSetTableService {
}
}
}
switch (type) {
case "DATE":
sqlVariableDetails = sqlVariableDetails.stream().filter(item -> item.getType().get(0).contains("DATETIME")).collect(Collectors.toList());
@ -1022,6 +1012,29 @@ public class DataSetTableService {
return sqlVariableDetails;
}
public List<SqlVariableDetails> paramsWithIds(String type, List<String> viewIds) {
if (CollectionUtils.isEmpty(viewIds)) {
return new ArrayList<>();
}
if (!Arrays.asList("DATE", "TEXT", "NUM").contains(type)) {
return new ArrayList<>();
}
ChartViewExample chartViewExample = new ChartViewExample();
chartViewExample.createCriteria().andIdIn(viewIds);
List<String> datasetIds = chartViewMapper.selectByExample(chartViewExample).stream().map(ChartView::getTableId).collect(Collectors.toList());
if (CollectionUtils.isEmpty(datasetIds)) {
return new ArrayList<>();
}
DatasetTableExample datasetTableExample = new DatasetTableExample();
datasetTableExample.createCriteria().andIdIn(datasetIds);
List<DatasetTable> datasetTables = datasetTableMapper.selectByExample(datasetTableExample);
if (CollectionUtils.isEmpty(datasetTables)) {
return new ArrayList<>();
}
return getSqlVariableDetails(type, datasetTables);
}
public void checkVariable(final String sql, String dsType) throws Exception {
String tmpSql = removeVariables(sql, dsType);

View File

@ -1,5 +1,6 @@
package io.dataease.service.dataset.impl.direct;
import cn.hutool.core.collection.CollectionUtil;
import com.google.gson.Gson;
import io.dataease.commons.exception.DEException;
import io.dataease.commons.model.BaseTreeNode;
@ -32,6 +33,7 @@ import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.text.Collator;
import java.util.*;
import java.util.stream.Collectors;
@ -77,6 +79,26 @@ public class DirectFieldService implements DataSetFieldService {
}).collect(Collectors.toList());
}
@Override
public List<Object> chineseSort(List<Object> list, DeSortDTO sortDTO) throws Exception {
if (ObjectUtils.isEmpty(sortDTO) || CollectionUtil.isEmpty(list)) return list;
String sort = sortDTO.getSort();
if (!StringUtils.equals(sort, "chinese")) {
return list;
}
String id = sortDTO.getId();
String sortStr = StringUtils.equalsIgnoreCase("chineseDesc", id) ? "desc" : "asc";
List<Object> result = CollectionUtil.sort(list, (v1, v2) -> {
Collator instance = Collator.getInstance(Locale.CHINESE);
if (StringUtils.equals("desc", sortStr)) {
return instance.compare(v2, v1);
}
return instance.compare(v1, v2);
});
return result;
}
@Override
public List<Object> fieldValues(List<String> fieldIds, DeSortDTO sortDTO, Long userId, Boolean userPermissions, Boolean needMapping, Boolean rowAndColumnMgm) throws Exception {
String fieldId = fieldIds.get(0);
@ -146,7 +168,7 @@ public class DirectFieldService implements DataSetFieldService {
datasourceRequest.setQuery(qp.createQuerySQL(dataTableInfoDTO.getTable(), permissionFields, !needSort, ds, customFilter, rowPermissionsTree, deSortFields));
} else if (StringUtils.equalsIgnoreCase(datasetTable.getType(), DatasetType.SQL.toString())) {
String sql = dataTableInfoDTO.getSql();
if(dataTableInfoDTO.isBase64Encryption()){
if (dataTableInfoDTO.isBase64Encryption()) {
sql = new String(java.util.Base64.getDecoder().decode(sql));
}
sql = dataSetTableService.removeVariables(sql, ds.getType());

View File

@ -104,11 +104,13 @@ public class DatasourceService {
@DeCleaner(DePermissionType.DATASOURCE)
@Transactional(rollbackFor = Exception.class)
public Datasource addDatasource(Datasource datasource) throws Exception {
public Datasource addDatasource(DatasourceDTO datasource) throws Exception {
if (!types().stream().map(DataSourceType::getType).collect(Collectors.toList()).contains(datasource.getType())) {
throw new Exception("Datasource type not supported.");
}
if(datasource.isConfigurationEncryption()){
datasource.setConfiguration(new String(java.util.Base64.getDecoder().decode(datasource.getConfiguration())));
}
Provider datasourceProvider = ProviderFactory.getProvider(datasource.getType());
datasourceProvider.checkConfiguration(datasource);
@ -212,6 +214,14 @@ public class DatasourceService {
}
}
}
if(StringUtils.isNotEmpty(datasourceDTO.getConfiguration())){
datasourceDTO.setConfiguration(new String(java.util.Base64.getEncoder().encode(datasourceDTO.getConfiguration().getBytes())));
}
if(CollectionUtils.isNotEmpty(datasourceDTO.getApiConfiguration())){
String config = new Gson().toJson(datasourceDTO.getApiConfiguration());
datasourceDTO.setApiConfigurationStr(new String(java.util.Base64.getEncoder().encode(config.getBytes())));
datasourceDTO.setApiConfiguration(null);
}
}
public DatasourceDTO getDataSourceDetails(String datasourceId){
@ -253,6 +263,9 @@ public class DatasourceService {
if (!types().stream().map(DataSourceType::getType).collect(Collectors.toList()).contains(updataDsRequest.getType())) {
throw new Exception("Datasource type not supported.");
}
if(updataDsRequest.isConfigurationEncryption()){
updataDsRequest.setConfiguration(new String(java.util.Base64.getDecoder().decode(updataDsRequest.getConfiguration())));
}
checkName(updataDsRequest.getName(), updataDsRequest.getType(), updataDsRequest.getId());
Datasource datasource = new Datasource();
datasource.setName(updataDsRequest.getName());
@ -261,15 +274,22 @@ public class DatasourceService {
datasource.setCreateTime(null);
datasource.setType(updataDsRequest.getType());
datasource.setUpdateTime(System.currentTimeMillis());
Provider datasourceProvider = ProviderFactory.getProvider(updataDsRequest.getType());
datasourceProvider.checkConfiguration(datasource);
checkAndUpdateDatasourceStatus(datasource);
DatasourceExample example = new DatasourceExample();
example.createCriteria().andIdEqualTo(updataDsRequest.getId());
datasourceMapper.updateByExampleSelective(datasource, example);
handleConnectionPool(updataDsRequest.getId());
if(StringUtils.isNotEmpty(updataDsRequest.getId())){
DatasourceExample example = new DatasourceExample();
example.createCriteria().andIdEqualTo(updataDsRequest.getId());
datasourceMapper.updateByExampleSelective(datasource, example);
handleConnectionPool(updataDsRequest.getId());
}else {
datasource.setId(UUID.randomUUID().toString());
datasource.setCreateTime(System.currentTimeMillis());
datasourceMapper.insert(datasource);
handleConnectionPool(datasource, "add");
sysAuthService.copyAuth(datasource.getId(), SysAuthConstants.AUTH_SOURCE_TYPE_DATASOURCE);
}
}
private void handleConnectionPool(String datasourceId) {
@ -283,7 +303,10 @@ public class DatasourceService {
}
}
public ResultHolder validate(Datasource datasource) throws Exception {
public ResultHolder validate(DatasourceDTO datasource) throws Exception {
if(datasource.isConfigurationEncryption()){
datasource.setConfiguration(new String(java.util.Base64.getDecoder().decode(datasource.getConfiguration())));
}
DatasourceDTO datasourceDTO = new DatasourceDTO();
BeanUtils.copyBean(datasourceDTO, datasource);
try {
@ -371,7 +394,10 @@ public class DatasourceService {
}
}
public List<String> getSchema(Datasource datasource) throws Exception {
public List<String> getSchema(DatasourceDTO datasource) throws Exception {
if(datasource.isConfigurationEncryption()){
datasource.setConfiguration(new String(java.util.Base64.getDecoder().decode(datasource.getConfiguration())));
}
Provider datasourceProvider = ProviderFactory.getProvider(datasource.getType());
DatasourceRequest datasourceRequest = new DatasourceRequest();
datasourceRequest.setDatasource(datasource);

View File

@ -11,6 +11,7 @@ import io.dataease.controller.request.dataset.DataSetTableRequest;
import io.dataease.controller.request.panel.PanelAppTemplateApplyRequest;
import io.dataease.controller.request.panel.PanelAppTemplateRequest;
import io.dataease.controller.request.panel.PanelGroupRequest;
import io.dataease.dto.DatasourceDTO;
import io.dataease.ext.ExtPanelAppTemplateMapper;
import io.dataease.plugins.common.base.domain.*;
import io.dataease.plugins.common.base.mapper.PanelAppTemplateMapper;
@ -137,13 +138,18 @@ public class PanelAppTemplateService {
}
@Transactional(rollbackFor = Exception.class)
public Map<String, String> applyDatasource(List<Datasource> oldDatasourceList, List<Datasource> newDatasourceList) throws Exception {
public Map<String, String> applyDatasource(List<Datasource> oldDatasourceList, PanelAppTemplateApplyRequest request) throws Exception {
Map<String, String> datasourceRealMap = new HashMap<>();
for (int i = 0; i < newDatasourceList.size(); i++) {
Datasource datasource = newDatasourceList.get(0);
datasource.setId(null);
Datasource newDatasource = datasourceService.addDatasource(datasource);
datasourceRealMap.put(oldDatasourceList.get(i).getId(), newDatasource.getId());
if (PanelConstants.APP_DATASOURCE_FROM.HISTORY.equals(request.getDatasourceFrom())) {
datasourceRealMap.put(oldDatasourceList.get(0).getId(), request.getDatasourceHistoryId());
} else {
List<DatasourceDTO> newDatasourceList = request.getDatasourceList();
for (int i = 0; i < newDatasourceList.size(); i++) {
DatasourceDTO datasource = newDatasourceList.get(0);
datasource.setId(null);
Datasource newDatasource = datasourceService.addDatasource(datasource);
datasourceRealMap.put(oldDatasourceList.get(i).getId(), newDatasource.getId());
}
}
return datasourceRealMap;
}
@ -366,24 +372,28 @@ public class PanelAppTemplateService {
datasetGroup.setPid(request.getDatasetGroupPid());
datasetGroup.setName(request.getDatasetGroupName());
dataSetGroupService.checkName(datasetGroup);
request.getDatasourceList().stream().forEach(datasource -> {
datasourceService.checkName(datasource.getName(), datasource.getType(), null);
});
if (PanelConstants.APP_DATASOURCE_FROM.NEW.equals(request.getDatasourceFrom())) {
request.getDatasourceList().stream().forEach(datasource -> {
datasourceService.checkName(datasource.getName(), datasource.getType(), null);
});
}
} else {
DatasetGroup datasetGroup = new DatasetGroup();
datasetGroup.setPid(request.getDatasetGroupPid());
datasetGroup.setName(request.getDatasetGroupName());
datasetGroup.setId(request.getDatasetGroupId());
dataSetGroupService.checkName(datasetGroup);
request.getDatasourceList().stream().forEach(datasource -> {
datasourceService.checkName(datasource.getName(), datasource.getType(), datasource.getId());
});
if (PanelConstants.APP_DATASOURCE_FROM.NEW.equals(request.getDatasourceFrom())) {
request.getDatasourceList().stream().forEach(datasource -> {
datasourceService.checkName(datasource.getName(), datasource.getType(), datasource.getId());
});
}
}
}
@Transactional(rollbackFor = Exception.class)
public void editDatasource(List<Datasource> updateDatasourceList) throws Exception {
public void editDatasource(List<DatasourceDTO> updateDatasourceList) throws Exception {
for (int i = 0; i < updateDatasourceList.size(); i++) {
UpdataDsRequest updataDsRequest = new UpdataDsRequest();
BeanUtils.copyBean(updataDsRequest, updateDatasourceList.get(i));

View File

@ -898,7 +898,7 @@ public class PanelGroupService {
List<PanelView> panelViewsInfo = gson.fromJson(appInfo.getPanelViewsInfo(), new TypeToken<List<PanelView>>() {
}.getType());
Map<String, String> datasourceRealMap = panelAppTemplateService.applyDatasource(oldDatasourceInfo, request.getDatasourceList());
Map<String, String> datasourceRealMap = panelAppTemplateService.applyDatasource(oldDatasourceInfo, request);
Map<String, String> datasetsRealMap = panelAppTemplateService.applyDataset(datasetTablesInfo, datasourceRealMap, asideDatasetGroupId);
@ -909,7 +909,7 @@ public class PanelGroupService {
Map<String, String> datasetFieldsRealMap = panelAppTemplateService.applyDatasetField(datasetTableFieldsInfo, datasetsRealMap, datasetTypeRealMap, datasetFieldsMd5FormatRealMap);
panelAppTemplateService.createDorisTable(datasetTablesInfo);
panelAppTemplateService.resetCustomAndUnionDataset(datasetTablesInfo, datasetsRealMap, datasetFieldsRealMap);
Map<String, String> chartViewsRealMap = panelAppTemplateService.applyViews(chartViewsInfo, datasetsRealMap, datasetFieldsRealMap, datasetFieldsMd5FormatRealMap, newPanelId);
@ -922,17 +922,19 @@ public class PanelGroupService {
String newDatasourceId = datasourceRealMap.entrySet().stream().findFirst().get().getValue();
String newDatasourceName = request.getDatasourceList().get(0).getName();
PanelAppTemplateLog templateLog = new PanelAppTemplateLog();
templateLog.setPanelId(newPanelId);
templateLog.setSourcePanelName(request.getPanelName());
templateLog.setDatasourceId(newDatasourceId);
templateLog.setSourceDatasourceName(newDatasourceName);
if (PanelConstants.APP_DATASOURCE_FROM.NEW.equals(request.getDatasourceFrom())) {
templateLog.setSourceDatasourceName(request.getDatasourceList().get(0).getName());
}
templateLog.setDatasetGroupId(asideDatasetGroupId);
templateLog.setSourceDatasetGroupName(request.getDatasetGroupName());
templateLog.setAppTemplateId(appInfo.getId());
templateLog.setAppTemplateName(appInfo.getName());
templateLog.setDatasourceFrom(request.getDatasourceFrom());
appTemplateLogService.newAppApplyLog(templateLog);
return newPanelId;
}

View File

@ -1,13 +1,57 @@
package io.dataease.service.redis.impl;
import com.google.gson.Gson;
import io.dataease.commons.utils.IPUtils;
import io.dataease.commons.utils.LogUtil;
import io.dataease.plugins.common.base.domain.MyPlugin;
import io.dataease.plugins.entity.PluginOperate;
import io.dataease.service.redis.RedisMessageBroadcast;
import io.dataease.service.sys.PluginService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
@Service
public class PluginMsgService implements RedisMessageBroadcast {
private static Gson json = new Gson();
@Resource
private PluginService pluginService;
@Override
public void messageCallBack(Object arg) {
PluginOperate operate = json.fromJson(json.toJson(arg), PluginOperate.class);
String domain = IPUtils.domain();
if (StringUtils.equals(domain, operate.getSenderIp())) return;
String operateType = operate.getType();
MyPlugin plugin = operate.getPlugin();
if (StringUtils.equals("install", operateType)) {
LogUtil.info("start install plugin [{}] in domain {}", plugin.getName(), domain);
install(plugin);
}
if (StringUtils.equals("uninstall", operateType)) {
LogUtil.info("start uninstall plugin [{}] in domain {}", plugin.getName(), domain);
uninstall(plugin);
}
if (StringUtils.equals("update", operateType)) {
LogUtil.info("start update plugin [{}] in domain {}", plugin.getName(), domain);
updateInstall(plugin);
}
}
private void install(MyPlugin plugin) {
pluginService.redisBroadcastInstall(plugin);
}
private void uninstall(MyPlugin plugin) {
pluginService.redisBroadcastUnInstall(plugin);
}
private void updateInstall(MyPlugin plugin) {
if (pluginService.redisBroadcastUnInstall(plugin)) {
pluginService.redisBroadcastInstall(plugin);
}
}
}

View File

@ -0,0 +1,32 @@
package io.dataease.service.sys;
import io.dataease.commons.condition.RedisStatusCondition;
import io.dataease.commons.constants.RedisConstants;
import io.dataease.commons.model.RedisMessage;
import io.dataease.plugins.entity.PluginOperate;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.annotation.Conditional;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
@Component
@Conditional({RedisStatusCondition.class})
public class DistributedPluginService {
@Resource
private RedisTemplate redisTemplate;
public void pushBroadcast(PluginOperate operate) {
if (ObjectUtils.isEmpty(operate) || ObjectUtils.isEmpty(operate.getPlugin()) || StringUtils.isBlank(operate.getSenderIp()))
return;
RedisMessage<PluginOperate> msg = new RedisMessage();
msg.setType(RedisConstants.PLUGIN_INSTALL_MSG);
msg.setData(operate);
redisTemplate.convertAndSend(RedisConstants.GLOBAL_REDIS_TOPIC, msg);
}
}

View File

@ -3,6 +3,7 @@ package io.dataease.service.sys;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.ZipUtil;
import com.google.gson.Gson;
import io.dataease.commons.utils.IPUtils;
import io.dataease.dto.MyPluginDTO;
import io.dataease.ext.ExtSysPluginMapper;
import io.dataease.ext.query.GridExample;
@ -17,6 +18,7 @@ import io.dataease.listener.util.CacheUtils;
import io.dataease.plugins.common.base.domain.MyPlugin;
import io.dataease.plugins.common.base.mapper.MyPluginMapper;
import io.dataease.plugins.config.LoadjarUtil;
import io.dataease.plugins.entity.PluginOperate;
import io.dataease.service.datasource.DatasourceService;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ArrayUtils;
@ -56,6 +58,9 @@ public class PluginService {
@Autowired
private LoadjarUtil loadjarUtil;
@Autowired(required = false)
private DistributedPluginService distributedPluginService;
@Value("${version}")
private String version;
@ -71,7 +76,7 @@ public class PluginService {
* @param file
* @return
*/
public Map<String, Object> localInstall(MultipartFile file) throws Exception{
public Map<String, Object> localInstall(MultipartFile file) throws Exception {
//1.上传文件到服务器pluginDir目录下
File dest = DeFileUtils.upload(file, pluginDir + "temp/");
//2.解压目标文件dest 得到plugin.json和jar
@ -113,7 +118,7 @@ public class PluginService {
}
if (pluginExist(myPlugin)) {
String msg = "插件【"+myPlugin.getName()+"】已存在,请先卸载";
String msg = "插件【" + myPlugin.getName() + "】已存在,请先卸载";
LogUtil.error(msg);
DEException.throwException(msg);
}
@ -123,7 +128,7 @@ public class PluginService {
targetDir = makeTargetDir(myPlugin);
String jarPath;
jarPath = DeFileUtils.copy(jarFile, targetDir);
if(myPlugin.getCategory().equalsIgnoreCase("datasource")){
if (myPlugin.getCategory().equalsIgnoreCase("datasource")) {
DeFileUtils.copyFolder(folder + "/" + myPlugin.getDsType() + "Driver", targetDir + myPlugin.getDsType() + "Driver");
}
loadJar(jarPath, myPlugin);
@ -142,13 +147,49 @@ public class PluginService {
DeFileUtils.deleteFile(pluginDir + "temp/");
DeFileUtils.deleteFile(folder);
}
distributeOperate(myPlugin, "install");
return null;
}
public void distributeOperate(MyPlugin plugin, String type) {
if (ObjectUtils.isNotEmpty(distributedPluginService)) {
PluginOperate operate = new PluginOperate();
operate.setPlugin(plugin);
operate.setSenderIp(IPUtils.domain());
operate.setType(type);
if (ObjectUtils.isEmpty(plugin) || StringUtils.isBlank(type) || StringUtils.isBlank(operate.getSenderIp()))
return;
distributedPluginService.pushBroadcast(operate);
}
}
public void loadJar(String jarPath, MyPlugin myPlugin) throws Exception {
loadjarUtil.loadJar(jarPath, myPlugin);
}
public void redisBroadcastInstall(MyPlugin plugin) {
String path = getPath(plugin);
try {
if (FileUtil.exist(path)) {
loadJar(path, plugin);
} else {
LogUtil.error("插件路径不存在 {} ", path);
}
} catch (Exception e) {
LogUtil.error(e);
}
}
public String getPath(MyPlugin plugin) {
String store = plugin.getStore();
String version = plugin.getVersion();
String moduleName = plugin.getModuleName();
String fileName = moduleName + "-" + version + ".jar";
String path = pluginDir + store + "/" + fileName;
return path;
}
private String makeTargetDir(MyPlugin myPlugin) {
String store = myPlugin.getStore();
String dir = pluginDir + store + "/";
@ -161,6 +202,7 @@ public class PluginService {
/**
* 检测插件是否已存在
*
* @param myPlugin
* @return
*/
@ -190,13 +232,29 @@ public class PluginService {
CacheUtils.removeAll(AuthConstants.USER_ROLE_CACHE_NAME);
CacheUtils.removeAll(AuthConstants.USER_PERMISSION_CACHE_NAME);
if(myPlugin.getCategory().equalsIgnoreCase("datasource")){
if(CollectionUtils.isNotEmpty(datasourceService.selectByType(myPlugin.getDsType()))){
if (myPlugin.getCategory().equalsIgnoreCase("datasource")) {
if (CollectionUtils.isNotEmpty(datasourceService.selectByType(myPlugin.getDsType()))) {
DEException.throwException(Translator.get("i18n_plugin_not_allow_delete"));
}
loadjarUtil.deleteModule(myPlugin.getModuleName() + "-" + myPlugin.getVersion());
}
myPluginMapper.deleteByPrimaryKey(pluginId);
distributeOperate(myPlugin, "uninstall");
return true;
}
public Boolean redisBroadcastUnInstall(MyPlugin myPlugin) {
CacheUtils.removeAll(AuthConstants.USER_ROLE_CACHE_NAME);
CacheUtils.removeAll(AuthConstants.USER_CACHE_NAME);
CacheUtils.removeAll(AuthConstants.USER_PERMISSION_CACHE_NAME);
if (myPlugin.getCategory().equalsIgnoreCase("datasource")) {
if (CollectionUtils.isNotEmpty(datasourceService.selectByType(myPlugin.getDsType()))) {
DEException.throwException(Translator.get("i18n_plugin_not_allow_delete"));
}
loadjarUtil.deleteModule(myPlugin.getModuleName() + "-" + myPlugin.getVersion());
}
myPluginMapper.deleteByPrimaryKey(myPlugin.getPluginId());
return true;
}
@ -208,7 +266,7 @@ public class PluginService {
File jarFile = new File(path);
FileUtil.del(jarFile);
if(plugin.getCategory().equalsIgnoreCase("datasource")){
if (plugin.getCategory().equalsIgnoreCase("datasource")) {
File driverFile = new File(pluginDir + plugin.getStore() + "/" + plugin.getDsType() + "Driver");
FileUtil.del(driverFile);
}
@ -259,7 +317,7 @@ public class PluginService {
} catch (InvocationTargetException e) {
e.printStackTrace();
}
if(result.getCategory().equalsIgnoreCase("datasource") && (StringUtils.isEmpty(result.getStore()) || !result.getStore().equalsIgnoreCase("default"))){
if (result.getCategory().equalsIgnoreCase("datasource") && (StringUtils.isEmpty(result.getStore()) || !result.getStore().equalsIgnoreCase("default"))) {
result.setStore("thirdpart");
}

View File

@ -29,56 +29,56 @@ import java.util.stream.Collectors;
@Service
public class TemplateMarketService {
private final static String POSTS_API="/api/content/posts?page=0&size=2000";
private final static String CATEGORIES_API="/api/content/categories";
private final static String POSTS_API = "/api/content/posts?page=0&size=2000";
private final static String CATEGORIES_API = "/api/content/categories";
@Resource
private SystemParameterService systemParameterService;
/**
* @Description Get template file from template market
* @param templateUrl template url
* @Description Get template file from template market
*/
public PanelTemplateFileDTO getTemplateFromMarket(String templateUrl){
if(StringUtils.isNotEmpty(templateUrl)){
public PanelTemplateFileDTO getTemplateFromMarket(String templateUrl) {
if (StringUtils.isNotEmpty(templateUrl)) {
String sufUrl = systemParameterService.templateMarketInfo().getTemplateMarketUlr();
Gson gson = new Gson();
String templateInfo = HttpClientUtil.get(sufUrl+templateUrl,null);
String templateInfo = HttpClientUtil.get(sufUrl + templateUrl, null);
return gson.fromJson(templateInfo, PanelTemplateFileDTO.class);
}else{
} else {
return null;
}
}
/**
* @Description Get info from template market content api
* @param url content api url
* @Description Get info from template market content api
*/
public String marketGet(String url,String accessKey){
public String marketGet(String url, String accessKey) {
HttpClientConfig config = new HttpClientConfig();
config.addHeader("API-Authorization",accessKey);
return HttpClientUtil.get(url,config);
config.addHeader("API-Authorization", accessKey);
return HttpClientUtil.get(url, config);
}
public MarketBaseResponse searchTemplate(TemplateMarketSearchRequest request){
try{
public MarketBaseResponse searchTemplate(TemplateMarketSearchRequest request) {
try {
BasicInfo basicInfo = systemParameterService.templateMarketInfo();
String result = marketGet(basicInfo.getTemplateMarketUlr()+POSTS_API,basicInfo.getTemplateAccessKey());
List<TemplateMarketDTO> postsResult = JSONObject.parseObject(result).getJSONObject("data").getJSONArray("content").toJavaList(TemplateMarketDTO.class);
return new MarketBaseResponse(basicInfo.getTemplateMarketUlr(),postsResult);
}catch (Exception e){
String result = marketGet(basicInfo.getTemplateMarketUlr() + POSTS_API, basicInfo.getTemplateAccessKey());
List<TemplateMarketDTO> postsResult = JSONObject.parseObject(result).getJSONObject("data").getJSONArray("content").toJavaList(TemplateMarketDTO.class);
return new MarketBaseResponse(basicInfo.getTemplateMarketUlr(), postsResult);
} catch (Exception e) {
DataEaseException.throwException(e);
}
return null;
}
public List<String> getCategories(){
public List<String> getCategories() {
BasicInfo basicInfo = systemParameterService.templateMarketInfo();
String resultStr = marketGet(basicInfo.getTemplateMarketUlr()+CATEGORIES_API,basicInfo.getTemplateAccessKey());
String resultStr = marketGet(basicInfo.getTemplateMarketUlr() + CATEGORIES_API, basicInfo.getTemplateAccessKey());
List<TemplateCategory> categories = JSONObject.parseObject(resultStr).getJSONArray("data").toJavaList(TemplateCategory.class);
if(CollectionUtils.isNotEmpty(categories)){
return categories.stream().sorted(Comparator.comparing(TemplateCategory::getPriority)).map(TemplateCategory :: getName).collect(Collectors.toList());
}else{
if (CollectionUtils.isNotEmpty(categories)) {
return categories.stream().filter(item -> !"应用系列".equals(item.getName())).sorted(Comparator.comparing(TemplateCategory::getPriority)).map(TemplateCategory::getName).collect(Collectors.toList());
} else {
return null;
}

View File

@ -0,0 +1,4 @@
INSERT INTO `my_plugin` (`name`, `store`, `free`, `cost`, `category`, `descript`, `version`, `creator`, `load_mybatis`,
`install_time`, `module_name`, `ds_type`)
VALUES ('人大金仓数据源插件', 'default', '0', '0', 'datasource', '人大金仓数据源插件', '1.0-SNAPSHOT', 'DATAEASE', '0',
'1650765903630', 'kingbase-backend', 'kingbase');

View File

@ -0,0 +1,34 @@
ALTER TABLE `panel_app_template_log`
ADD COLUMN `datasource_from` varchar(255) NULL DEFAULT 'new' COMMENT '数据源来源' AFTER `datasource_id`;
UPDATE `panel_subject`
SET `details` = '{\"width\":1600,\"height\":900,\"scale\":100,\"scaleWidth\":100,\"scaleHeight\":100,\"selfAdaption\":true,\"auxiliaryMatrix\":true,\"openCommonStyle\":true,\"panel\":{\"themeColor\":\"light\",\"color\":\"#F1F3F5\",\"imageUrl\":{},\"backgroundType\":\"color\",\"gap\":\"yes\",\"resultMode\":\"all\",\"resultCount\":1000},\"aidedDesign\":{\"showGrid\":false,\"matrixBase\":4},\"refreshViewLoading\":true,\"refreshUnit\":\"minute\",\"refreshTime\":5,\"themeId\":\"251a25d0-7ac5-11ed-9e50-5f9360ac1250\",\"chartInfo\":{\"chartTitle\":{\"show\":true,\"fontSize\":\"18\",\"color\":\"#000000\",\"hPosition\":\"left\",\"vPosition\":\"top\",\"isItalic\":false,\"isBolder\":true},\"chartColor\":{\"value\":\"default\",\"colors\":[\"#5470c6\",\"#91cc75\",\"#fac858\",\"#ee6666\",\"#73c0de\",\"#3ba272\",\"#fc8452\",\"#9a60b4\",\"#ea7ccc\"],\"alpha\":100,\"tableHeaderBgColor\":\"#6D9A49\",\"tableItemBgColor\":\"#FFFFFF\",\"tableFontColor\":\"#000000\",\"tableStripe\":true,\"dimensionColor\":\"#000000\",\"quotaColor\":\"#4E81BB\",\"tableBorderColor\":\"#E6E7E4\",\"seriesColors\":[],\"tableHeaderFontColor\":\"#000000\"},\"chartCommonStyle\":{\"backgroundColorSelect\":true,\"color\":\"#FFFFFF\",\"alpha\":100,\"borderRadius\":5,\"innerPadding\":0},\"filterStyle\":{\"horizontal\":\"left\",\"vertical\":\"top\",\"color\":\"#000000\",\"brColor\":\"#DCDFE6\",\"wordColor\":\"#606266\",\"innerBgColor\":\"#FFFFFF\"}}}'
WHERE `id` = 'system_1';
ALTER TABLE `sys_task`
ADD COLUMN `status` tinyint(1) NULL DEFAULT 1 COMMENT '运行状态' AFTER `create_time`;
INSERT INTO `sys_menu` (`menu_id`, `pid`, `sub_count`, `type`, `title`, `name`, `component`, `menu_sort`, `icon`,
`path`, `i_frame`, `cache`, `hidden`, `permission`)
VALUES (1100, 1, 0, 1, '血缘关系', 'sys-relationship', 'system/relationship/index', 1002, 'sys-relationship',
'relationship', 0, 0, 0, 'relationship:read');
UPDATE `sys_menu`
SET `menu_sort` = 1003
WHERE (`menu_id` = 101);
UPDATE `my_plugin`
SET `version` = '1.18.0'
where `plugin_id` > 0;
ALTER TABLE `chart_view`
ADD COLUMN `refresh_view_enable` tinyint(1) NULL DEFAULT 0 COMMENT '是否开启刷新' AFTER `view_fields`,
ADD COLUMN `refresh_unit` varchar(255) NULL DEFAULT 'minute' COMMENT '刷新时间单位' AFTER `refresh_view_enable`,
ADD COLUMN `refresh_time` int(13) NULL DEFAULT 5 COMMENT '刷新时间' AFTER `refresh_unit`;
ALTER TABLE `chart_view_cache`
ADD COLUMN `refresh_view_enable` tinyint(1) NULL DEFAULT 0 COMMENT '是否开启刷新' AFTER `view_fields`,
ADD COLUMN `refresh_unit` varchar(255) NULL DEFAULT 'minute' COMMENT '刷新时间单位' AFTER `refresh_view_enable`,
ADD COLUMN `refresh_time` int(13) NULL DEFAULT 5 COMMENT '刷新时间' AFTER `refresh_unit`;

File diff suppressed because one or more lines are too long

View File

@ -259,4 +259,5 @@ I18N_LOG_FORMAT_PREFIX=With authority of %s\u3010%s\u3011
\u7F16\u8F91\u8BB0\u5F55=Edit record
\u5220\u9664\u8BB0\u5F55=Delete record
\u6C34\u5370\u7BA1\u7406=Watermark
\u8840\u7F18\u5173\u7CFB=Relationship

View File

@ -259,5 +259,6 @@ I18N_LOG_FORMAT_PREFIX=\u4EE5%s\u3010%s\u3011\u6743\u9650
\u7F16\u8F91\u8BB0\u5F55=\u7F16\u8F91\u8BB0\u5F55
\u5220\u9664\u8BB0\u5F55=\u5220\u9664\u8BB0\u5F55
\u6C34\u5370\u7BA1\u7406=\u6C34\u5370\u7BA1\u7406
\u8840\u7F18\u5173\u7CFB=\u8840\u7F18\u5173\u7CFB

View File

@ -255,3 +255,4 @@ I18N_LOG_FORMAT_PREFIX=\u4EE5%s\u3010%s\u3011\u6B0A\u9650
\u7F16\u8F91\u8BB0\u5F55=\u7DE8\u8F2F\u8A18\u9304
\u5220\u9664\u8BB0\u5F55=\u522A\u9664\u8A18\u9304
\u6C34\u5370\u7BA1\u7406=\u6C34\u5370\u7BA1\u7406
\u8840\u7F18\u5173\u7CFB=\u8840\u7DE3\u95DC\u7CFB

View File

@ -8,11 +8,12 @@ export function post(url, data, loading = false) {
data
})
}
export function tableField(id) {
return request({
url: '/dataset/table/getWithPermission/' + id,
method: 'post',
loading: true,
loading: false,
hideMsg: true,
timeout: 60000
})
@ -34,6 +35,7 @@ export function chartCopy(id, panelId) {
loading: false
})
}
export function chartBatchCopy(params, panelId) {
return request({
url: '/chart/view/chartBatchCopy/' + panelId,
@ -42,6 +44,7 @@ export function chartBatchCopy(params, panelId) {
loading: false
})
}
export function chartGroupTree(data) {
return request({
url: '/chart/group/tree',
@ -116,6 +119,7 @@ export function resetViewCacheCallBack(viewId, panelId, callback) {
callback(rep)
})
}
export function resetViewCache(viewId, panelId) {
return request({
url: '/chart/view/resetViewCache/' + viewId + '/' + panelId,

View File

@ -128,6 +128,14 @@ export function fieldListWithPermission(id, showLoading = true) {
})
}
export function datasetParams(id, type, showLoading = true) {
return request({
url: '/dataset/table/params/' + id + '/' + type,
loading: showLoading,
method: 'post'
})
}
export function fieldListDQ(id, showLoading = true) {
return request({
url: '/dataset/field/listByDQ/' + id,

View File

@ -108,7 +108,6 @@ import { ApplicationContext } from '@/utils/ApplicationContext'
import { chartCopy } from '@/api/chart/chart'
import { adaptCurThemeCommonStyle } from '@/components/canvas/utils/style'
import toast from '@/components/canvas/utils/toast'
import generateID from '@/components/canvas/utils/generateID'
import ButtonDialog from '@/views/panel/filter/ButtonDialog'
import ButtonResetDialog from '@/views/panel/filter/ButtonResetDialog'
import FilterDialog from '@/views/panel/filter/FilterDialog'
@ -432,7 +431,7 @@ export default {
uploadFileResult(file, (fileUrl) => {
const component = {
...commonAttr,
id: generateID(),
id: uuid.v1(),
component: 'Picture',
type: 'picture-add',
label: '图片',

View File

@ -44,6 +44,7 @@
:in-screen="inScreen"
:edit-mode="'preview'"
:h="config.style.height"
:search-count="searchCount"
:canvas-id="canvasId"
/>
<component

View File

@ -137,7 +137,7 @@
:target="curComponent.hyperlinks.openMode "
:href="curComponent.hyperlinks.content "
>
<i class="icon iconfont icon-com-jump" />
<i class="icon iconfont icon-com-jump"/>
</a>
</span>
@ -496,19 +496,7 @@ export default {
},
// sourceViewId
clearLinkage() {
this.componentData.forEach(item => {
if (item.linkageFilters && item.linkageFilters.length > 0) {
const newList = item.linkageFilters.filter(linkage => linkage.sourceViewId !== this.element.propValue.viewId)
item.linkageFilters.splice(0, item.linkageFilters.length)
// push watch
if (newList.length > 0) {
newList.forEach(newLinkage => {
item.linkageFilters.push(newLinkage)
})
}
}
})
bus.$emit('clear_panel_linkage', { viewId: this.element.propValue.viewId })
this.$store.commit('clearViewLinkage', this.element.propValue.viewId)
},
goFile() {
this.$refs.files.click()

View File

@ -6,6 +6,7 @@
@scroll="canvasScroll"
>
<canvas-opt-bar
v-if="canvasId==='canvas-main'"
ref="canvas-opt-bar"
:canvas-style-data="canvasStyleData"
@link-export-pdf="downloadAsPDF"
@ -155,7 +156,7 @@ import bus from '@/utils/bus'
import { buildFilterMap, buildViewKeyMap, formatCondition, valueValid, viewIdMatch } from '@/utils/conditionUtil'
import { hasDataPermission } from '@/utils/permission'
import { activeWatermark } from '@/components/canvas/tools/watermark'
import { userLoginInfo } from '@/api/systemInfo/userLogin'
import { proxyUserLoginInfo, userLoginInfo } from '@/api/systemInfo/userLogin'
import html2canvas from 'html2canvasde'
import { queryAll } from '@/api/panel/pdfTemplate'
import PDFPreExport from '@/views/panel/export/PDFPreExport'
@ -443,6 +444,9 @@ export default {
bus.$off('trigger-reset-button', this.triggerResetButton)
},
methods: {
getCanvasHeight() {
return this.mainHeightCount
},
openChartDetailsDialog(paramInfo) {
if (this.canvasId === 'canvas-main') {
this.showChartInfo = paramInfo.showChartInfo
@ -456,7 +460,8 @@ export default {
if (this.userInfo) {
activeWatermark(this.panelInfo.watermarkInfo.settingContent, this.userInfo, waterDomId, this.canvasId, this.panelInfo.watermarkOpen)
} else {
userLoginInfo().then(res => {
const method = this.userId ? proxyUserLoginInfo : userLoginInfo
method(this.userId).then(res => {
this.userInfo = res.data
activeWatermark(this.panelInfo.watermarkInfo.settingContent, this.userInfo, waterDomId, this.canvasId, this.panelInfo.watermarkOpen)
})
@ -781,14 +786,6 @@ export default {
padding: 10px 20px 20px;
}
.mobile-dialog-css ::v-deep .el-dialog__headerbtn {
top: 7px
}
.mobile-dialog-css ::v-deep .el-dialog__body {
padding: 0px;
}
::-webkit-scrollbar {
width: 0px !important;
height: 0px !important;

View File

@ -29,7 +29,7 @@ export default {
data() {
return {
canvasId: 'canvas-main',
dataLoading: false,
dataLoading: true,
backScreenShot: false,
mainHeight: '100vh!important',
shareUserId: null
@ -171,12 +171,12 @@ export default {
</script>
<style lang="scss" scoped>
.bg {
width: 100%;
height: 100vh!important;
min-width: 200px;
min-height: 300px;
background-color: #f7f8fa;
}
.bg {
width: 100%;
height: 100vh !important;
min-width: 200px;
min-height: 300px;
background-color: #f7f8fa;
}
</style>

View File

@ -44,7 +44,12 @@
v-else
class="info-class"
>
{{ $t('panel.web_add_tips') }}
<span>{{ $t('panel.web_add_tips_pre') }}</span>
<i
slot="reference"
class="icon iconfont icon-chaolianjie"
/>
<span>{{ $t('panel.web_add_tips_suf') }}</span>
</div>
</el-row>
</template>
@ -53,6 +58,7 @@
import { mapState } from 'vuex'
import bus from '@/utils/bus'
import eventBus from '@/components/canvas/utils/eventBus'
export default {
name: 'DeFrame',
props: {
@ -121,51 +127,56 @@ export default {
</script>
<style>
.info-class{
text-align: center;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
background-color: rgba(255,255,255,0.3);
font-size: 12px;
color: #9ea6b2;
}
.info-class {
text-align: center;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
background-color: rgba(255, 255, 255, 0.3);
font-size: 12px;
color: #9ea6b2;
}
.main-frame{
height: 100%;
width: 100%;
}
.frame-mask {
display: flex;
opacity: 0.5;
position:absolute;
top:0px;
z-index: 1;
display: flex;
align-items: center;
justify-content: center;
}
.edit-mask{
left: 0px;
background-color: #5c5e61;
height: 100%!important;
width: 100% !important;
}
.preview-top-mask{
left: 0px;
height: 15px!important;
width: 100% !important;
}
.preview-right-mask{
right: 0px;
height: 100%!important;
width: 15px !important;
}
.preview-left-mask{
left: 0px;
height: 100%!important;
width: 15px !important;
}
.main-frame {
height: 100%;
width: 100%;
}
.frame-mask {
display: flex;
opacity: 0.5;
position: absolute;
top: 0px;
z-index: 1;
display: flex;
align-items: center;
justify-content: center;
}
.edit-mask {
left: 0px;
background-color: #5c5e61;
height: 100% !important;
width: 100% !important;
}
.preview-top-mask {
left: 0px;
height: 15px !important;
width: 100% !important;
}
.preview-right-mask {
right: 0px;
height: 100% !important;
width: 15px !important;
}
.preview-left-mask {
left: 0px;
height: 100% !important;
width: 15px !important;
}
</style>

View File

@ -305,6 +305,7 @@ export default {
},
data() {
return {
innerRefreshTimer: null,
mobileChartDetailsVisible: false,
chartDetailsVisible: false,
showChartInfo: {},
@ -350,6 +351,10 @@ export default {
},
computed: {
// 使filter
initLoad() {
return !(this.isEdit && this.currentCanvasNewId.includes(this.element.id)) && this.isFirstLoad
},
scaleCoefficient() {
if (this.terminal === 'pc' && !this.mobileLayoutStatus) {
return 1.1
@ -389,14 +394,14 @@ export default {
return this.httpRequest.status && this.chart.type && this.chart.type === 'label'
},
loadingFlag() {
return (this.canvasStyleData.refreshViewLoading || this.searchCount === 0) && this.requestStatus === 'waiting'
return (this.canvasStyleData.refreshViewLoading || (!this.innerRefreshTimer && this.searchCount === 0)) && this.requestStatus === 'waiting'
},
panelInfo() {
return this.$store.state.panel.panelInfo
},
filter() {
const filter = {}
filter.filter = this.isFirstLoad ? this.filters : this.cfilters
filter.filter = this.initLoad ? this.filters : this.cfilters
filter.linkageFilters = this.element.linkageFilters
filter.outerParamsFilters = this.element.outerParamsFilters
filter.drill = this.drillClickDimensionList
@ -455,6 +460,7 @@ export default {
return this.element.commonBackground && this.element.commonBackground.innerPadding || 0
},
...mapState([
'currentCanvasNewId',
'nowPanelTrackInfo',
'nowPanelJumpInfo',
'publicLinkStatus',
@ -515,7 +521,8 @@ export default {
},
//
searchCount: function(val1) {
if (val1 > 0 && this.requestStatus !== 'waiting') {
//
if (val1 > 0 && this.requestStatus !== 'waiting' && !this.innerRefreshTimer) {
this.getData(this.element.propValue.viewId)
}
},
@ -542,6 +549,7 @@ export default {
},
beforeDestroy() {
this.innerRefreshTimer && clearInterval(this.innerRefreshTimer)
bus.$off('plugin-chart-click', this.pluginChartClick)
bus.$off('plugin-jump-click', this.pluginJumpClick)
bus.$off('plugin-add-view-track-filter', this.pluginAddViewTrackFilter)
@ -561,6 +569,20 @@ export default {
}
},
methods: {
//
buildInnerRefreshTimer(refreshViewEnable = false, refreshUnit = 'minute', refreshTime = 5) {
if (this.editMode === 'preview' && !this.innerRefreshTimer && refreshViewEnable) {
this.innerRefreshTimer && clearInterval(this.innerRefreshTimer)
const timerRefreshTime = refreshUnit === 'second' ? refreshTime * 1000 : refreshTime * 60000
this.innerRefreshTimer = setInterval(() => {
this.clearViewLinkage()
this.getData(this.element.propValue.viewId)
}, timerRefreshTime)
}
},
clearViewLinkage() {
this.$store.commit('clearViewLinkage', this.element.propValue.viewId)
},
responseResetButton() {
if (!this.cfilters?.length) {
this.getData(this.element.propValue.viewId, false)
@ -736,6 +758,7 @@ export default {
if (response.success) {
this.chart = response.data
this.view = response.data
this.buildInnerRefreshTimer(this.chart.refreshViewEnable, this.chart.refreshUnit, this.chart.refreshTime)
this.$emit('fill-chart-2-parent', this.chart)
this.getDataOnly(response.data, dataBroadcast)
this.chart['position'] = this.inTab ? 'tab' : 'panel'
@ -1263,4 +1286,12 @@ export default {
z-index: 2;
display: block !important;
}
.mobile-dialog-css ::v-deep .el-dialog__headerbtn {
top: 7px
}
.mobile-dialog-css ::v-deep .el-dialog__body {
padding: 0px;
}
</style>

View File

@ -14,7 +14,6 @@ export default {
toast('已经到顶了')
}
}
},
downComponent({ componentData, curComponent }) {

View File

@ -1,4 +1,4 @@
import { sin, cos } from '@/components/canvas/utils/translate'
import { cos, sin } from '@/components/canvas/utils/translate'
import store from '@/store'
import Vue from 'vue'
@ -361,7 +361,13 @@ export function adaptCurTheme(customStyle, customAttr, chartType) {
}
}
customAttr['color'] = { ...canvasStyle.chartInfo.chartColor }
customStyle['text'] = { ...canvasStyle.chartInfo.chartTitle, title: customStyle['text']['title'], show: customStyle['text']['show'], remarkShow: customStyle['text']['remarkShow'], remark: customStyle['text']['remark'] }
customStyle['text'] = {
...canvasStyle.chartInfo.chartTitle,
title: customStyle['text']['title'],
show: customStyle['text']['show'],
remarkShow: customStyle['text']['remarkShow'],
remark: customStyle['text']['remark']
}
if (customStyle.background) {
delete customStyle.background
}
@ -370,7 +376,7 @@ export function adaptCurTheme(customStyle, customAttr, chartType) {
export function adaptCurThemeCommonStyle(component) {
const commonStyle = store.state.canvasStyleData.chartInfo.chartCommonStyle
for (const key in commonStyle) {
component.commonBackground[key] = commonStyle[key]
Vue.set(component.commonBackground, key, commonStyle[key])
}
if (isFilterComponent(component.component)) {
const filterStyle = store.state.canvasStyleData.chartInfo.filterStyle

View File

@ -1,5 +1,6 @@
import {
BASE_MOBILE_STYLE,
COMMON_BACKGROUND,
COMMON_BACKGROUND_NONE,
HYPERLINKS
} from '@/components/canvas/customComponent/component-list'
@ -86,7 +87,18 @@ export function panelDataPrepare(componentData, componentStyle, callback) {
componentStyle.chartInfo.tabStyle = (componentStyle.chartInfo.tabStyle || deepCopy(TAB_COMMON_STYLE))
componentStyle.themeId = (componentStyle.themeId || 'NO_THEME')
componentStyle.panel.themeColor = (componentStyle.panel.themeColor || 'light')
componentStyle.panel.mobileSetting = (componentStyle.panel.mobileSetting || MOBILE_SETTING)
componentStyle.panel.mobileSetting = (componentStyle.panel.mobileSetting || deepCopy(MOBILE_SETTING))
// 主题增加组件背景设置
if (componentStyle.chartCommonStyle) {
componentStyle.chartCommonStyle.enable = componentStyle.chartCommonStyle.enable || false
componentStyle.chartCommonStyle.backgroundType = componentStyle.chartCommonStyle.backgroundType || 'innerImage'
componentStyle.chartCommonStyle.innerImageColor = componentStyle.chartCommonStyle.innerImageColor || '#1094E5'
componentStyle.chartCommonStyle.innerImage = componentStyle.chartCommonStyle.innerImage || 'board/blue_1.svg'
componentStyle.chartCommonStyle.outerImage = componentStyle.chartCommonStyle.outerImage || null
} else {
componentStyle.chartCommonStyle = deepCopy(COMMON_BACKGROUND)
}
componentData.forEach((item, index) => {
if (item.component && item.component === 'de-date') {
const widget = ApplicationContext.getService(item.serviceName)

View File

@ -48,7 +48,6 @@
:element="element"
:in-draw="inDraw"
:in-screen="inScreen"
:size="sizeInfo"
/>
</div>
</div>
@ -97,10 +96,16 @@ export default {
isRelation: {
type: Boolean,
default: false
},
searchCount: {
type: Number,
required: false,
default: 0
}
},
data() {
return {
needRefreshComponents: ['de-select', 'de-select-grid', 'de-select-tree'],
inputMaxSize: 46,
inputLargeSize: 42,
inputSmallSize: 38,
@ -127,17 +132,6 @@ export default {
transform: 'scale(' + this.scale + ')'
}
},
sizeInfo() {
let size
if (this.duHeight > this.inputLargeSize) {
size = 'medium'
} else if (this.duHeight > this.inputSmallSize) {
size = 'small'
} else {
size = 'mini'
}
return size
},
deSelectGridBg() {
if (this.element.component !== 'de-select-grid') return null
const { backgroundColorSelect, color } = this.element.commonBackground
@ -150,6 +144,7 @@ export default {
return ['de-select', 'de-select-grid', 'de-date', 'de-input-search', 'de-number-range', 'de-select-tree'].includes(this.element.component)
},
...mapState([
'curComponent',
'previewCanvasScale'
])
},
@ -160,6 +155,13 @@ export default {
},
deep: true,
immediate: true
},
//
searchCount: function(val1) {
//
if (val1 > 0 && this.needRefreshComponents.includes(this.element.component) && (!this.curComponent || this.curComponent.id !== this.element.id)) {
this.$refs['deOutWidget'].refreshLoad()
}
}
},
mounted() {
@ -222,7 +224,7 @@ export default {
left: 0px;
}
.ccondition-main {
.condition-main {
position: absolute;
overflow: auto;
top: 0px;
@ -281,6 +283,11 @@ export default {
align-items: flex-end;
}
.first-element-container ::v-deep .el-input__inner {
height: 40px !important;
line-height: 40px !important;
}
.first-element-grid-container {
background: #fff;
border: 1px solid #d7dae2;

View File

@ -1,6 +1,6 @@
<template>
<el-input
v-count="{value, maxlength}"
v-count="{value, maxlength, buttonDisabled}"
:placeholder="$t('fu.search_bar.please_input')"
show-word-limit
:disabled="disabled"
@ -16,14 +16,16 @@ export default {
directives: {
count: {
update: function(el, binding) {
const lg = binding.value.value?.length || 0
const { value, maxlength, buttonDisabled } = binding.value
if (buttonDisabled) return
const lg = value?.length || 0
const count = el.querySelector('.el-input__count')
if (!count) return
if (!lg) {
if (count?.classList?.contains('no-zore')) {
count.classList.remove('no-zore')
}
count.innerHTML = `0/${binding.value.maxlength || 200}`
count.innerHTML = `0/${maxlength || 200}`
return
}
if (el.querySelector('.no-zore')) {
@ -34,7 +36,7 @@ export default {
const num = document.createElement('span')
const total = document.createElement('span')
num.style.color = '#1F2329'
total.innerHTML = `/${binding.value.maxlength || 200}`
total.innerHTML = `/${maxlength || 200}`
num.innerHTML = lg
if (!newCount) return
newCount.classList.add('el-input__count', 'no-zore')
@ -44,6 +46,11 @@ export default {
}
}
},
inject: {
elForm: {
default: ''
}
},
props: {
disabled: Boolean,
value: String,
@ -52,6 +59,13 @@ export default {
default: 200
}
},
computed: {
buttonDisabled() {
return Object.prototype.hasOwnProperty.call(this.$options.propsData, 'disabled')
? this.disabled
: (this.elForm || {}).disabled
}
},
methods: {
handleChange(val) {
this.$emit('input', val)

View File

@ -17,8 +17,8 @@
},
className
]"
@mousedown="elementMouseDown"
@touchstart="elementTouchDown"
@mousedown="outerElementMouseDown"
@mouseenter="enter"
@mouseleave="leave"
>
@ -73,6 +73,22 @@
:style="mainSlotStyleInner"
class="main-background"
>
<div
class="de-drag-area de-drag-top"
@mousedown="elementMouseDown"
/>
<div
class="de-drag-area de-drag-right"
@mousedown="elementMouseDown"
/>
<div
class="de-drag-area de-drag-bottom"
@mousedown="elementMouseDown"
/>
<div
class="de-drag-area de-drag-left"
@mousedown="elementMouseDown"
/>
<svg-icon
v-if="svgInnerEnable"
:style="{'color':element.commonBackground.innerImageColor}"
@ -863,6 +879,18 @@ export default {
eventsFor = events.touch
this.elementDown(e)
},
outerElementMouseDown(e) {
// private
this.$store.commit('setClickComponentStatus', true)
if (this.element.component !== 'user-view' && this.element.component !== 'de-frame' && this.element.component !== 'v-text' && this.element.component !== 'de-rich-text' && this.element.component !== 'rect-shape' && this.element.component !== 'de-input-search' && this.element.component !== 'de-select-grid' && this.element.component !== 'de-number-range' && this.element.component !== 'de-date') {
e.preventDefault()
}
//
e.stopPropagation()
this.$nextTick(() => {
this.$store.commit('setCurComponent', { component: this.element, index: this.index })
})
},
elementMouseDown(e) {
// private
this.$store.commit('setClickComponentStatus', true)
@ -2131,4 +2159,42 @@ export default {
.drag-on-tab-collision {
z-index: 1000 !important;
}
.de-drag-area {
position: absolute;
z-index: 10;
}
.de-drag-area:hover {
cursor: move;
}
.de-drag-top {
left: 0;
top: 0;
height: 12px;
width: 100%;
}
.de-drag-right {
right: 0;
top: 0;
width: 16px;
height: 100%;
}
.de-drag-bottom {
left: 0;
bottom: 0;
height: 12px;
width: 100%;
}
.de-drag-left {
left: 0;
top: 0;
width: 16px;
height: 100%;
}
</style>

View File

@ -0,0 +1,573 @@
<template>
<div
class="ui-fas"
:class="'ui-fas-' + id"
>
<div
v-if="!!name"
class="selected-icon-container"
>
<span
title="icon"
:style="{ color: color }"
>
<e-icon
:icon-name="name"
:title="name"
class="e-icon"
/>
</span>
</div>
<el-popover
ref="popover"
v-model="visible"
:disabled="disabled"
:placement="myPlacement"
popper-class="el-icon-popper"
:width="popoverWidth"
show-arrow
trigger="manual"
@show="setTempSelected"
>
<template slot="reference">
<slot
name="default"
:data="{ prefixIcon, visible, placeholder, disabled, clearable, readonly, size }"
>
<el-input
ref="input"
v-model="proxyValue"
class="de-icon-picker-input"
:placeholder="dynamicPlaceholder"
:style="styles"
:clearable="clearable"
:disabled="disabled"
:readonly="true"
:size="size"
@input="_change"
@clear="_initIcon(false)"
@focus="_popoverShowFun(false)"
>
<template
v-if="showPrefix"
slot="prepend"
>
<slot
name="prepend"
:icon="prefixIcon"
>
<e-icon
:icon-name="prefixIcon"
class="e-icon"
/>
</slot>
</template>
</el-input>
</slot>
</template>
<div :class="'de-icon-picker-container-' + id">
<div class="top-container">
<el-color-picker
v-model="curColor"
:popper-class="'icon-picker-inner-color-' + id"
show-alpha
@change="colorChange"
/>
<div class="top-sure-button-div">
<el-button
type="primary"
size="mini"
icon="el-icon-check"
@click.stop="sure"
/>
</div>
</div>
<el-divider class="top-divider" />
<el-scrollbar
v-if="!destroy"
ref="eScrollbar"
tag="div"
wrap-class="el-select-dropdown__wrap"
view-class="el-select-dropdown__list"
:class="'is-empty-' + id"
>
<div
v-for="(group, gname, i) in dataGroup"
:key="i"
>
<el-divider
class="icon-type-line"
content-position="left"
>{{ $t('chart.' + gname.substr(1)) }}</el-divider>
<ul
v-if="group && group.length > 0"
ref="fasIconList"
class="fas-icon-list"
>
<li
v-for="(item, index) in group"
:key="index"
class="picker-li"
:style="tempSelected === item && (highLightColor !== '' || !!curColor) ? { color: highLightColor || curColor, border: '1px solid ' + curColor } : ''"
@click="_selectedIcon(item)"
>
<slot
name="icon"
:icon="item"
>
<e-icon
:icon-name="item"
:title="item"
class="e-icon"
/>
</slot>
</li>
</ul>
</div>
<ul
v-if="dataList && dataList.length > 0"
ref="fasIconList"
class="fas-icon-list"
>
<li
v-for="(item, index) in dataList"
:key="index"
class="picker-li"
:style="tempSelected === item && (highLightColor !== '' || !!curColor) ? { color: highLightColor || curColor, border: '1px solid ' + curColor } : ''"
@click="_selectedIcon(item)"
>
<slot
name="icon"
:icon="item"
>
<e-icon
:icon-name="item"
:title="item"
class="e-icon"
/>
</slot>
</li>
</ul>
<span
v-if="!dataGroup && (!dataList || !dataList.length)"
class="fas-no-data"
v-text="emptyText"
/>
</el-scrollbar>
</div>
</el-popover>
</div>
</template>
<script>
import iconList from '../iconList'
import { off, on } from '../utils/index'
import EIcon from '../eIcon/e-icon'
import ElInput from 'element-ui/lib/input'
import ElPopover from 'element-ui/lib/popover'
import ElScrollbar from 'element-ui/lib/scrollbar'
import { PopupManager } from 'element-ui/lib/utils/popup'
export default {
name: 'DeIconGroupPicker',
components: {
EIcon,
ElInput,
ElPopover,
ElScrollbar
},
props: {
disabled: {
type: Boolean,
default() {
return false
}
},
readonly: {
type: Boolean,
default() {
return false
}
},
clearable: {
type: Boolean,
default() {
return false
}
},
styles: {
type: Object,
default() {
return {}
}
},
placement: {
type: String,
default() {
return 'bottom'
}
},
value: {
type: String,
default() {
return ''
}
},
options: {
type: Object,
default: () => {}
},
width: {
type: Number,
default() {
return -1
}
},
size: {
type: String,
default() {
return 'medium'
}
},
placeholder: {
type: String,
default() {
return '请选择图标'
}
},
defaultIcon: {
type: String,
default() {
return 'eiconfont e-icon-bi'
}
},
emptyText: {
type: String,
default() {
return '暂无可选图标'
}
},
highLightColor: {
type: String,
default() {
return ''
}
},
zIndex: {
type: Number,
default() {
return null
}
},
showPrefix: {
type: Boolean,
default() {
return false
}
},
color: {
type: String,
default() {
return 'rgba(255, 0, 0, 1.0)'
}
}
},
data() {
return {
iconList: [],
visible: false,
prefixIcon: 'eiconfont e-icon-bi',
name: '',
icon: {},
myPlacement: 'bottom',
popoverWidth: 200,
destroy: false,
id: new Date().getTime(),
proxyValue: '',
curColor: '',
tempSelected: '',
iconGroup: {}
}
},
computed: {
dataList: function() {
const arr1 = []
for (let i = 0, len = this.iconList.length; i < len; i++) {
if (arr1.indexOf(this.iconList[i]) === -1) {
arr1.push(this.iconList[i])
}
}
return arr1
},
dataGroup: function() {
return JSON.parse(JSON.stringify(this.iconGroup))
},
dynamicPlaceholder() {
return this.name ? '' : this.placeholder
}
},
watch: {
value: function(val) {
setTimeout(() => {
this.name = val
this.prefixIcon = this.name ? this.name : this.defaultIcon
}, 50)
},
visible: function(val) {
if (val === false) {
this.$nextTick(() => {
off(document, 'mouseup', this._popoverHideFun)
})
} else {
this.$nextTick(() => {
this.createIconList()
on(document, 'mouseup', this._popoverHideFun)
})
}
},
options: {
handler(newV, oldV) {
const self = this
setTimeout(() => {
self._initIcon(true)
}, 50)
},
deep: true
}
},
mounted() {
this._updateW()
},
beforeDestroy() {
off(document, 'mouseup', this._popoverHideFun)
this.destroyIconList()
},
created() {
this.createIconList()
this._initIcon(true)
this.curColor = this.color
},
methods: {
colorChange(c) {
this.color = c
this.$emit('set-color', c)
},
setTempSelected() {
this.tempSelected = this.name
},
sure() {
this.visible = false
this.name = this.tempSelected
this.prefixIcon = this.name
this.color = this.curColor
this._emitFun(this.name)
this.$emit('set-color', this.curColor)
},
_change(val) {
this.iconList = this.icon.list.filter(function(i) {
return i.indexOf(val) !== -1
})
},
_initIcon(type) {
this.prefixIcon = this.value && type && type === true ? this.value : this.defaultIcon
this.name = type === true ? this.value : ''
this.icon = Object.assign({}, iconList)
if (this.options) {
this.icon.list = []
if (this.options.addIconList !== undefined &&
this.options.addIconList &&
this.options.addIconList.length > 0) {
this.icon.addIcon(this.options.addIconList)
}
if (this.options.removeIconList !== undefined &&
this.options.removeIconList &&
this.options.removeIconList.length > 0) {
this.icon.removeIcon(this.options.removeIconList)
}
if (this.options?.addIconGroup) {
this.icon.initGroup(this.options.addIconGroup)
}
}
this.iconList = this.icon.list
this.iconGroup = this.icon.group
if (this.placement && (this.placement === 'bottom' || this.placement === 'top')) {
this.myPlacement = this.placement
}
if (type === false) {
this._emitFun('')
}
},
addIcon(item = []) {
if (item !== undefined && item && item.length > 0) {
this.icon.addIcon(item)
this.iconList = this.icon.list
}
},
removeIcon(item = []) {
if (item !== undefined && item && item.length > 0) {
this.icon.removeIcon(item)
this.iconList = this.icon.list
}
},
updatePopper(zIndex) {
if (zIndex) {
PopupManager.zIndex = zIndex
}
this._popoverShowFun(true)
setTimeout(() => {
this.$refs.popover.updatePopper()
}, 100)
},
_selectedIcon(item) {
this.tempSelected = item
},
_updateW() {
this.$nextTick(() => {
if (this.width === -1 && this.$refs.input && this.$refs.input.$el) {
this.popoverWidth = this.$refs.input.$el.getBoundingClientRect().width - 36
} else {
this.popoverWidth = this.width
}
if (this.$refs.eScrollbar && this.$refs.eScrollbar.wrap) {
this.$refs.eScrollbar.wrap.scrollTop = 0
this.$refs.eScrollbar.handleScroll()
this.$refs.eScrollbar.update()
}
})
},
_popoverShowFun(flag) {
const _this = this
if (_this.readonly !== true && _this.disabled !== true) {
if (!flag && _this.zIndex) {
PopupManager.zIndex = this.zIndex
}
_this.visible = true
_this._updateW()
}
},
_popoverHideFun(e) {
const path = e.path || (e.composedPath && e.composedPath())
const insideClassNameList = ['ui-fas-', 'de-icon-picker-container-', 'icon-picker-inner-color-']
const isInside = path.some(list => {
return list.className && typeof list.className === 'string' && insideClassNameList.some(cName => list.className.includes(cName + this.id))
})
if (!isInside) {
this.visible = false
}
},
_emitFun(val) {
this.$emit('input', val)
this.$emit('change', val)
},
destroyIconList() {
this.destroy = true
},
createIconList() {
this.destroy = false
},
show() {
this._popoverShowFun(false)
},
hide() {
this.visible = false
}
}
}
</script>
<style lang="scss" scoped>
@import '~element-ui/lib/theme-chalk/input.css';
@import '~element-ui/lib/theme-chalk/popover.css';
@import '~element-ui/lib/theme-chalk/scrollbar.css';
@import '~element-ui/lib/theme-chalk/select-dropdown.css';
.fas-icon-list {
list-style-type: none;
margin: 0 0 0 -4px;
padding: 0;
display: flex;
flex-direction: row;
flex-wrap: wrap;
}
.ui-fas .el-input__inner {
cursor: pointer;
}
.fas-icon-list li {
width: 30px;
height: 30px;
margin: 5px;
}
.fas-icon-list li i,
.fas-icon-list li svg {
font-size: 20px;
cursor: pointer;
}
.el-icon-popper {
max-height: 400px;
overflow: auto;
overflow-x: hidden;
overflow-y: hidden;
}
.el-icon-popper[x-placement^="bottom"] {
margin-top: 5px;
}
.fas-no-data {
display: block;
}
.e-icon {
font-size: 16px;
}
.top-divider {
margin: 5px 0 0 0 !important;
}
.top-container {
display: flex;
}
.top-sure-button-div {
margin: 4px 15px 0 auto;
::v-deep button {
width: 25px;
height: 20px;
padding: 4px 5px;
}
}
.selected-icon-container {
position: absolute;
z-index: 9;
width: 21%;
text-align: center;
margin-top: 2px;
pointer-events: none;
}
.picker-li {
text-align: center;
line-height: 30px;
}
.icon-type-line {
margin: 13px 0;
}
</style>

View File

@ -0,0 +1,86 @@
<template>
<i
v-if="fontClass"
:class="iconName"
@click="click(iconName,$event)"
/>
<svg
v-else-if="svg"
:class="svgClass"
aria-hidden="true"
@click="click(iconName,$event)"
>
<use :xlink:href="iconName" />
</svg>
<div
v-else-if="isExternal"
:style="styleExternalIcon"
:class="className"
class="icon external-icon"
@click="click(iconName,$event)"
/>
</template>
<script>
import { isExternal } from '../utils/index'
export default {
name: 'EIcon',
props: {
iconName: {
type: String,
required: true
},
className: {
type: String,
default: ''
}
},
computed: {
fontClass() {
return this.iconName && this.iconName.trim().length > 2 && (!isExternal(this.iconName) && !this.iconName.startsWith('#'))
},
svg() {
return this.iconName && this.iconName.trim().length > 2 && (!isExternal(this.iconName) && this.iconName.startsWith('#'))
},
isExternal() {
return isExternal(this.iconName)
},
svgClass() {
if (this.className) {
return 'icon ' + this.className
} else {
return 'icon'
}
},
styleExternalIcon() {
return {
'background-image': `url(${this.iconName})`,
'background-repeat': 'no-repeat',
'background-size': '100% 100%',
'-moz-background-size': '100% 100%'
}
}
},
methods: {
click(iconName, event) {
if (event) event.preventDefault()
this.$emit('click', iconName)
}
}
}
</script>
<style scoped>
.icon {
width: 1em;
height: 1em;
vertical-align: -0.15em;
fill: currentColor;
overflow: hidden;
}
.external-icon {
display: inline-block;
}
</style>

View File

@ -0,0 +1 @@
export default ['xianxingbenzitubiao1', 'xianxinganquansuotubiao', 'xianxingbenzitubiao2', 'xianxingdianzantubiao', 'xianxingdiannaotubiao', 'xianxingjishibentubiao', 'xianxingdianhuatubiao', 'xianxinghuishouzhantubiao', 'xianxingWIFItubiao', 'xianxingduihuakuangtubiao', 'xianxinglajitongtubiao', 'xianxingjiangpaitubiao2', 'xianxingjiaoyoutubiao', 'xianxingquerentubiao', 'xianxingrenwutubiao', 'xianxingjiangpaitubiao1', 'xianxingshoujitubiao', 'xianxinglianxirentubiao', 'xianxingrenyuantubiao', 'xianxinggongjutubiao', 'xianxingshenfentubiao', 'xianxingxiangjitubiao', 'xianxingwendatubiao', 'xianxingyanjingtubiao', 'xianxingxinxitubiao', 'xianxingxinjiantubiao', 'xianxingtudingtubiao', 'xianxingshijiantubiao', 'xianxingqianbaotubiao', 'xianxingtupiantubiao', 'xianxingzhifubaotubiao', 'xianxingyoujiantubiao', 'xianxingzhifeijitubiao', 'xianxingyuantubiao', 'xianxingxiangfatubiao', 'diannao-01', 'jiaojuan-01', 'shuji-01', 'gujianzhu-01', 'simiao-01', 'yundong-yumaoqiu', 'sanjiaojia-01', 'zhaoxiangji-01', 'shuihu-01', 'yumaopai-01', 'yanjing-01', 'chalaoban-01', 'shouji-01', 'yinzhang-01', 'xiangyan-01', 'guangpan-01', 'kafei-01', 'erji-01', 'foling-01', 'xiong-01', 'bingxiang', 'diannao', 'chufangcheng', 'biludianshi', 'dayinji', 'guangpan', 'jiashiqi', 'fengshan', 'kongtiao', 'dianfanbao', 'fengrenji', 'dianzicheng', 'mensuo', 'shexiangji', 'saodijiqiren', 'lvshuiji', 'shuzhuodeng', 'kafeiji', 'jisuanqi', 'xiyiji', 'shexiangtou'].map(s => 'eiconfont e-icon-' + s)

View File

@ -0,0 +1 @@
export default ['platform-eleme', 'eleme', 'delete-solid', 'delete', 's-tools', 'setting', 'user-solid', 'user', 'phone', 'phone-outline', 'more', 'more-outline', 'star-on', 'star-off', 's-goods', 'goods', 'warning', 'warning-outline', 'question', 'info', 'remove', 'circle-plus', 'success', 'error', 'zoom-in', 'zoom-out', 'remove-outline', 'circle-plus-outline', 'circle-check', 'circle-close', 's-help', 'help', 'minus', 'plus', 'check', 'close', 'picture', 'picture-outline', 'picture-outline-round', 'upload', 'upload2', 'download', 'camera-solid', 'camera', 'video-camera-solid', 'video-camera', 'message-solid', 'bell', 's-cooperation', 's-order', 's-platform', 's-fold', 's-unfold', 's-operation', 's-promotion', 's-home', 's-release', 's-ticket', 's-management', 's-open', 's-shop', 's-marketing', 's-flag', 's-comment', 's-finance', 's-claim', 's-custom', 's-opportunity', 's-data', 's-check', 's-grid', 'menu', 'share', 'd-caret', 'caret-left', 'caret-right', 'caret-bottom', 'caret-top', 'bottom-left', 'bottom-right', 'back', 'right', 'bottom', 'top', 'top-left', 'top-right', 'arrow-left', 'arrow-right', 'arrow-down', 'arrow-up', 'd-arrow-left', 'd-arrow-right', 'video-pause', 'video-play', 'refresh', 'refresh-right', 'refresh-left', 'finished', 'sort', 'sort-up', 'sort-down', 'rank', 'loading', 'view', 'c-scale-to-original', 'date', 'edit', 'edit-outline', 'folder', 'folder-opened', 'folder-add', 'folder-remove', 'folder-delete', 'folder-checked', 'tickets', 'document-remove', 'document-delete', 'document-copy', 'document-checked', 'document', 'document-add', 'printer', 'paperclip', 'takeaway-box', 'search', 'monitor', 'attract', 'mobile', 'scissors', 'umbrella', 'headset', 'brush', 'mouse', 'coordinate', 'magic-stick', 'reading', 'data-line', 'data-board', 'pie-chart', 'data-analysis', 'collection-tag', 'film', 'suitcase', 'suitcase-1', 'receiving', 'collection', 'files', 'notebook-1', 'notebook-2', 'toilet-paper', 'office-building', 'school', 'table-lamp', 'house', 'no-smoking', 'smoking', 'shopping-cart-full', 'shopping-cart-1', 'shopping-cart-2', 'shopping-bag-1', 'shopping-bag-2', 'sold-out', 'sell', 'present', 'box', 'bank-card', 'money', 'coin', 'wallet', 'discount', 'price-tag', 'news', 'guide', 'male', 'female', 'thumb', 'cpu', 'link', 'connection', 'open', 'turn-off', 'set-up', 'chat-round', 'chat-line-round', 'chat-square', 'chat-dot-round', 'chat-dot-square', 'chat-line-square', 'message', 'postcard', 'position', 'turn-off-microphone', 'microphone', 'close-notification', 'bangzhu', 'time', 'odometer', 'crop', 'aim', 'switch-button', 'full-screen', 'copy-document', 'mic', 'stopwatch', 'medal-1', 'medal', 'trophy', 'trophy-1', 'first-aid-kit', 'discover', 'place', 'location', 'location-outline', 'location-information', 'add-location', 'delete-location', 'map-location', 'alarm-clock', 'timer', 'watch-1', 'watch', 'lock', 'unlock', 'key', 'service', 'mobile-phone', 'bicycle', 'truck', 'ship', 'basketball', 'football', 'soccer', 'baseball', 'wind-power', 'light-rain', 'lightning', 'heavy-rain', 'sunrise', 'sunrise-1', 'sunset', 'sunny', 'cloudy', 'partly-cloudy', 'cloudy-and-sunny', 'moon', 'moon-night', 'dish', 'dish-1', 'food', 'chicken', 'fork-spoon', 'knife-fork', 'burger', 'tableware', 'sugar', 'dessert', 'ice-cream', 'hot-water', 'water-cup', 'coffee-cup', 'cold-drink', 'goblet', 'goblet-full', 'goblet-square', 'goblet-square-full', 'refrigerator', 'grape', 'watermelon', 'cherry', 'apple', 'pear', 'orange', 'coffee', 'ice-tea', 'ice-drink', 'milk-tea', 'potato-strips', 'lollipop', 'ice-cream-square', 'ice-cream-round'].map(s => 'el-icon-' + s)

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,61 @@
import { TypeUtil } from './utils/index'
import fontAwesome from './fontAwesome'
import elementUI from './elementUI'
import eIconList from './eIconList'
const add = function(list, item) {
let arr = []
if (item && TypeUtil.isArray(item)) {
arr = list.concat(item)
} else if (item && TypeUtil.isString(item)) {
arr = arr.concat(list)
arr.push(item)
}
return arr
}
const remove = function(list, item) {
if (item && TypeUtil.isArray(item)) {
for (let i = 0; i < item.length; i++) {
for (let j = 0; j < list.length; j++) {
if (list[j] === item[i]) {
list.splice(j, 1)
j--
}
}
}
} else if (item && TypeUtil.isString(item)) {
list = list.filter(function(i) {
return i !== item
})
}
return list
}
const iconList = {
list: [],
group: {},
addIcon: function(item) {
this.list = add(this.list, item)
},
addGroup: function(item) {
const { value, type } = item
this.group[type] = this.group[type] ? this.group[type] : []
if (TypeUtil.isArray(value)) {
this.group[type] = this.group[type].concat(value)
} else {
this.group[type].push(value)
}
},
initGroup: function(data) {
this.group = JSON.parse(JSON.stringify(data))
},
removeIcon: function(item) {
this.list = remove(this.list, item)
}
}
export { fontAwesome, elementUI, eIconList }
export default iconList

View File

@ -0,0 +1,542 @@
<template>
<div class="ui-fas">
<div
v-if="!!name"
class="selected-icon-container"
>
<span
title="icon"
:style="{color: color}"
>
<e-icon
:icon-name="name"
:title="name"
class="e-icon"
/>
</span>
</div>
<el-popover
ref="popover"
v-model="visible"
:disabled="disabled"
:placement="myPlacement"
popper-class="el-icon-popper"
:width="popoverWidth"
show-arrow
trigger="manual"
@show="setTempSelected"
>
<template slot="reference">
<slot
name="default"
:data="{prefixIcon,visible,placeholder,disabled,clearable,readonly,size}"
>
<el-input
ref="input"
v-model="proxyValue"
class="de-icon-picker-input"
:placeholder="dynamicPlaceholder"
:style="styles"
:clearable="clearable"
:disabled="disabled"
:readonly="true"
:size="size"
@input="_change"
@clear="_initIcon(false)"
@focus="_popoverShowFun(false)"
>
<template
v-if="showPrefix"
slot="prepend"
>
<slot
name="prepend"
:icon="prefixIcon"
>
<e-icon
:icon-name="prefixIcon"
class="e-icon"
/>
</slot>
</template>
</el-input>
</slot>
</template>
<div class="de-icon-picker-container">
<div class="top-container">
<el-color-picker
v-model="curColor"
show-alpha
@change="colorChange"
/>
<div class="top-sure-button-div">
<el-button
type="primary"
size="mini"
icon="el-icon-check"
@click.stop="sure"
/>
</div>
</div>
<el-divider class="top-divider" />
<el-scrollbar
v-if="!destroy"
ref="eScrollbar"
tag="div"
wrap-class="el-select-dropdown__wrap"
view-class="el-select-dropdown__list"
:class="'is-empty-'+id"
>
<ul
v-if="dataList && dataList.length > 0"
ref="fasIconList"
class="fas-icon-list"
>
<li
v-for="(item, index) in dataList"
:key="index"
class="picker-li"
:style="tempSelected === item && (highLightColor !== '' || !!curColor) ? {color: highLightColor || curColor, border: '1px solid ' + curColor} : ''"
@click="_selectedIcon(item)"
>
<slot
name="icon"
:icon="item"
>
<e-icon
:icon-name="item"
:title="item"
class="e-icon"
/>
</slot>
</li>
</ul>
<span
v-else
class="fas-no-data"
v-text="emptyText"
/>
</el-scrollbar>
</div>
</el-popover>
</div>
</template>
<script>
import iconList, { eIconList, elementUI, fontAwesome } from './iconList'
import { off, on } from './utils/index'
import EIcon from './eIcon/e-icon'
import ElInput from 'element-ui/lib/input'
import ElPopover from 'element-ui/lib/popover'
import ElScrollbar from 'element-ui/lib/scrollbar'
import { PopupManager } from 'element-ui/lib/utils/popup'
export default {
name: 'EIconPicker',
components: {
EIcon,
ElInput,
ElPopover,
ElScrollbar
},
props: {
disabled: {
type: Boolean,
default() {
return false
}
},
readonly: {
type: Boolean,
default() {
return false
}
},
clearable: {
type: Boolean,
default() {
return false
}
},
styles: {
type: Object,
default() {
return {}
}
},
placement: {
type: String,
default() {
return 'bottom'
}
},
value: {
type: String,
default() {
return ''
}
},
options: {
type: Object,
default: () => {}
},
width: {
type: Number,
default() {
return -1
}
},
size: {
type: String,
default() {
return 'medium'
}
},
placeholder: {
type: String,
default() {
return '请选择图标'
}
},
defaultIcon: {
type: String,
default() {
return 'eiconfont e-icon-bi'
}
},
emptyText: {
type: String,
default() {
return '暂无可选图标'
}
},
highLightColor: {
type: String,
default() {
return ''
}
},
zIndex: {
type: Number,
default() {
return null
}
},
showPrefix: {
type: Boolean,
default() {
return false
}
},
color: {
type: String,
default() {
return 'rgba(255, 0, 0, 1.0)'
}
}
},
data() {
return {
iconList: [],
visible: false,
prefixIcon: 'eiconfont e-icon-bi',
name: '',
icon: {},
myPlacement: 'bottom',
popoverWidth: 200,
destroy: false,
id: new Date().getTime(),
proxyValue: '',
curColor: '',
tempSelected: ''
}
},
computed: {
dataList: function() {
const arr1 = []
for (let i = 0, len = this.iconList.length; i < len; i++) {
if (arr1.indexOf(this.iconList[i]) === -1) {
arr1.push(this.iconList[i])
}
}
return arr1
},
dynamicPlaceholder() {
return this.name ? '' : this.placeholder
}
},
watch: {
value: function(val) {
setTimeout(() => {
this.name = val
this.prefixIcon = this.name ? this.name : this.defaultIcon
}, 50)
},
visible: function(val) {
if (val === false) {
this.$nextTick(() => {
off(document, 'mouseup', this._popoverHideFun)
})
} else {
this.$nextTick(() => {
this.createIconList()
on(document, 'mouseup', this._popoverHideFun)
})
}
},
options: {
handler(newV, oldV) {
const self = this
setTimeout(() => {
self._initIcon(true)
}, 50)
},
deep: true
}
},
mounted() {
this._updateW()
},
beforeDestroy() {
off(document, 'mouseup', this._popoverHideFun)
this.destroyIconList()
},
created() {
this.createIconList()
this._initIcon(true)
this.curColor = this.color
},
methods: {
colorChange(c) {
this.color = c
this.$emit('set-color', c)
},
setTempSelected() {
this.tempSelected = this.name
},
sure() {
this.visible = false
this.name = this.tempSelected
this.prefixIcon = this.name
this.color = this.curColor
this._emitFun(this.name)
this.$emit('set-color', this.curColor)
},
_change(val) {
this.iconList = this.icon.list.filter(function(i) {
return i.indexOf(val) !== -1
})
},
_initIcon(type) {
this.prefixIcon = this.value && type && type === true ? this.value : this.defaultIcon
this.name = type === true ? this.value : ''
this.icon = Object.assign({}, iconList)
if (this.options) {
this.icon.list = []
if (this.options.addIconList !== undefined &&
this.options.addIconList &&
this.options.addIconList.length > 0) {
this.icon.addIcon(this.options.addIconList)
}
if (this.options.removeIconList !== undefined &&
this.options.removeIconList &&
this.options.removeIconList.length > 0) {
this.icon.removeIcon(this.options.removeIconList)
}
if (this.options.FontAwesome === true) {
this.icon.addIcon(fontAwesome)
}
if (this.options.ElementUI === true) {
this.icon.addIcon(elementUI)
}
if (this.options.eIcon === true) {
if (this.options.eIconSymbol) {
const list = eIconList.map((item) => {
return item.replace('eiconfont ', '#')
})
this.icon.addIcon(list)
} else {
this.icon.addIcon(eIconList)
}
}
}
this.iconList = this.icon.list
if (this.placement && (this.placement === 'bottom' || this.placement === 'top')) {
this.myPlacement = this.placement
}
if (type === false) {
this._emitFun('')
}
},
addIcon(item = []) {
if (item !== undefined && item && item.length > 0) {
this.icon.addIcon(item)
this.iconList = this.icon.list
}
},
removeIcon(item = []) {
if (item !== undefined && item && item.length > 0) {
this.icon.removeIcon(item)
this.iconList = this.icon.list
}
},
updatePopper(zIndex) {
if (zIndex) {
PopupManager.zIndex = zIndex
}
this._popoverShowFun(true)
setTimeout(() => {
this.$refs.popover.updatePopper()
}, 100)
},
_selectedIcon(item) {
this.tempSelected = item
},
_updateW() {
this.$nextTick(() => {
if (this.width === -1 && this.$refs.input && this.$refs.input.$el) {
this.popoverWidth = this.$refs.input.$el.getBoundingClientRect().width - 36
} else {
this.popoverWidth = this.width
}
if (this.$refs.eScrollbar && this.$refs.eScrollbar.wrap) {
this.$refs.eScrollbar.wrap.scrollTop = 0
this.$refs.eScrollbar.handleScroll()
this.$refs.eScrollbar.update()
}
})
},
_popoverShowFun(flag) {
const _this = this
if (_this.readonly !== true && _this.disabled !== true) {
if (!flag && _this.zIndex) {
PopupManager.zIndex = this.zIndex
}
_this.visible = true
_this._updateW()
}
},
_popoverHideFun(e) {
const path = e.path || (e.composedPath && e.composedPath())
const isInside = path.some(list => {
return list.className && typeof list.className === 'string' && (list.className.indexOf('ui-fas') !== -1 || list.className.indexOf('de-icon-picker-container') !== -1)
})
if (!isInside) {
this.visible = false
}
const isInput = path.some(list => {
return list.className && typeof list.className === 'string' && list.className.indexOf('de-icon-picker-input') !== -1
})
if (this.visible && isInput) {
// this.visible = false
}
},
_emitFun(val) {
this.$emit('input', val)
this.$emit('change', val)
},
destroyIconList() {
this.destroy = true
},
createIconList() {
this.destroy = false
},
show() {
this._popoverShowFun(false)
},
hide() {
this.visible = false
}
}
}
</script>
<style lang="scss" scoped>
@import '~element-ui/lib/theme-chalk/input.css';
@import '~element-ui/lib/theme-chalk/popover.css';
@import '~element-ui/lib/theme-chalk/scrollbar.css';
@import '~element-ui/lib/theme-chalk/select-dropdown.css';
.fas-icon-list {
list-style-type: none;
margin: 0 0 0 -4px;
padding: 0;
display: flex;
flex-direction: row;
flex-wrap: wrap;
}
.ui-fas .el-input__inner {
cursor: pointer;
}
.fas-icon-list li {
width: 30px;
height: 30px;
margin: 5px;
}
.fas-icon-list li i, .fas-icon-list li svg {
font-size: 20px;
cursor: pointer;
}
.el-icon-popper {
max-height: 400px;
overflow: auto;
overflow-x: hidden;
overflow-y: hidden;
}
.el-icon-popper[x-placement^="bottom"] {
margin-top: 5px;
}
.fas-no-data {
display: block;
}
.e-icon {
font-size: 16px;
}
.top-divider {
margin: 5px 0 0 0 !important;
}
.top-container {
display: flex;
}
.top-sure-button-div {
margin: 4px 15px 0 auto;
::v-deep button {
width: 25px;
height: 20px;
padding: 4px 5px;
}
}
.selected-icon-container {
position: absolute;
z-index: 9;
width: 21%;
text-align: center;
margin-top: 2px;
pointer-events: none;
}
.picker-li {
text-align: center;
line-height: 30px;
}
</style>

View File

@ -0,0 +1,27 @@
export const TypeUtil = {
isArray: function(obj) {
return (typeof obj === 'object') && obj.constructor === Array
},
isString: function(obj) {
return (typeof obj === 'string') && obj.constructor === String
},
isNumber: function(obj) {
return (typeof obj === 'number') && obj.constructor === Number
},
isDate: function(obj) {
return (typeof obj === 'object') && obj.constructor === Date
},
isFunction: function(obj) {
return (typeof obj === 'function') && obj.constructor === Function
},
isObject: function(obj) {
return (typeof obj === 'object') && obj.constructor === Object
}
}

View File

@ -0,0 +1,36 @@
import { isServer } from './util'
export const on = (function() {
if (!isServer) {
if (document && document.addEventListener) {
return function(element, event, handler) {
if (element && event && handler) {
element.addEventListener(event, handler, false)
}
}
} else {
return function(element, event, handler) {
if (element && event && handler) {
element.attachEvent('on' + event, handler)
}
}
}
}
})()
export const off = (function() {
if (!isServer) {
if (document && document.removeEventListener) {
return function(element, event, handler) {
if (element && event) {
element.removeEventListener(event, handler, false)
}
}
} else {
return function(element, event, handler) {
if (element && event) {
element.detachEvent('on' + event, handler)
}
}
}
}
})()

View File

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

View File

@ -0,0 +1,28 @@
(function(e, d, w) {
if (!e.composedPath) {
e.composedPath = function() {
if (this.path) {
return this.path
}
let target = this.target
this.path = []
while (target.parentNode !== null) {
this.path.push(target)
target = target.parentNode
}
this.path.push(d, w)
return this.path
}
}
if (!String.prototype.startsWith) {
// eslint-disable-next-line no-extend-native
String.prototype.startsWith = function(search, pos) {
return this.substr(!pos || pos < 0 ? 0 : +pos, search.length) === search
}
}
})(Event.prototype, document, window)
export * from './util'
export * from './dom'
export * from './TypeUtil'

View File

@ -0,0 +1,53 @@
export const analyzingIconForIconfont = function(json) {
let font_family = ''
let css_prefix_text = ''
let list = []
if (json) {
if (json.font_family) {
font_family = json.font_family
}
if (json.css_prefix_text) {
css_prefix_text = json.css_prefix_text
}
if (json.glyphs) {
list = json.glyphs.map(function(value, index, array) {
return font_family + ' ' + css_prefix_text + value.font_class
})
}
}
return {
font_family,
css_prefix_text,
list
}
}
export const eIconSymbol = function(json) {
let font_family = ''
let css_prefix_text = ''
let list = []
if (json) {
if (json.font_family) {
font_family = json.font_family
}
if (json.css_prefix_text) {
css_prefix_text = json.css_prefix_text
}
if (json.glyphs) {
list = json.glyphs.map(function(value, index, array) {
return '#' + css_prefix_text + value.font_class
})
}
}
return {
font_family,
css_prefix_text,
list
}
}
export function isExternal(path) {
return /^(https?:|data:|\/\/?)/.test(path)
}
export const isServer = typeof window === 'undefined'

View File

@ -47,6 +47,7 @@ import { isSameVueObj, mergeCustomSortOption } from '@/utils'
import { getLinkToken, getToken } from '@/utils/auth'
import customInput from '@/components/widget/deWidget/customInput'
import { textSelectWidget } from '@/components/widget/deWidget/serviceNameFn.js'
export default {
components: { ElVisualSelect },
mixins: [customInput],
@ -251,10 +252,20 @@ export default {
handleElTagStyle() {
setTimeout(() => {
this.$refs['deSelect'] && this.$refs['deSelect'].$el && textSelectWidget(this.$refs['deSelect'].$el, this.element.style)
}, 50)
}, 500)
},
initLoad() {
this.value = this.fillValueDerfault()
this.initOptions()
if (this.element.options.value) {
this.value = this.fillValueDerfault()
this.changeValue(this.value)
}
},
refreshLoad() {
this.initOptions()
},
initOptions() {
this.data = []
if (this.element.options.attrs.fieldId) {
let method = multFieldValues
@ -273,10 +284,6 @@ export default {
bus.$emit('valid-values-change', false)
})
}
if (this.element.options.value) {
this.value = this.fillValueDerfault()
this.changeValue(this.value)
}
},
visualChange(value) {
this.value = value

View File

@ -286,6 +286,16 @@ export default {
textSelectGridWidget: textSelectGridWidget,
initLoad() {
this.value = this.element.options.attrs.multiple ? [] : null
this.initOptions()
if (this.element.options.value) {
this.value = this.fillValueDerfault()
this.changeValue(this.value)
}
},
refreshLoad() {
this.initOptions()
},
initOptions() {
if (this.element.options.attrs.fieldId) {
let method = multFieldValues
const token = this.$store.getters.token || getToken()
@ -305,10 +315,6 @@ export default {
}
})
}
if (this.element.options.value) {
this.value = this.fillValueDerfault()
this.changeValue(this.value)
}
},
changeValue(value) {
if (!this.inDraw) {

View File

@ -265,6 +265,17 @@ export default {
},
initLoad() {
this.value = this.fillValueDerfault()
this.data = []
this.initOptions()
if (this.element.options.value) {
this.value = this.fillValueDerfault()
this.changeValue(this.value)
}
},
refreshLoad() {
this.initOptions()
},
initOptions() {
this.data = []
if (this.element.options.attrs.fieldId) {
let method = mappingFieldValues
@ -283,10 +294,6 @@ export default {
})
})
}
if (this.element.options.value) {
this.value = this.fillValueDerfault()
this.changeValue(this.value)
}
},
changeValue(value) {
if (!this.inDraw) {

View File

@ -79,7 +79,7 @@
:canvas-style-data="canvasStyleData"
:canvas-id="element.id+'-'+item.name"
:panel-info="panelInfo"
:in-screen="true"
:in-screen="inScreen"
:show-position="showPosition"
/>
</div>
@ -232,6 +232,11 @@ export default {
name: 'DeTabs',
components: { TextAttr, Preview, DeCanvasTab, TabUseList, ViewSelect, DataeaseTabs },
props: {
inScreen: {
type: Boolean,
required: false,
default: true
},
canvasId: {
type: String,
default: 'canvas-main'
@ -635,7 +640,7 @@ export default {
while (len--) {
if (this.element.options.tabList[len].name === param.name) {
this.element.options.tabList.splice(len, 1)
this.$store.commit('deleteComponentsWithCanvasId', this.element.id + '-' + param.name)
const activeIndex = (len - 1 + this.element.options.tabList.length) % this.element.options.tabList.length
this.activeTabName = this.element.options.tabList[activeIndex].name
}

View File

@ -99,6 +99,9 @@ class TextSelectGridServiceImpl extends WidgetService {
isCustomSortWidget() {
return true
}
isChinesSortWidget() {
return true
}
fillValueDerfault(element) {
const defaultV = element.options.value === null ? '' : element.options.value.toString()
if (element.options.attrs.multiple) {

View File

@ -105,7 +105,9 @@ class TextSelectServiceImpl extends WidgetService {
isParamWidget() {
return true
}
isChinesSortWidget() {
return true
}
fillValueDerfault(element) {
const defaultV = element.options.value === null ? '' : element.options.value.toString()
if (element.options.attrs.multiple) {

View File

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

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="200px" height="200.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M423.731142 161.571862 423.731142 249.306043 713.416847 249.306043 160.428318 802.295596 221.877855 863.682711 774.803963 310.790372 774.803963 600.443331 862.637404 600.443331 862.637404 161.571862Z" /></svg>

After

Width:  |  Height:  |  Size: 476 B

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="200px" height="200.00px" viewBox="0 0 1000 1000" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M362.57 764.226h364.149c28.44 0 51.491-23.051 51.491-51.491v-364.149c0-28.44-23.051-51.491-51.491-51.491s-51.491 23.051-51.491 51.491v239.829l-349.073-349.073c-20.119-20.119-52.711-20.119-72.831 0s-20.119 52.711 0 72.831l349.073 349.073h-239.829c-14.202-0.001-27.093 5.754-36.415 15.076s-15.094 22.195-15.076 36.415c0 28.44 23.051 51.491 51.491 51.491z" /></svg>

After

Width:  |  Height:  |  Size: 629 B

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="200px" height="200.00px" viewBox="0 0 1000 1000" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M661.43 259.774h-364.149c-28.44 0-51.491 23.051-51.491 51.491v364.149c0 28.44 23.051 51.491 51.491 51.491s51.491-23.051 51.491-51.491v-239.829l349.073 349.073c20.119 20.119 52.711 20.119 72.831 0s20.119-52.711 0-72.831l-349.073-349.073h239.829c14.202 0.001 27.093-5.754 36.415-15.076s15.094-22.195 15.076-36.415c0-28.44-23.051-51.491-51.491-51.491z" /></svg>

After

Width:  |  Height:  |  Size: 625 B

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="200px" height="200.00px" viewBox="0 0 1000 1000" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M259.774 362.57v364.149c0 28.44 23.051 51.491 51.491 51.491h364.149c28.44 0 51.491-23.051 51.491-51.491s-23.051-51.491-51.491-51.491h-239.829l349.073-349.073c20.119-20.119 20.119-52.711 0-72.831s-52.711-20.119-72.831 0l-349.073 349.073v-239.829c0.001-14.202-5.754-27.093-15.076-36.415s-22.195-15.094-36.415-15.076c-28.44 0-51.491 23.051-51.491 51.491z" /></svg>

After

Width:  |  Height:  |  Size: 628 B

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="200px" height="200.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M470.016 976.896q-44.032 0-59.392-20.48t-15.36-65.536q0-20.48-0.512-64.512t-1.024-93.696-1.536-96.768-1.024-74.752q0-39.936-7.68-62.464t-35.328-21.504q-20.48 0-48.64-1.024t-49.664 0q-35.84 0-45.568-19.456t13.824-50.176q24.576-30.72 57.344-72.704t67.584-86.016 68.096-87.04 58.88-75.776q23.552-29.696 45.568-30.72t46.592 26.624q24.576 29.696 56.832 69.632t67.072 82.432 68.608 83.968 60.416 73.216q29.696 35.84 23.04 58.88t-43.52 23.04q-11.264 0-25.088 0.512t-29.184 1.024-30.208 1.024-27.136 0.512q-25.6 1.024-32.256 16.384t-5.632 41.984q0 29.696 0.512 77.824t1.024 100.352 1.536 101.376 1.024 79.872q0 13.312-2.048 27.648t-9.728 26.112-21.504 19.968-36.352 8.192q-27.648 0-52.736 0.512t-56.832 1.536z" /></svg>

After

Width:  |  Height:  |  Size: 978 B

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="200px" height="200.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M47.104 453.632q0-43.008 20.992-57.856t66.048-14.848q20.48 0 64.512 0.512t93.696 0.512 96.768 0.512 74.752 0.512q38.912 1.024 61.44-6.656t22.528-35.328q0-20.48 1.536-48.64t1.536-48.64q1.024-35.84 20.48-45.568t49.152 14.848q30.72 24.576 71.68 58.368t84.992 69.12 86.016 69.632 74.752 59.904q29.696 24.576 30.208 46.592t-28.16 45.568q-29.696 24.576-70.144 56.32t-83.968 65.536-85.504 67.072-74.752 58.88q-35.84 28.672-58.88 21.504t-22.016-44.032l0-24.576 0-29.696q0-15.36-0.512-30.208t-0.512-27.136q0-25.6-15.36-32.256t-41.984-6.656q-29.696 0-77.824-0.512t-100.352-0.512-101.376-0.512-79.872-0.512q-13.312 0-27.648-2.56t-26.112-9.728-18.944-20.992-7.168-37.376q0-27.648-0.512-53.248t0.512-57.344z" /></svg>

After

Width:  |  Height:  |  Size: 971 B

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="200px" height="200.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M966.656 567.296q0 43.008-20.48 58.368t-65.536 15.36l-64.512 0q-44.032 0-93.696 0.512t-96.768 0.512l-74.752 0q-38.912 0-61.952 7.68t-22.016 35.328q0 20.48-1.024 48.64t-1.024 49.664q0 35.84-19.456 45.568t-50.176-13.824q-30.72-24.576-72.704-57.856t-85.504-68.096-86.016-68.608-75.264-59.392q-30.72-24.576-31.232-46.592t28.16-45.568q28.672-24.576 68.608-56.832t82.944-66.56 84.48-68.096 74.24-60.416q35.84-28.672 58.88-22.016t23.04 43.52l0 25.6q0 14.336 0.512 29.696t1.024 30.208 0.512 26.112q1.024 25.6 16.384 32.256t41.984 6.656q29.696 0 77.824-0.512t100.352-0.512 101.376-0.512 79.872-0.512q13.312 0 27.648 2.048t26.112 9.728 19.456 21.504 7.68 36.352q0 27.648 0.512 53.248t0.512 57.344z" /></svg>

After

Width:  |  Height:  |  Size: 964 B

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="200px" height="200.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M564.224 44.032q43.008 0 58.368 20.48t15.36 65.536q0 20.48 0.512 64.512t0.512 93.696 0.512 96.768 0.512 74.752q0 38.912 7.68 61.952t35.328 22.016q19.456 0 48.128 1.024t49.152 1.024q35.84 0 45.568 18.944t-13.824 49.664q-24.576 30.72-57.344 72.704t-68.096 86.016-69.12 86.528-59.392 75.264q-23.552 29.696-45.568 30.72t-45.568-27.648q-24.576-29.696-57.344-69.632t-67.072-82.432-67.584-83.968-59.904-74.24q-29.696-35.84-22.528-58.88t44.032-23.04l24.576 0q14.336 0 29.696-0.512t30.208-1.536 26.112-1.024q26.624 0 32.768-15.36t6.144-41.984q0-29.696-0.512-77.824t-0.512-100.352-0.512-101.376-0.512-79.872q0-13.312 2.048-27.648t9.728-26.112 20.992-19.456 36.864-7.68q27.648 0 53.248-0.512t57.344-0.512z" /></svg>

After

Width:  |  Height:  |  Size: 971 B

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="200px" height="200.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M65.582671 735.208665l446.417329-446.41733 446.417329 446.41733z" /></svg>

After

Width:  |  Height:  |  Size: 341 B

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="200px" height="200.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M65.582671 288.791335l446.417329 446.41733 446.417329-446.41733z" /></svg>

After

Width:  |  Height:  |  Size: 341 B

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="200px" height="200.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M735.208665 65.582671l-446.41733 446.417329 446.41733 446.417329z" /></svg>

After

Width:  |  Height:  |  Size: 342 B

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="200px" height="200.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M288.791335 65.582671l446.41733 446.417329-446.41733 446.417329z" /></svg>

After

Width:  |  Height:  |  Size: 341 B

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="200px" height="200.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M512 69.479l442.498 442.498-442.498 442.498-442.498-442.498 442.498-442.498z" /></svg>

After

Width:  |  Height:  |  Size: 353 B

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="200px" height="200.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M71.675 893.33l440.325-762.683 440.325 762.683z" /></svg>

After

Width:  |  Height:  |  Size: 324 B

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="200px" height="200.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M62 512c0 248.528 201.472 450 450 450s450-201.472 450-450c0-248.528-201.472-450-450-450-248.528 0-450 201.472-450 450z" /></svg>

After

Width:  |  Height:  |  Size: 395 B

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="200px" height="200.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M512 63.34l141.072 285.815 315.433 45.84-228.24 222.503 53.879 314.185-282.144-148.368-282.144 148.368 53.879-314.185-228.24-222.503 315.433-45.84z" /></svg>

After

Width:  |  Height:  |  Size: 424 B

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="200px" height="200.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M62 62h900v900h-900v-900z" /></svg>

After

Width:  |  Height:  |  Size: 302 B

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="200px" height="200.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M152.474 62.225c-26.856 0-56.286 21.748-56.286 48.663v802.451c0 26.798 28.773 48.653 55.579 48.653 26.789 0 56.286-21.857 56.286-48.663v-802.434c0-26.914-28.78-48.663-55.579-48.663zM730.146 129.011c-157.836 0-157.836-64.694-315.663-64.694-91.108 0-161.46 42.504-161.46 42.504l-0.658 484.313s71.010-42.446 162.119-42.446c157.827 0 157.827 64.694 315.663 64.694 98.74 0 197.923-51.845 197.923-51.845v-484.264s-99.183 51.737-197.923 51.737z" /></svg>

After

Width:  |  Height:  |  Size: 714 B

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="200px" height="200.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M512 64C264.8 64 64 264.8 64 512s200.8 448 448 448 448-200.8 448-448S759.2 64 512 64z m238.4 641.6l-45.6 45.6L512 557.6 318.4 750.4l-45.6-45.6L467.2 512 273.6 318.4l45.6-45.6L512 467.2l193.6-193.6 45.6 45.6L557.6 512l192.8 193.6z" /></svg>

After

Width:  |  Height:  |  Size: 506 B

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="200px" height="200.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M512 64C264.8 64 64 264.8 64 512s200.8 448 448 448 448-200.8 448-448S759.2 64 512 64z m32 704h-64v-64h64v64z m-64-128V256h64v384h-64z" /></svg>

After

Width:  |  Height:  |  Size: 410 B

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="200px" height="200.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M512 64C264.8 64 64 264.8 64 512s200.8 448 448 448 448-200.8 448-448S759.2 64 512 64z m32 704h-64v-64h64v64z m11.2-203.2l-5.6 4.8c-3.2 2.4-5.6 8-5.6 12.8v58.4h-64v-58.4c0-24.8 11.2-48 29.6-63.2l5.6-4.8c56-44.8 83.2-68 83.2-108C598.4 358.4 560 320 512 320c-49.6 0-86.4 36.8-86.4 86.4h-64C361.6 322.4 428 256 512 256c83.2 0 150.4 67.2 150.4 150.4 0 72.8-49.6 112.8-107.2 158.4z" /></svg>

After

Width:  |  Height:  |  Size: 652 B

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="200px" height="200.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M512 64C264.8 64 64 264.8 64 512s200.8 448 448 448 448-200.8 448-448S759.2 64 512 64zM428 718.4l-45.6 45.6-45.6-45.6-116-117.6 45.6-45.6L383.2 672l367.2-367.2 45.6 45.6-368 368z" /></svg>

After

Width:  |  Height:  |  Size: 454 B

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="200px" height="200.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M883.075899 428.228061l-267.119757-22.906709-104.369046-246.226914-104.363929 246.226914-267.122827 22.906709 202.63714 175.596274-60.72606 261.081227 229.575676-138.430816 229.577722 138.374534-60.780295-261.134439L883.075899 428.228061zM511.587096 656.715963 511.587096 311.183322l63.559595 149.966547 162.695452 14.038738-123.465986 106.871029 37.002752 158.998247L511.587096 656.715963z" /></svg>

After

Width:  |  Height:  |  Size: 667 B

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="200px" height="200.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M509.867 189.867L608 411.733l243.2 25.6-181.333 162.134 51.2 238.933-211.2-121.6-211.2 121.6 51.2-238.933L168.533 435.2l243.2-25.6 98.134-219.733z" /></svg>

After

Width:  |  Height:  |  Size: 423 B

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="200px" height="200.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M512 128c52 0 102.4 10.4 149.6 30.4 45.6 19.2 86.4 47.2 122.4 82.4s63.2 76 82.4 122.4c20 47.2 30.4 97.6 30.4 149.6s-10.4 102.4-30.4 149.6c-19.2 45.6-47.2 86.4-82.4 122.4s-76.8 63.2-122.4 82.4c-47.2 20-97.6 30.4-149.6 30.4s-102.4-10.4-149.6-30.4c-45.6-19.2-86.4-47.2-122.4-82.4s-63.2-76.8-82.4-122.4C138.4 614.4 128 564 128 512s10.4-102.4 30.4-149.6C177.6 316.8 204.8 276 240 240s76-63.2 122.4-82.4C409.6 138.4 460 128 512 128m0-64C264.8 64 64 264.8 64 512s200.8 448 448 448 448-200.8 448-448S759.2 64 512 64zM288 384c0 35.2 28.8 64 64 64s64-28.8 64-64-28.8-64-64-64-64 28.8-64 64z m320 0.8c0 35.2 28.8 64 64 64s64-28.8 64-64-28.8-64-64-64-64 28-64 64zM512 768c46.4 0 92-15.2 132-44.8 37.6-28 68.8-67.2 91.2-114.4 8-16 0.8-35.2-15.2-42.4-16-8-35.2-0.8-42.4 15.2-17.6 37.6-43.2 68.8-72 90.4-28 20.8-60.8 32-93.6 32s-64.8-11.2-93.6-32.8c-28.8-21.6-53.6-52.8-72-90.4-8-16-27.2-22.4-42.4-15.2-16 8-22.4 26.4-15.2 42.4 22.4 47.2 54.4 86.4 91.2 114.4 40 30.4 85.6 45.6 132 45.6z" /></svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="200px" height="200.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M512 128c52 0 102.4 10.4 149.6 30.4 45.6 19.2 86.4 47.2 122.4 82.4s63.2 76 82.4 122.4c20 47.2 30.4 97.6 30.4 149.6s-10.4 102.4-30.4 149.6c-19.2 45.6-47.2 86.4-82.4 122.4s-76.8 63.2-122.4 82.4c-47.2 20-97.6 30.4-149.6 30.4s-102.4-10.4-149.6-30.4c-45.6-19.2-86.4-47.2-122.4-82.4s-63.2-76.8-82.4-122.4C138.4 614.4 128 564 128 512s10.4-102.4 30.4-149.6C177.6 316.8 204.8 276 240 240s76-63.2 122.4-82.4C409.6 138.4 460 128 512 128m0-64C264.8 64 64 264.8 64 512s200.8 448 448 448 448-200.8 448-448S759.2 64 512 64zM288 384c0 35.2 28.8 64 64 64s64-28.8 64-64-28.8-64-64-64-64 28-64 64z m320 0c0 35.2 28.8 64 64 64s64-28.8 64-64-28.8-64-64-64-64 28.8-64 64z m96 288c0-17.6-14.4-32-32-32H352c-17.6 0-32 14.4-32 32s14.4 32 32 32h320c17.6 0 32-14.4 32-32z" /></svg>

After

Width:  |  Height:  |  Size: 1021 B

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="200px" height="200.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M512 128c52 0 102.4 10.4 149.6 30.4 45.6 19.2 86.4 47.2 122.4 82.4s63.2 76 82.4 122.4c20 47.2 30.4 97.6 30.4 149.6s-10.4 102.4-30.4 149.6c-19.2 45.6-47.2 86.4-82.4 122.4s-76.8 63.2-122.4 82.4c-47.2 20-97.6 30.4-149.6 30.4s-102.4-10.4-149.6-30.4c-45.6-19.2-86.4-47.2-122.4-82.4s-63.2-76.8-82.4-122.4C138.4 614.4 128 564 128 512s10.4-102.4 30.4-149.6C177.6 316.8 204.8 276 240 240s76-63.2 122.4-82.4C409.6 138.4 460 128 512 128m0-64C264.8 64 64 264.8 64 512s200.8 448 448 448 448-200.8 448-448S759.2 64 512 64z" /><path d="M288 384c0 35.2 28.8 64 64 64s64-28.8 64-64-28.8-64-64-64-64 28.8-64 64zM608 384c0 35.2 28.8 64 64 64s64-28.8 64-64-28.8-64-64-64-64 28.8-64 64zM513.6 512.8c-46.4 0-92 15.2-132 44.8C344 585.6 312 624.8 289.6 672c-8 16-0.8 35.2 15.2 42.4 16 7.2 35.2 0.8 42.4-15.2 17.6-37.6 42.4-68.8 72-90.4C448 587.2 480 576 512.8 576s64.8 11.2 93.6 32.8c28.8 21.6 53.6 52.8 72 90.4 7.2 16 26.4 22.4 42.4 15.2 16-7.2 22.4-26.4 15.2-42.4-22.4-47.2-54.4-86.4-91.2-114.4-39.2-29.6-84.8-44.8-131.2-44.8z" /></svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="200px" height="200.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M320 834.4V491.2c0-10.4 5.6-20 14.4-25.6 79.2-48 220-168.8 220-271.2 0-4.8-5.6-66.4 40.8-66.4 0 0 118.4 28 44.8 320h208s47.2-4 47.2 48.8c0 0 2.4 66.4-67.2 324.8 0 0-21.6 74.4-48.8 74.4 0 0-340-32-431.2-32-15.2 0-28-13.6-28-29.6z m-173.6 34.4l96-4c8-1.6 13.6-8 13.6-16V494.4c0-8-5.6-14.4-13.6-16l-96-3.2c-9.6-1.6-18.4 5.6-18.4 16v361.6c-0.8 10.4 8 17.6 18.4 16z" /></svg>

After

Width:  |  Height:  |  Size: 637 B

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="200px" height="200.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M320 189.6v343.2c0 10.4 5.6 20 14.4 25.6 80 48 220.8 168.8 220.8 271.2 0 4.8-5.6 66.4 40.8 66.4 0 0 118.4-28 44.8-320h208s48 4 48-48.8c0 0 2.4-66.4-68-324.8 0 0-21.6-74.4-48.8-74.4 0 0-340 32-430.4 32-16.8 0-29.6 12.8-29.6 29.6zM146.4 155.2l96 4c8 1.6 13.6 8 13.6 16v355.2c0 8-5.6 14.4-13.6 16l-96 3.2c-9.6 1.6-18.4-5.6-18.4-16V171.2c0-10.4 8.8-17.6 18.4-16z" /></svg>

After

Width:  |  Height:  |  Size: 635 B

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="200px" height="200.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M512 64C264.8 64 64 264.8 64 512s200.8 448 448 448 448-200.8 448-448S759.2 64 512 64zM340.8 525.6c0 4.8-4 9.6-8.8 10.4l-64 2.4c-5.6 0.8-12-4-12-10.4V288c0-6.4 5.6-11.2 12.8-10.4l64 2.4c4.8 0.8 8.8 5.6 8.8 10.4v235.2z m424-2.4c0 35.2-31.2 32.8-31.2 32.8H596C644.8 749.6 566.4 768 566.4 768c-30.4 0-27.2-40.8-27.2-44C539.2 656 446.4 576 393.6 544c-5.6-3.2-9.6-9.6-9.6-16.8V299.2c0-10.4 8.8-19.2 19.2-19.2 60 0 284-21.6 284-21.6 17.6 0 32 49.6 32 49.6 47.2 171.2 45.6 215.2 45.6 215.2z" /></svg>

After

Width:  |  Height:  |  Size: 759 B

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