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

This commit is contained in:
wisonic-s 2023-12-18 11:13:51 +08:00
commit 3ea84269d0
39 changed files with 708 additions and 80 deletions

View File

@ -10,6 +10,8 @@ public interface ExtAuthService {
Set<Long> userIdsByRD(AuthURD request); Set<Long> userIdsByRD(AuthURD request);
Set<String> userNamesByRD(AuthURD request);
AuthURD resourceTarget(String resourceId); AuthURD resourceTarget(String resourceId);
List<AuthItem> dataSourceIdByUser(Long userId); List<AuthItem> dataSourceIdByUser(Long userId);

View File

@ -43,6 +43,21 @@ public class ExtAuthServiceImpl implements ExtAuthService {
return result; return result;
} }
@Override
public Set<String> userNamesByRD(AuthURD request) {
Set<String> result = new HashSet<>();
List<Long> roleIds = request.getRoleIds();
List<Long> deptIds = request.getDeptIds();
if (!CollectionUtils.isEmpty(roleIds)) {
result.addAll(extAuthMapper.queryUserNameWithRoleIds(roleIds));
}
if (!CollectionUtils.isEmpty(deptIds)) {
result.addAll(extAuthMapper.queryUserNameWithDeptIds(deptIds));
}
return result;
}
@Override @Override
public AuthURD resourceTarget(String resourceId) { public AuthURD resourceTarget(String resourceId) {
AuthURD authURD = new AuthURD(); AuthURD authURD = new AuthURD();

View File

@ -71,6 +71,10 @@ public class AuthUtils {
return userIds; return userIds;
} }
public static Set<String> accountByURD(AuthURD request) {
return extAuthService.userNamesByRD(request);
}
public static List<String> parentResources(String resourceId, String type) { public static List<String> parentResources(String resourceId, String type) {
return extAuthService.parentResource(resourceId, type); return extAuthService.parentResource(resourceId, type);
} }

View File

@ -11,8 +11,10 @@ import java.util.List;
public interface ExtAuthMapper { public interface ExtAuthMapper {
List<Long> queryUserIdWithRoleIds(@Param("roleIds") List<Long> roleIds); List<Long> queryUserIdWithRoleIds(@Param("roleIds") List<Long> roleIds);
List<String> queryUserNameWithRoleIds(@Param("roleIds") List<Long> roleIds);
List<Long> queryUserIdWithDeptIds(@Param("deptIds") List<Long> deptIds); List<Long> queryUserIdWithDeptIds(@Param("deptIds") List<Long> deptIds);
List<String> queryUserNameWithDeptIds(@Param("deptIds") List<Long> deptIds);
List<SysAuth> queryByResource(@Param("resourceId") String resourceId); List<SysAuth> queryByResource(@Param("resourceId") String resourceId);

View File

@ -16,6 +16,16 @@
</foreach> </foreach>
</select> </select>
<select id="queryUserNameWithRoleIds" resultType="java.lang.String" >
select su.username
from sys_user su
left join sys_users_roles sur on sur.user_id = su.user_id
where sur.role_id in
<foreach collection="roleIds" item="roleId" open='(' separator=',' close=')'>
#{roleId}
</foreach>
</select>
<select id="queryUserIdWithDeptIds" resultType="java.lang.Long" > <select id="queryUserIdWithDeptIds" resultType="java.lang.Long" >
select user_id select user_id
@ -26,6 +36,15 @@
</foreach> </foreach>
</select> </select>
<select id="queryUserNameWithDeptIds" resultType="java.lang.String" >
select username
from sys_user
where dept_id in
<foreach collection="deptIds" item="deptId" open='(' separator=',' close=')'>
#{deptId}
</foreach>
</select>
<select id="queryByResource" resultMap="io.dataease.plugins.common.base.mapper.SysAuthMapper.BaseResultMap" > <select id="queryByResource" resultMap="io.dataease.plugins.common.base.mapper.SysAuthMapper.BaseResultMap" >
select a.* select a.*

View File

@ -6,6 +6,7 @@ import io.dataease.auth.entity.TokenInfo;
import io.dataease.auth.service.AuthUserService; import io.dataease.auth.service.AuthUserService;
import io.dataease.auth.service.impl.AuthUserServiceImpl; import io.dataease.auth.service.impl.AuthUserServiceImpl;
import io.dataease.auth.util.JWTUtils; import io.dataease.auth.util.JWTUtils;
import io.dataease.commons.model.AuthURD;
import io.dataease.commons.utils.*; import io.dataease.commons.utils.*;
import io.dataease.dto.PermissionProxy; import io.dataease.dto.PermissionProxy;
import io.dataease.dto.chart.ViewOption; import io.dataease.dto.chart.ViewOption;
@ -45,10 +46,7 @@ import org.springframework.web.util.HtmlUtils;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.io.File; import java.io.File;
import java.util.ArrayList; import java.util.*;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@Service("emailTaskHandler") @Service("emailTaskHandler")
@ -157,6 +155,27 @@ public class EmailTaskHandler extends TaskHandler implements Job {
emailXpackService.saveInstance(taskInstance); emailXpackService.saveInstance(taskInstance);
} }
private void formatReci(XpackEmailTemplateDTO emailTemplateDTO) {
String reciUsers = emailTemplateDTO.getReciUsers();
String roleList = emailTemplateDTO.getRoleList();
String orgList = emailTemplateDTO.getOrgList();
AuthURD authURD = new AuthURD();
if (StringUtils.isNotBlank(roleList)) {
authURD.setRoleIds(Arrays.stream(roleList.split(",")).map(Long::parseLong).collect(Collectors.toList()));
}
if (StringUtils.isNotBlank(orgList)) {
authURD.setDeptIds(Arrays.stream(orgList.split(",")).map(Long::parseLong).collect(Collectors.toList()));
}
Set<String> accountSet = AuthUtils.accountByURD(authURD);
if (accountSet == null) accountSet = new HashSet<>();
if (StringUtils.isNotBlank(reciUsers)) {
accountSet.addAll(Arrays.stream(reciUsers.split(",")).collect(Collectors.toSet()));
}
if (CollectionUtils.isNotEmpty(accountSet)) {
emailTemplateDTO.setReciUsers(String.join(",", accountSet));
}
}
@Async("priorityExecutor") @Async("priorityExecutor")
public void sendReport(GlobalTaskInstance taskInstance, SysUserEntity user, Boolean isTempTask) { public void sendReport(GlobalTaskInstance taskInstance, SysUserEntity user, Boolean isTempTask) {
@ -177,6 +196,9 @@ public class EmailTaskHandler extends TaskHandler implements Job {
token = tokenByUser(user); token = tokenByUser(user);
XpackPixelEntity xpackPixelEntity = buildPixel(emailTemplateDTO); XpackPixelEntity xpackPixelEntity = buildPixel(emailTemplateDTO);
// 下面继续执行发送邮件的 // 下面继续执行发送邮件的
if (StringUtils.isNotBlank(emailTemplateDTO.getRoleList()) || StringUtils.isNotBlank(emailTemplateDTO.getOrgList()))
formatReci(emailTemplateDTO);
LogUtil.info(String.format("recipients list is [%s]", emailTemplateDTO.getReciUsers()));
String recipients = emailTemplateDTO.getRecipients(); String recipients = emailTemplateDTO.getRecipients();
String reciUsers = emailTemplateDTO.getReciUsers(); String reciUsers = emailTemplateDTO.getReciUsers();
Integer extWaitTime = emailTemplateDTO.getExtWaitTime(); Integer extWaitTime = emailTemplateDTO.getExtWaitTime();

View File

@ -636,7 +636,9 @@ public class ChartViewService {
if (StringUtils.equalsIgnoreCase(view.getType(), "table-pivot") if (StringUtils.equalsIgnoreCase(view.getType(), "table-pivot")
|| StringUtils.containsIgnoreCase(view.getType(), "group") || StringUtils.containsIgnoreCase(view.getType(), "group")
|| ("antv".equalsIgnoreCase(view.getRender()) && "line".equalsIgnoreCase(view.getType())) || ("antv".equalsIgnoreCase(view.getRender()) && "line".equalsIgnoreCase(view.getType()))
|| StringUtils.equalsIgnoreCase(view.getType(), "flow-map")) { || StringUtils.equalsIgnoreCase(view.getType(), "flow-map")
|| StringUtils.equalsIgnoreCase(view.getType(), "bar-time-range")
) {
xAxis.addAll(xAxisExt); xAxis.addAll(xAxisExt);
} }
List<ChartViewFieldDTO> yAxis = gson.fromJson(view.getYAxis(), tokenType); List<ChartViewFieldDTO> yAxis = gson.fromJson(view.getYAxis(), tokenType);
@ -1421,6 +1423,8 @@ public class ChartViewService {
mapChart = ChartDataBuild.transBaseGroupDataAntV(xAxisBase, xAxis, xAxisExt, yAxis, view, data, isDrill); mapChart = ChartDataBuild.transBaseGroupDataAntV(xAxisBase, xAxis, xAxisExt, yAxis, view, data, isDrill);
} else if (StringUtils.equalsIgnoreCase(view.getType(), "bar-group-stack")) { } else if (StringUtils.equalsIgnoreCase(view.getType(), "bar-group-stack")) {
mapChart = ChartDataBuild.transGroupStackDataAntV(xAxisBase, xAxis, xAxisExt, yAxis, extStack, data, view, isDrill); mapChart = ChartDataBuild.transGroupStackDataAntV(xAxisBase, xAxis, xAxisExt, yAxis, extStack, data, view, isDrill);
} else if (StringUtils.equalsIgnoreCase(view.getType(), "bar-time-range")) {
mapChart = ChartDataBuild.transTimeBarDataAntV(xAxisBase, xAxis, xAxisExt, yAxis, extStack, data, view, isDrill);
} else if (StringUtils.containsIgnoreCase(view.getType(), "bar-stack")) { } else if (StringUtils.containsIgnoreCase(view.getType(), "bar-stack")) {
mapChart = ChartDataBuild.transStackChartDataAntV(xAxis, yAxis, view, data, extStack, isDrill); mapChart = ChartDataBuild.transStackChartDataAntV(xAxis, yAxis, view, data, extStack, isDrill);
} else if (StringUtils.containsIgnoreCase(view.getType(), "line-stack")) { } else if (StringUtils.containsIgnoreCase(view.getType(), "line-stack")) {

View File

@ -11,6 +11,7 @@ import org.apache.commons.lang3.StringUtils;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.math.RoundingMode; import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.util.*; import java.util.*;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -1282,6 +1283,120 @@ public class ChartDataBuild {
} }
} }
private static String getDateFormat(String dateStyle, String datePattern) {
String split;
if (StringUtils.equalsIgnoreCase(datePattern, "date_split")) {
split = "/";
} else {
split = "-";
}
switch (dateStyle) {
case "y":
return "yyyy";
case "y_M":
return "yyyy" + split + "MM";
case "y_M_d":
return "yyyy" + split + "MM" + split + "dd";
case "H_m_s":
return "HH:mm:ss";
case "y_M_d_H":
return "yyyy" + split + "MM" + split + "dd" + " HH";
case "y_M_d_H_m":
return "yyyy" + split + "MM" + split + "dd" + " HH:mm";
case "y_M_d_H_m_s":
return "yyyy" + split + "MM" + split + "dd" + " HH:mm:ss";
default:
return "yyyy-MM-dd HH:mm:ss";
}
}
public static Map<String, Object> transTimeBarDataAntV(List<ChartViewFieldDTO> xAxisBase, List<ChartViewFieldDTO> xAxis, List<ChartViewFieldDTO> xAxisExt, List<ChartViewFieldDTO> yAxis, List<ChartViewFieldDTO> extStack, List<String[]> data, ChartViewWithBLOBs view, boolean isDrill) {
Map<String, Object> map = new HashMap<>();
if (CollectionUtils.isEmpty(xAxisBase) || CollectionUtils.isEmpty(xAxisExt) || xAxisExt.size() < 2) {
map.put("data", new ArrayList<>());
return map;
}
if (xAxisExt.stream().filter(ext -> !ext.isDrill()).count() != 2) {
map.put("data", new ArrayList<>());
return map;
}
List<Date> dates = new ArrayList<>();
ChartViewFieldDTO xAxis1 = xAxis.get(xAxisBase.size());
SimpleDateFormat sdf = new SimpleDateFormat(getDateFormat(xAxis1.getDateStyle(), xAxis1.getDatePattern()));
List<Object> dataList = new ArrayList<>();
for (int i1 = 0; i1 < data.size(); i1++) {
String[] row = data.get(i1);
StringBuilder xField = new StringBuilder();
if (isDrill) {
xField.append(row[xAxis.size() - 1]);
} else {
for (int i = 0; i < xAxisBase.size(); i++) {
if (i == xAxisBase.size() - 1) {
xField.append(row[i]);
} else {
xField.append(row[i]).append("\n");
}
}
}
Map<String, Object> obj = new HashMap<>();
obj.put("field", xField.toString());
obj.put("category", xField.toString());
List<ChartDimensionDTO> dimensionList = new ArrayList<>();
for (int j = 0; j < xAxis.size(); j++) {
ChartDimensionDTO chartDimensionDTO = new ChartDimensionDTO();
chartDimensionDTO.setId(xAxis.get(j).getId());
chartDimensionDTO.setValue(row[j]);
dimensionList.add(chartDimensionDTO);
}
obj.put("dimensionList", dimensionList);
List<String> values = new ArrayList<>();
if (row[xAxisBase.size()] == null || row[xAxisBase.size() + 1] == null) {
continue;
}
values.add(row[xAxisBase.size()]);
values.add(row[xAxisBase.size() + 1]);
obj.put("values", values);
try {
Date date = sdf.parse(row[xAxisBase.size()]);
if (date != null) {
dates.add(date);
}
} catch (Exception ignore) {
}
try {
Date date = sdf.parse(row[xAxisBase.size() + 1]);
if (date != null) {
dates.add(date);
}
} catch (Exception ignore) {
}
dataList.add(obj);
}
map.put("minTime", sdf.format(dates.stream().min(Date::compareTo).orElse(null)));
map.put("maxTime", sdf.format(dates.stream().max(Date::compareTo).orElse(null)));
map.put("data", dataList);
return map;
}
public static Map<String, Object> transBidirectionalBarData(List<ChartViewFieldDTO> xAxis, List<ChartViewFieldDTO> yAxis, ChartViewDTO view, List<String[]> data, boolean isDrill) { public static Map<String, Object> transBidirectionalBarData(List<ChartViewFieldDTO> xAxis, List<ChartViewFieldDTO> yAxis, ChartViewDTO view, List<String[]> data, boolean isDrill) {
Map<String, Object> map = new HashMap<>(); Map<String, Object> map = new HashMap<>();

View File

@ -6,4 +6,8 @@ ALTER TABLE `sys_task_email`
ADD COLUMN `groups` varchar(255) NULL COMMENT '群聊' AFTER `view_data_range`; ADD COLUMN `groups` varchar(255) NULL COMMENT '群聊' AFTER `view_data_range`;
ALTER TABLE `sys_task_email` ALTER TABLE `sys_task_email`
ADD COLUMN `ext_wait_time` int(0) NOT NULL DEFAULT 0 COMMENT '加载仪表板额外等待时间(s)' AFTER `groups`; ADD COLUMN `ext_wait_time` int(0) NOT NULL DEFAULT 0 COMMENT '加载仪表板额外等待时间(s)' AFTER `groups`;
ALTER TABLE `sys_task_email`
ADD COLUMN `role_list` varchar(255) NULL COMMENT '收件角色' AFTER `ext_wait_time`,
ADD COLUMN `org_list` varchar(255) NULL COMMENT '收件组织' AFTER `role_list`;

View File

@ -1,6 +1,6 @@
{ {
"name": "dataease", "name": "dataease",
"version": "1.18.13", "version": "1.18.14",
"description": "dataease front", "description": "dataease front",
"private": true, "private": true,
"scripts": { "scripts": {

View File

@ -830,7 +830,6 @@ export default {
const filters = this.filter.filter const filters = this.filter.filter
const group = this.groupRequiredInvalid(filters) const group = this.groupRequiredInvalid(filters)
if (group.unReady?.length) { if (group.unReady?.length) {
this.view && (this.view.unReadyMsg = '请先完成必填项过滤器!')
this.getDataLoading = false this.getDataLoading = false
return return
} else { } else {

View File

@ -28,10 +28,21 @@
class="condition-content" class="condition-content"
:class="{'condition-content-default' : !(element.options.attrs.showTitle && element.options.attrs.title)}" :class="{'condition-content-default' : !(element.options.attrs.showTitle && element.options.attrs.title)}"
> >
<div
v-if="element.options.attrs.required"
class="widget-required-symbol"
>
<span>*</span>
</div>
<div <div
class="condition-content-container" class="condition-content-container"
:class="{'widget-required' : element.options.attrs.required}" :class="{'widget-required' : element.options.attrs.required}"
> >
<!-- <div class="required-msg-container">
<span>必填项不能为空</span>
</div> -->
<div class="first-element"> <div class="first-element">
<div <div
:class="element.component === 'de-select-grid' ? 'first-element-grid-container': ''" :class="element.component === 'de-select-grid' ? 'first-element-grid-container': ''"
@ -58,12 +69,7 @@
</div> </div>
</div> </div>
<div
v-if="element.options.attrs.required"
class="widget-required-symbol"
>
<span>*</span>
</div>
</div> </div>
</div> </div>
</div> </div>
@ -281,13 +287,13 @@ export default {
width: 100%; width: 100%;
.widget-required { .widget-required {
width: calc(100% - 12px) !important; width: calc(100% - 12px) !important;
float: left !important; float: right !important;
} }
.widget-required-symbol { .widget-required-symbol {
color: #f54a45; color: #f54a45;
height: 40px; height: 40px;
line-height: 40px; line-height: 40px;
float: right; float: left;
width: 12px; width: 12px;
} }
} }

View File

@ -5,11 +5,12 @@
ref="dateRef" ref="dateRef"
v-model="values" v-model="values"
:popper-class="'coustom-date-picker' + ' ' + extPoperClass" :popper-class="'coustom-date-picker' + ' ' + extPoperClass"
:class="{'show-required-tips': showRequiredTips}"
:type="componentType" :type="componentType"
:range-separator="$t(element.options.attrs.rangeSeparator)" :range-separator="$t(element.options.attrs.rangeSeparator)"
:start-placeholder="$t(element.options.attrs.startPlaceholder)" :start-placeholder="showRequiredTips ? $t('panel.required_tips') : $t(element.options.attrs.startPlaceholder)"
:end-placeholder="$t(element.options.attrs.endPlaceholder)" :end-placeholder="showRequiredTips ? $t('panel.required_tips') : $t(element.options.attrs.endPlaceholder)"
:placeholder="$t(element.options.attrs.placeholder)" :placeholder="showRequiredTips ? $t('panel.required_tips') : $t(element.options.attrs.placeholder)"
:append-to-body="inScreen" :append-to-body="inScreen"
value-format="timestamp" value-format="timestamp"
:format="labelFormat" :format="labelFormat"
@ -219,6 +220,9 @@ export default {
} }
return null return null
}, },
showRequiredTips() {
return this.inDraw && this.element.options.attrs.required && (!this.values || this.values.length === 0)
},
...mapState([ ...mapState([
'canvasStyleData', 'canvasStyleData',
'mobileStatus' 'mobileStatus'
@ -516,7 +520,31 @@ export default {
} }
</script> </script>
<style lang="scss" scoped>
.show-required-tips {
border-color: #ff0000 !important;
::v-deep .el-input__inner {
color: #ff0000 !important;
}
::v-deep input::placeholder {
color: #ff0000 !important;
}
::v-deep i {
color: #ff0000 !important;
}
}
.show-required-tips ::v-deep .el-input__inner, input {
border-color: #ff0000 !important;
}
.show-required-tips ::v-deep .el-input__inner, input::placeholder {
color: #ff0000 !important;
}
.show-required-tips ::v-deep i {
color: #ff0000 !important;
}
</style>
<style lang="scss"> <style lang="scss">
.date-picker-vant { .date-picker-vant {
position: relative; position: relative;

View File

@ -5,9 +5,10 @@
ref="de-input-search" ref="de-input-search"
v-model="value" v-model="value"
resize="vertical" resize="vertical"
:placeholder="$t(element.options.attrs.placeholder)" :placeholder="showRequiredTips ? $t('panel.required_tips') : $t(element.options.attrs.placeholder)"
:size="size" :size="size"
class="de-range-tag" class="de-range-tag"
:class="{'show-required-tips': showRequiredTips}"
@input="valueChange" @input="valueChange"
@keypress.enter.native="search" @keypress.enter.native="search"
@dblclick="setEdit" @dblclick="setEdit"
@ -63,6 +64,9 @@ export default {
}, },
manualModify() { manualModify() {
return !!this.element.options.manualModify return !!this.element.options.manualModify
},
showRequiredTips() {
return this.inDraw && this.element.options.attrs.required && !this.value
} }
}, },
watch: { watch: {
@ -146,10 +150,14 @@ export default {
} }
</script> </script>
<style lang="scss"> <style lang="scss" scoped>
// .de-range-tag { .show-required-tips ::v-deep .el-input__inner {
// input::placeholder { border-color: #ff0000 !important;
// color: var(--CustomColor, #909399) !important; }
// } .show-required-tips ::v-deep .el-input__inner::placeholder {
// } color: #ff0000 !important;
}
.show-required-tips ::v-deep i {
color: #ff0000 !important;
}
</style> </style>

View File

@ -7,7 +7,10 @@
style="width: 100%;" style="width: 100%;"
:rules="rules" :rules="rules"
> >
<div class="de-number-range-container"> <div
class="de-number-range-container"
:class="{'show-required-tips': showRequiredTips}"
>
<el-form-item <el-form-item
prop="min" prop="min"
style="padding-left: 0px;" style="padding-left: 0px;"
@ -15,7 +18,7 @@
<el-input <el-input
ref="de-number-range-min" ref="de-number-range-min"
v-model="form.min" v-model="form.min"
:placeholder="$t(element.options.attrs.placeholder_min)" :placeholder="showRequiredTips ? $t('panel.required_tips') : $t(element.options.attrs.placeholder_min)"
:size="size" :size="size"
@input="inputChange" @input="inputChange"
@change="handleMinChange" @change="handleMinChange"
@ -29,7 +32,7 @@
<el-input <el-input
ref="de-number-range-max" ref="de-number-range-max"
v-model="form.max" v-model="form.max"
:placeholder="$t(element.options.attrs.placeholder_max)" :placeholder="showRequiredTips ? $t('panel.required_tips') : $t(element.options.attrs.placeholder_max)"
:size="size" :size="size"
@input="inputChange" @input="inputChange"
@change="handleMaxChange" @change="handleMaxChange"
@ -102,6 +105,9 @@ export default {
}, },
manualModify() { manualModify() {
return !!this.element.options.manualModify return !!this.element.options.manualModify
},
showRequiredTips() {
return this.inDraw && this.element.options.attrs.required && !this.form.min && !this.form.max
} }
}, },
watch: { watch: {
@ -316,6 +322,16 @@ export default {
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.show-required-tips ::v-deep .el-input__inner {
border-color: #ff0000 !important;
}
.show-required-tips ::v-deep .el-input__inner::placeholder {
color: #ff0000 !important;
}
.show-required-tips ::v-deep i {
color: #ff0000 !important;
}
.de-number-range-container { .de-number-range-container {
display: inline; display: inline;
max-height: 40px; max-height: 40px;

View File

@ -8,7 +8,7 @@
:collapse-tags="showNumber" :collapse-tags="showNumber"
:clearable="!element.options.attrs.multiple && (inDraw || !selectFirst)" :clearable="!element.options.attrs.multiple && (inDraw || !selectFirst)"
:multiple="element.options.attrs.multiple" :multiple="element.options.attrs.multiple"
:placeholder="$t(element.options.attrs.placeholder) + placeholderSuffix" :placeholder="showRequiredTips ? $t('panel.required_tips') : ($t(element.options.attrs.placeholder) + placeholderSuffix)"
:popper-append-to-body="inScreen" :popper-append-to-body="inScreen"
:size="size" :size="size"
:filterable="inDraw || !selectFirst" :filterable="inDraw || !selectFirst"
@ -16,7 +16,7 @@
:item-disabled="!inDraw && selectFirst" :item-disabled="!inDraw && selectFirst"
:key-word="keyWord" :key-word="keyWord"
popper-class="coustom-de-select" popper-class="coustom-de-select"
:class="{'disabled-close': !inDraw && selectFirst && element.options.attrs.multiple}" :class="{'disabled-close': !inDraw && selectFirst && element.options.attrs.multiple, 'show-required-tips': showRequiredTips}"
:list="data" :list="data"
:flag="flag" :flag="flag"
:is-config="isConfig" :is-config="isConfig"
@ -143,6 +143,9 @@ export default {
}, },
selectFirst() { selectFirst() {
return this.element.serviceName === 'textSelectWidget' && this.element.options.attrs.selectFirst return this.element.serviceName === 'textSelectWidget' && this.element.options.attrs.selectFirst
},
showRequiredTips() {
return this.inDraw && this.element.options.attrs.required && !this.value
} }
}, },
@ -159,8 +162,10 @@ export default {
}, },
'defaultValueStr': function(value, old) { 'defaultValueStr': function(value, old) {
if (value === old) return if (value === old) return
this.value = this.fillValueDerfault() this.$nextTick(() => {
this.changeValue(value) this.value = this.fillValueDerfault()
this.changeValue(value)
})
}, },
'element.options.attrs.fieldId': function(value, old) { 'element.options.attrs.fieldId': function(value, old) {
if (value === null || typeof value === 'undefined' || value === old) return if (value === null || typeof value === 'undefined' || value === old) return
@ -532,6 +537,15 @@ export default {
.disabled-close ::v-deep .el-icon-close { .disabled-close ::v-deep .el-icon-close {
display: none !important; display: none !important;
} }
.show-required-tips ::v-deep .el-input__inner {
border-color: #ff0000 !important;
}
.show-required-tips ::v-deep .el-input__inner::placeholder {
color: #ff0000 !important;
}
.show-required-tips ::v-deep i {
color: #ff0000 !important;
}
</style> </style>
<style lang="scss"> <style lang="scss">
.coustom-de-select { .coustom-de-select {

View File

@ -4,11 +4,14 @@
v-if="element.options!== null && element.options.attrs!==null && show" v-if="element.options!== null && element.options.attrs!==null && show"
class="de-select-grid-class" class="de-select-grid-class"
> >
<div class="de-select-grid-search"> <div
class="de-select-grid-search"
:class="{'show-required-tips': showRequiredTips}"
>
<el-input <el-input
ref="de-select-grid" ref="de-select-grid"
v-model="keyWord" v-model="keyWord"
:placeholder="$t('deinputsearch.placeholder')" :placeholder="showRequiredTips ? $t('panel.required_tips') : $t('deinputsearch.placeholder')"
:size="size" :size="size"
prefix-icon="el-icon-search" prefix-icon="el-icon-search"
clearable clearable
@ -149,6 +152,9 @@ export default {
}, },
isCustomSortWidget() { isCustomSortWidget() {
return this.element.serviceName === 'textSelectGridWidget' return this.element.serviceName === 'textSelectGridWidget'
},
showRequiredTips() {
return this.inDraw && this.element.options.attrs.required && (!this.value || !this.value.length)
} }
}, },
watch: { watch: {
@ -448,6 +454,16 @@ export default {
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.show-required-tips ::v-deep .el-input__inner {
border-color: #ff0000 !important;
}
.show-required-tips ::v-deep .el-input__inner::placeholder {
color: #ff0000 !important;
}
.show-required-tips ::v-deep i {
color: #ff0000 !important;
}
.de-select-grid-search { .de-select-grid-search {
::v-deep input { ::v-deep input {
border-radius: 0px; border-radius: 0px;

View File

@ -4,6 +4,7 @@
v-if="element.options!== null && element.options.attrs!==null && show" v-if="element.options!== null && element.options.attrs!==null && show"
ref="deSelectTree" ref="deSelectTree"
v-model="value" v-model="value"
:class="{'show-required-tips': showRequiredTips}"
popover-class="test-class-wrap" popover-class="test-class-wrap"
:data="data" :data="data"
:select-params="selectParams" :select-params="selectParams"
@ -69,7 +70,7 @@ export default {
value: this.isSingle ? '' : [], value: this.isSingle ? '' : [],
selectParams: { selectParams: {
clearable: true, clearable: true,
placeholder: this.$t(this.element.options.attrs.placeholder) placeholder: this.showRequiredTips ? this.$t('panel.required_tips') : this.$t(this.element.options.attrs.placeholder)
}, },
treeParams: { treeParams: {
showParent: true, showParent: true,
@ -118,6 +119,9 @@ export default {
customStyle() { customStyle() {
const { brColor, wordColor, innerBgColor } = this.element.style const { brColor, wordColor, innerBgColor } = this.element.style
return { brColor, wordColor, innerBgColor } return { brColor, wordColor, innerBgColor }
},
showRequiredTips() {
return this.inDraw && this.element.options.attrs.required && (!this.value || !this.value.length)
} }
}, },
@ -414,6 +418,17 @@ export default {
} }
</script> </script>
<style lang="scss" scoped>
.show-required-tips ::v-deep .el-input__inner {
border-color: #ff0000 !important;
}
.show-required-tips ::v-deep .el-input__inner::placeholder {
color: #ff0000 !important;
}
.show-required-tips ::v-deep i {
color: #ff0000 !important;
}
</style>
<style lang="scss"> <style lang="scss">
.test-class-wrap { .test-class-wrap {
background: var(--BgSelectTreeColor, #FFFFFF) !important; background: var(--BgSelectTreeColor, #FFFFFF) !important;

View File

@ -0,0 +1,8 @@
<svg width="1072" height="1024" xmlns="http://www.w3.org/2000/svg" p-id="1374" version="1.1" class="icon" t="1616054957891">
<g>
<title>Layer 1</title>
<path id="svg_1" p-id="1375" d="m150.528,77.48267l0,207.28685l472.64914,0l2.99886,-207.28685l-475.648,0zm873.32571,303.34781l-469.32565,0l0,204.62018l469.12451,0l0.20114,-204.62018zm-203.14209,303.34781l-483.51692,0l0,207.28685l479.25025,0l4.26667,-207.28685z"/>
<path id="svg_2" p-id="1376" d="m115.15124,943.07962l0,-942.93333l-41.20381,0l0,994.37714l996.10819,0l0,-51.44381l-954.90438,0z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 566 B

View File

@ -1184,6 +1184,7 @@ export default {
chart_bar_stack: 'Stack Bar', chart_bar_stack: 'Stack Bar',
chart_percentage_bar_stack: 'Percentage Stack Bar', chart_percentage_bar_stack: 'Percentage Stack Bar',
chart_bar_horizontal: 'Horizontal Bar', chart_bar_horizontal: 'Horizontal Bar',
chart_bar_time_range: 'Time Bar',
chart_bar_stack_horizontal: 'Stack Horizontal Bar', chart_bar_stack_horizontal: 'Stack Horizontal Bar',
chart_percentage_bar_stack_horizontal: 'Horizontal Percentage Stack Bar', chart_percentage_bar_stack_horizontal: 'Horizontal Percentage Stack Bar',
chart_bidirectional_bar: 'Bidirectional Bar', chart_bidirectional_bar: 'Bidirectional Bar',
@ -1494,6 +1495,7 @@ export default {
dynamic: 'Dynamic', dynamic: 'Dynamic',
gauge_size_field_delete: 'Dynamic field changedplease edit again', gauge_size_field_delete: 'Dynamic field changedplease edit again',
chart_group: 'Sub Type', chart_group: 'Sub Type',
chart_bar_time: 'Times',
chart_bar_group: 'Bar Group', chart_bar_group: 'Bar Group',
chart_bar_group_stack: 'Group Stack Bar', chart_bar_group_stack: 'Group Stack Bar',
field_dynamic: 'Dynamic', field_dynamic: 'Dynamic',
@ -1521,6 +1523,7 @@ export default {
set_zero: 'Set Zero', set_zero: 'Set Zero',
ignore_data: 'Hide Data', ignore_data: 'Hide Data',
sub_dimension_tip: 'This field is required, and cannot be included in the type axis, you should choose non-group chart if you don\'t need it, or you will get unexpected chart.', sub_dimension_tip: 'This field is required, and cannot be included in the type axis, you should choose non-group chart if you don\'t need it, or you will get unexpected chart.',
time_bar_tip: 'This field is required, and axis type must be time',
drill_dimension_tip: 'Only fields in the dataset can be drilled', drill_dimension_tip: 'Only fields in the dataset can be drilled',
table_scroll_tip: 'The detail table is only effective when the pagination mode is "Drop-down".', table_scroll_tip: 'The detail table is only effective when the pagination mode is "Drop-down".',
table_threshold_tip: 'Tip: Do not select fields repeatedly. If the same field is configured repeatedly, only the last field will take effect.', table_threshold_tip: 'Tip: Do not select fields repeatedly. If the same field is configured repeatedly, only the last field will take effect.',
@ -2043,6 +2046,7 @@ export default {
back_parent: 'Back to previous' back_parent: 'Back to previous'
}, },
panel: { panel: {
required_tips: 'Cannot be empty!',
filter_no_select: 'Filter components do not need to be selected', filter_no_select: 'Filter components do not need to be selected',
first_item: 'First item', first_item: 'First item',
forbidden_copy: 'Forbidden copy', forbidden_copy: 'Forbidden copy',

View File

@ -1182,6 +1182,7 @@ export default {
chart_bar_stack: '堆疊柱狀圖', chart_bar_stack: '堆疊柱狀圖',
chart_percentage_bar_stack: '百分比柱狀圖', chart_percentage_bar_stack: '百分比柱狀圖',
chart_bar_horizontal: '橫嚮柱狀圖', chart_bar_horizontal: '橫嚮柱狀圖',
chart_bar_time_range: '時間條形圖',
chart_bar_stack_horizontal: '橫嚮堆疊柱狀圖', chart_bar_stack_horizontal: '橫嚮堆疊柱狀圖',
chart_percentage_bar_stack_horizontal: '橫嚮百分比柱狀圖', chart_percentage_bar_stack_horizontal: '橫嚮百分比柱狀圖',
chart_bidirectional_bar: '對稱柱狀圖', chart_bidirectional_bar: '對稱柱狀圖',
@ -1491,6 +1492,7 @@ export default {
dynamic: '動態值', dynamic: '動態值',
gauge_size_field_delete: '動態值中字段發生變更,請重新編輯', gauge_size_field_delete: '動態值中字段發生變更,請重新編輯',
chart_group: '子類別', chart_group: '子類別',
chart_bar_time: '起止時間',
chart_bar_group: '分組柱狀圖', chart_bar_group: '分組柱狀圖',
chart_bar_group_stack: '分組堆疊柱狀圖', chart_bar_group_stack: '分組堆疊柱狀圖',
field_dynamic: '動態值', field_dynamic: '動態值',
@ -1518,6 +1520,7 @@ export default {
ignore_data: '隱藏空值', ignore_data: '隱藏空值',
empty_data_field_ctrl: '字段設置', empty_data_field_ctrl: '字段設置',
sub_dimension_tip: '該字段為必填項,且不應使用類別軸中的字段,若無需該字段,請選擇基礎圖表進行展示,否則展示效果不理想', sub_dimension_tip: '該字段為必填項,且不應使用類別軸中的字段,若無需該字段,請選擇基礎圖表進行展示,否則展示效果不理想',
time_bar_tip: '該字段為必填項,且需要兩個時間類型字段',
drill_dimension_tip: '鑽取字段僅支持數據集中的字段', drill_dimension_tip: '鑽取字段僅支持數據集中的字段',
table_scroll_tip: '明細表僅在分頁模式為"下拉"時生效。', table_scroll_tip: '明細表僅在分頁模式為"下拉"時生效。',
table_threshold_tip: '提示:請勿重複選擇字段,若同一字段重複配置,則只有最後的字段配置生效。', table_threshold_tip: '提示:請勿重複選擇字段,若同一字段重複配置,則只有最後的字段配置生效。',
@ -2035,6 +2038,7 @@ export default {
back_parent: '返回上一級' back_parent: '返回上一級'
}, },
panel: { panel: {
required_tips: '必填項不能爲空!',
filter_no_select: '過濾組件無需選擇', filter_no_select: '過濾組件無需選擇',
first_item: '首項', first_item: '首項',
forbidden_copy: '當前組件不允許復製', forbidden_copy: '當前組件不允許復製',

View File

@ -1182,6 +1182,7 @@ export default {
chart_bar_stack: '堆叠柱状图', chart_bar_stack: '堆叠柱状图',
chart_percentage_bar_stack: '百分比柱状图', chart_percentage_bar_stack: '百分比柱状图',
chart_bar_horizontal: '横向柱状图', chart_bar_horizontal: '横向柱状图',
chart_bar_time_range: '时间条形图',
chart_bar_stack_horizontal: '横向堆叠柱状图', chart_bar_stack_horizontal: '横向堆叠柱状图',
chart_percentage_bar_stack_horizontal: '横向百分比柱状图', chart_percentage_bar_stack_horizontal: '横向百分比柱状图',
chart_bidirectional_bar: '对称柱状图', chart_bidirectional_bar: '对称柱状图',
@ -1491,6 +1492,7 @@ export default {
dynamic: '动态值', dynamic: '动态值',
gauge_size_field_delete: '动态值中字段发生变更,请重新编辑', gauge_size_field_delete: '动态值中字段发生变更,请重新编辑',
chart_group: '子类别', chart_group: '子类别',
chart_bar_time: '起止时间',
chart_bar_group: '分组柱状图', chart_bar_group: '分组柱状图',
chart_bar_group_stack: '分组堆叠柱状图', chart_bar_group_stack: '分组堆叠柱状图',
field_dynamic: '动态值', field_dynamic: '动态值',
@ -1518,6 +1520,7 @@ export default {
set_zero: '置为0', set_zero: '置为0',
ignore_data: '隐藏空值', ignore_data: '隐藏空值',
sub_dimension_tip: '该字段为必填项,且不应使用类别轴中的字段,若无需该字段,请选择基础图表进行展示,否则展示效果不理想。', sub_dimension_tip: '该字段为必填项,且不应使用类别轴中的字段,若无需该字段,请选择基础图表进行展示,否则展示效果不理想。',
time_bar_tip: '该字段为必填项,且需要两个时间类型字段',
drill_dimension_tip: '钻取字段仅支持数据集中的字段', drill_dimension_tip: '钻取字段仅支持数据集中的字段',
table_scroll_tip: '明细表仅在分页模式为"下拉"时生效。', table_scroll_tip: '明细表仅在分页模式为"下拉"时生效。',
table_threshold_tip: '提示:请勿重复选择字段,若同一字段重复配置,则只有最后的字段配置生效', table_threshold_tip: '提示:请勿重复选择字段,若同一字段重复配置,则只有最后的字段配置生效',
@ -2036,6 +2039,7 @@ export default {
back_parent: '返回上一级' back_parent: '返回上一级'
}, },
panel: { panel: {
required_tips: '必填项不能为空!',
filter_no_select: '过滤组件无需选择', filter_no_select: '过滤组件无需选择',
first_item: '首项', first_item: '首项',
forbidden_copy: '当前组件不允许复制', forbidden_copy: '当前组件不允许复制',

View File

@ -7,7 +7,7 @@
> >
<licbar /> <licbar />
<topbar <topbar
v-if="!fullHeightFlag && finishLoad" v-if="!fullHeightFlag"
:show-tips="showTips" :show-tips="showTips"
/> />
@ -83,7 +83,6 @@ export default {
return { return {
componentName: 'PanelMain', componentName: 'PanelMain',
showTips: false, showTips: false,
finishLoad: false,
buttonDisable: false, buttonDisable: false,
sideWidth: '' sideWidth: ''
} }
@ -125,12 +124,7 @@ export default {
} }
}, },
beforeCreate() { beforeCreate() {
needModifyPwd().then(res => { this.showTips = false
this.showTips = res.success && res.data
this.finishLoad = true
}).catch(e => {
this.finishLoad = true
})
}, },
mounted() { mounted() {
document.addEventListener('click', this.bodyClick) document.addEventListener('click', this.bodyClick)

View File

@ -262,6 +262,130 @@ export function hBaseBarOptionAntV(plot, container, chart, action, isGroup, isSt
return plot return plot
} }
export function timeRangeBarOptionAntV(plot, container, chart, action) {
// theme
const theme = getTheme(chart)
// attr
const label = getLabel(chart)
const tooltip = getTooltip(chart)
// style
const legend = getLegend(chart)
const yAxis = getXAxis(chart)
const xAxis = getYAxis(chart)
// data
const data = _.cloneDeep(chart.data.data)
const minTime = chart.data.minTime
const maxTime = chart.data.maxTime
// config
const slider = getSlider(chart)
const analyse = getAnalyse(chart)
// options
const options = {
theme: theme,
data: data,
xField: 'values',
yField: 'field',
seriesField: 'category',
appendPadding: getPadding(chart),
label: label,
tooltip: tooltip,
legend: legend,
xAxis: xAxis,
yAxis: yAxis,
slider: slider,
annotations: analyse,
isRange: true,
meta: {
values: {
type: 'time',
min: minTime,
max: maxTime
}
},
brush: {
enabled: true,
isStartEnable: (context) => {
// 按住 shift 键,才能开启交互
if (context.event.gEvent.originalEvent?.shiftKey) {
return true
}
return false
}
},
interactions: [
{
type: 'legend-active', cfg: {
start: [{ trigger: 'legend-item:mouseenter', action: ['element-active:reset'] }],
end: [{ trigger: 'legend-item:mouseleave', action: ['element-active:reset'] }]
}
},
{
type: 'legend-filter', cfg: {
start: [{ trigger: 'legend-item:click', action: ['list-unchecked:toggle', 'data-filter:filter', 'element-active:reset', 'element-highlight:reset'] }]
}
},
{
type: 'tooltip', cfg: {
start: [{ trigger: 'interval:mousemove', action: 'tooltip:show' }],
end: [{ trigger: 'interval:mouseleave', action: 'tooltip:hide' }]
}
},
{
type: 'active-region', cfg: {
start: [{ trigger: 'interval:mousemove', action: 'active-region:show' }],
end: [{ trigger: 'interval:mouseleave', action: 'active-region:hide' }]
}
}
]
}
// size
let customAttr = {}
if (chart.customAttr) {
customAttr = JSON.parse(chart.customAttr)
if (customAttr.size) {
const s = JSON.parse(JSON.stringify(customAttr.size))
if (s.barDefault) {
delete options.marginRatio
} else {
options.marginRatio = s.barGap
}
}
}
delete options.isGroup
delete options.isStack
options.isPercent = chart.type.includes('percentage')
// custom color
options.color = antVCustomColor(chart)
if (customAttr.color.gradient) {
options.color = options.color.map((ele) => {
return setGradientColor(ele, customAttr.color.gradient)
})
}
// 处理空值
if (chart.senior) {
let emptyDataStrategy = JSON.parse(chart.senior)?.functionCfg?.emptyDataStrategy
if (!emptyDataStrategy) {
emptyDataStrategy = 'breakLine'
}
handleEmptyDataStrategy(emptyDataStrategy, chart, data, options)
}
// 开始渲染
if (plot) {
plot.destroy()
}
plot = new Bar(container, options)
plot.off('interval:click')
plot.on('interval:click', action)
return plot
}
export function baseBidirectionalBarOptionAntV(plot, container, chart, action, isGroup, isStack) { export function baseBidirectionalBarOptionAntV(plot, container, chart, action, isGroup, isStack) {
// theme // theme
const theme = getTheme(chart) const theme = getTheme(chart)

View File

@ -422,7 +422,7 @@ export function getTooltip(chart) {
res = valueFormatter(param.value, formatterItem) res = valueFormatter(param.value, formatterItem)
} }
} }
} else if (includesAny(chart.type, 'bar', 'scatter', 'radar', 'area') && !chart.type.includes('group')) { } else if (includesAny(chart.type, 'bar', 'scatter', 'radar', 'area') && !chart.type.includes('group') && chart.type !== 'bar-time-range') {
obj = { name: param.category, value: param.value } obj = { name: param.category, value: param.value }
for (let i = 0; i < yAxis.length; i++) { for (let i = 0; i < yAxis.length; i++) {
const f = yAxis[i] const f = yAxis[i]
@ -470,6 +470,9 @@ export function getTooltip(chart) {
res = valueFormatter(param.value, formatterItem) res = valueFormatter(param.value, formatterItem)
} }
} }
} else if (chart.type === 'bar-time-range') {
obj = { values: param.values, name: param.category }
res = param.values[0] + ' - ' + param.values[1]
} else { } else {
res = param.value res = param.value
} }
@ -724,7 +727,7 @@ export function getXAxis(chart) {
delete axis.maxLimit delete axis.maxLimit
delete axis.tickCount delete axis.tickCount
const axisValue = a.axisValue const axisValue = a.axisValue
if (chart.type.includes('horizontal')) { if (chart.type.includes('horizontal') || chart.type === 'bar-time-range') {
if (axisValue && !axisValue.auto) { if (axisValue && !axisValue.auto) {
const yAxisSeriesMaxList = [] const yAxisSeriesMaxList = []
const maxList = [] const maxList = []
@ -814,7 +817,7 @@ export function getYAxis(chart) {
if (chart.type === 'waterfall') { if (chart.type === 'waterfall') {
return value return value
} else { } else {
if (!chart.type.includes('horizontal')) { if (!(chart.type.includes('horizontal') || chart.type === 'bar-time-range')) {
if (!a.axisLabelFormatter) { if (!a.axisLabelFormatter) {
return valueFormatter(value, formatterItem) return valueFormatter(value, formatterItem)
} else { } else {
@ -841,7 +844,7 @@ export function getYAxis(chart) {
delete axis.maxLimit delete axis.maxLimit
delete axis.tickCount delete axis.tickCount
const axisValue = a.axisValue const axisValue = a.axisValue
if (!chart.type.includes('horizontal')) { if (!chart.type.includes('horizontal') || chart.type === 'bar-time-range') {
if (axisValue && !axisValue.auto) { if (axisValue && !axisValue.auto) {
const yAxisSeriesMaxList = [] const yAxisSeriesMaxList = []
const maxList = [] const maxList = []

View File

@ -1100,6 +1100,85 @@ export const TYPE_CONFIGS = [
] ]
} }
}, },
{
render: 'antv',
category: 'chart.chart_type_compare',
value: 'bar-time-range',
title: 'chart.chart_bar_time_range',
icon: 'bar-time-range',
properties: [
'color-selector',
'label-selector-ant-v',
'tooltip-selector-ant-v',
'x-axis-selector-ant-v',
'y-axis-selector-ant-v',
'title-selector-ant-v',
'legend-selector-ant-v'
],
propertyInner: {
'color-selector': [
'value',
'colorPanel',
'customColor',
'gradient',
'alpha'
],
'size-selector-ant-v': [
'barDefault',
'barGap'
],
'label-selector-ant-v': [
'show',
'fontSize',
'color',
'position-h'
],
'tooltip-selector-ant-v': [
'show',
'textStyle'
],
'x-axis-selector-ant-v': [
'show',
'position',
'name',
'nameTextStyle',
'splitLine',
'axisForm',
'axisLabel'
],
'y-axis-selector-ant-v': [
'show',
'position',
'name',
'nameTextStyle',
'splitLine',
'axisForm',
'axisLabel'
],
'title-selector-ant-v': [
'show',
'title',
'fontSize',
'color',
'hPosition',
'isItalic',
'isBolder',
'remarkShow',
'fontFamily',
'letterSpace',
'fontShadow'
],
'legend-selector-ant-v': [
'show',
'icon',
'orient',
'textStyle',
'hPosition',
'vPosition'
]
}
},
{ {
render: 'antv', render: 'antv',
category: 'chart.chart_type_compare', category: 'chart.chart_type_compare',
@ -3517,7 +3596,7 @@ export function getColors(chart, colors, reset) {
} }
} }
} }
} else if ((includesAny(chart.type, 'bar', 'radar', 'area')) && !chart.type.includes('group')) { } else if ((includesAny(chart.type, 'bar', 'radar', 'area')) && !chart.type.includes('group') && chart.type !== 'bar-time-range') {
if (Object.prototype.toString.call(chart.yaxis) === '[object Array]') { if (Object.prototype.toString.call(chart.yaxis) === '[object Array]') {
series = JSON.parse(JSON.stringify(chart.yaxis)) series = JSON.parse(JSON.stringify(chart.yaxis))
} else { } else {

View File

@ -45,7 +45,7 @@ import { baseLiquid } from '@/views/chart/chart/liquid/liquid'
import { uuid } from 'vue-uuid' import { uuid } from 'vue-uuid'
import ViewTrackBar from '@/components/canvas/components/editor/ViewTrackBar' import ViewTrackBar from '@/components/canvas/components/editor/ViewTrackBar'
import { getRemark, hexColorToRGBA } from '@/views/chart/chart/util' import { getRemark, hexColorToRGBA } from '@/views/chart/chart/util'
import { baseBarOptionAntV, hBaseBarOptionAntV, baseBidirectionalBarOptionAntV } from '@/views/chart/chart/bar/bar_antv' import { baseBarOptionAntV, hBaseBarOptionAntV, baseBidirectionalBarOptionAntV, timeRangeBarOptionAntV } from '@/views/chart/chart/bar/bar_antv'
import { baseAreaOptionAntV, baseLineOptionAntV } from '@/views/chart/chart/line/line_antv' import { baseAreaOptionAntV, baseLineOptionAntV } from '@/views/chart/chart/line/line_antv'
import { basePieOptionAntV, basePieRoseOptionAntV } from '@/views/chart/chart/pie/pie_antv' import { basePieOptionAntV, basePieRoseOptionAntV } from '@/views/chart/chart/pie/pie_antv'
import { baseScatterOptionAntV } from '@/views/chart/chart/scatter/scatter_antv' import { baseScatterOptionAntV } from '@/views/chart/chart/scatter/scatter_antv'
@ -273,6 +273,8 @@ export default {
this.myChart = hBaseBarOptionAntV(this.myChart, this.chartId, chart, this.antVAction, true, false) this.myChart = hBaseBarOptionAntV(this.myChart, this.chartId, chart, this.antVAction, true, false)
} else if (equalsAny(chart.type, 'bar-stack-horizontal', 'percentage-bar-stack-horizontal')) { } else if (equalsAny(chart.type, 'bar-stack-horizontal', 'percentage-bar-stack-horizontal')) {
this.myChart = hBaseBarOptionAntV(this.myChart, this.chartId, chart, this.antVAction, false, true) this.myChart = hBaseBarOptionAntV(this.myChart, this.chartId, chart, this.antVAction, false, true)
} else if (equalsAny(chart.type, 'bar-time-range')) {
this.myChart = timeRangeBarOptionAntV(this.myChart, this.chartId, chart, this.antVAction)
} else if (chart.type === 'line') { } else if (chart.type === 'line') {
this.myChart = baseLineOptionAntV(this.myChart, this.chartId, chart, this.antVAction) this.myChart = baseLineOptionAntV(this.myChart, this.chartId, chart, this.antVAction)
} else if (chart.type === 'area') { } else if (chart.type === 'area') {
@ -389,8 +391,12 @@ export default {
} }
return return
} }
const quotaList = this.pointParam.data.quotaList let quotaList = this.pointParam.data.quotaList
quotaList[0]['value'] = this.pointParam.data.value if (this.chart.type === 'bar-time-range') {
quotaList = this.pointParam.data.dimensionList
} else {
quotaList[0]['value'] = this.pointParam.data.value
}
const linkageParam = { const linkageParam = {
option: 'linkage', option: 'linkage',
name: this.pointParam.data.name, name: this.pointParam.data.name,

View File

@ -28,14 +28,18 @@
size="mini" size="mini"
@change="changeXAxisStyle('position')" @change="changeXAxisStyle('position')"
> >
<div v-if="chart.type !== 'bidirectional-bar'"> <div v-if="chart.type === 'bidirectional-bar'">
<el-radio-button label="top">{{ $t('chart.text_pos_top') }}</el-radio-button>
<el-radio-button label="bottom">{{ $t('chart.text_pos_bottom') }}</el-radio-button>
</div>
<div v-else-if="chart.type === 'bidirectional-bar'">
<el-radio-button label="top">{{ $t('chart.text_pos_left') }}</el-radio-button> <el-radio-button label="top">{{ $t('chart.text_pos_left') }}</el-radio-button>
<el-radio-button label="bottom">{{ $t('chart.text_pos_center') }}</el-radio-button> <el-radio-button label="bottom">{{ $t('chart.text_pos_center') }}</el-radio-button>
</div> </div>
<div v-else-if="chart.type === 'bar-time-range'">
<el-radio-button label="bottom">{{ $t('chart.text_pos_left') }}</el-radio-button>
<el-radio-button label="top">{{ $t('chart.text_pos_right') }}</el-radio-button>
</div>
<div v-else>
<el-radio-button label="top">{{ $t('chart.text_pos_top') }}</el-radio-button>
<el-radio-button label="bottom">{{ $t('chart.text_pos_bottom') }}</el-radio-button>
</div>
</el-radio-group> </el-radio-group>
</el-form-item> </el-form-item>
<el-form-item <el-form-item
@ -266,7 +270,7 @@
/> />
</el-form-item> </el-form-item>
<el-form-item <el-form-item
v-if="chart.type && chart.type !== 'bidirectional-bar'" v-if="chart.type && chart.type !== 'bidirectional-bar' && chart.type !== 'bar-time-range'"
:label="$t('chart.axis_label_rotate')" :label="$t('chart.axis_label_rotate')"
class="form-item form-item-slider" class="form-item form-item-slider"
> >

View File

@ -28,14 +28,18 @@
size="mini" size="mini"
@change="changeYAxisStyle('position')" @change="changeYAxisStyle('position')"
> >
<div v-if="chart.type !== 'bidirectional-bar'"> <div v-if="chart.type === 'bidirectional-bar' ">
<el-radio-button label="left">{{ $t('chart.text_pos_left') }}</el-radio-button>
<el-radio-button label="right">{{ $t('chart.text_pos_right') }}</el-radio-button>
</div>
<div v-else-if="chart.type === 'bidirectional-bar'">
<el-radio-button label="right">{{ $t('chart.text_pos_top') }}</el-radio-button> <el-radio-button label="right">{{ $t('chart.text_pos_top') }}</el-radio-button>
<el-radio-button label="left">{{ $t('chart.text_pos_bottom') }}</el-radio-button> <el-radio-button label="left">{{ $t('chart.text_pos_bottom') }}</el-radio-button>
</div> </div>
<div v-else-if="chart.type === 'bar-time-range'">
<el-radio-button label="left">{{ $t('chart.text_pos_top') }}</el-radio-button>
<el-radio-button label="right">{{ $t('chart.text_pos_bottom') }}</el-radio-button>
</div>
<div v-else>
<el-radio-button label="left">{{ $t('chart.text_pos_left') }}</el-radio-button>
<el-radio-button label="right">{{ $t('chart.text_pos_right') }}</el-radio-button>
</div>
</el-radio-group> </el-radio-group>
</el-form-item> </el-form-item>
<el-form-item <el-form-item
@ -293,7 +297,7 @@
</el-select> </el-select>
</el-form-item> </el-form-item>
<span v-show="chart.type && !chart.type.includes('horizontal') && chart.type !== 'waterfall'"> <span v-show="chart.type && !(chart.type.includes('horizontal') || chart.type === 'bar-time-range') && chart.type !== 'waterfall'">
<el-form-item <el-form-item
:label="$t('chart.value_formatter_type')" :label="$t('chart.value_formatter_type')"
class="form-item" class="form-item"

View File

@ -119,11 +119,18 @@
>{{ $t('chart.y_W') }}</el-dropdown-item> >{{ $t('chart.y_W') }}</el-dropdown-item>
<el-dropdown-item :command="beforeDateStyle('y_M_d')">{{ $t('chart.y_M_d') }}</el-dropdown-item> <el-dropdown-item :command="beforeDateStyle('y_M_d')">{{ $t('chart.y_M_d') }}</el-dropdown-item>
<el-dropdown-item <el-dropdown-item
v-if="!hideSpecial"
:command="beforeDateStyle('H_m_s')" :command="beforeDateStyle('H_m_s')"
divided divided
>{{ $t('chart.H_m_s') }}</el-dropdown-item> >{{ $t('chart.H_m_s') }}</el-dropdown-item>
<el-dropdown-item :command="beforeDateStyle('y_M_d_H')">{{ $t('chart.y_M_d_H') }}</el-dropdown-item> <el-dropdown-item
<el-dropdown-item :command="beforeDateStyle('y_M_d_H_m')">{{ $t('chart.y_M_d_H_m') }}</el-dropdown-item> v-if="!hideSpecial"
:command="beforeDateStyle('y_M_d_H')"
>{{ $t('chart.y_M_d_H') }}</el-dropdown-item>
<el-dropdown-item
:command="beforeDateStyle('y_M_d_H_m')"
:divided="hideSpecial"
>{{ $t('chart.y_M_d_H_m') }}</el-dropdown-item>
<el-dropdown-item :command="beforeDateStyle('y_M_d_H_m_s')">{{ $t('chart.y_M_d_H_m_s') }}</el-dropdown-item> <el-dropdown-item :command="beforeDateStyle('y_M_d_H_m_s')">{{ $t('chart.y_M_d_H_m_s') }}</el-dropdown-item>
</el-dropdown-menu> </el-dropdown-menu>
</el-dropdown> </el-dropdown>
@ -210,6 +217,11 @@ export default {
showDateExt: false showDateExt: false
} }
}, },
computed: {
hideSpecial() {
return this.chart.type === 'bar-time-range'
}
},
watch: { watch: {
dimensionData: function() { dimensionData: function() {
this.getItemTagType() this.getItemTagType()
@ -299,10 +311,10 @@ export default {
}, },
getDateExtStatus() { getDateExtStatus() {
if (this.chart) { if (this.chart) {
this.showDateExt = this.chart.datasourceType === 'mysql' || this.showDateExt = (this.chart.datasourceType === 'mysql' ||
this.chart.datasourceType === 'ds_doris' || this.chart.datasourceType === 'ds_doris' ||
this.chart.datasourceType === 'StarRocks' || this.chart.datasourceType === 'StarRocks' ||
this.chart.datasetMode === 1 this.chart.datasetMode === 1) && this.chart.type !== 'bar-time-range'
} else { } else {
this.showDateExt = false this.showDateExt = false
} }

View File

@ -687,12 +687,14 @@
v-if="view.type === 'bar-group' v-if="view.type === 'bar-group'
|| view.type === 'bar-group-stack' || view.type === 'bar-group-stack'
|| (view.render === 'antv' && view.type === 'line') || (view.render === 'antv' && view.type === 'line')
|| view.type === 'flow-map'" || view.type === 'flow-map'
|| view.type === 'bar-time-range'"
class="padding-lr" class="padding-lr"
> >
<span class="data-area-label"> <span class="data-area-label">
<span> <span>
<span v-if="view.type !=='flow-map'">{{ $t('chart.chart_group') }}</span> <span v-if="view.type === 'bar-time-range'">{{ $t('chart.chart_bar_time') }}</span>
<span v-else-if="view.type !== 'flow-map'">{{ $t('chart.chart_group') }}</span>
<span v-else-if="view.type === 'flow-map'">{{ $t('chart.end_point') }}</span> <span v-else-if="view.type === 'flow-map'">{{ $t('chart.end_point') }}</span>
<span <span
v-show="view.type !== 'line'" v-show="view.type !== 'line'"
@ -708,7 +710,12 @@
placement="bottom" placement="bottom"
> >
<div slot="content"> <div slot="content">
{{ $t('chart.sub_dimension_tip') }} <template v-if="view.type === 'bar-time-range'">
{{ $t('chart.time_bar_tip') }}
</template>
<template v-else>
{{ $t('chart.sub_dimension_tip') }}
</template>
</div> </div>
<i <i
class="el-icon-info" class="el-icon-info"
@ -739,7 +746,7 @@
:dimension-data="dimension" :dimension-data="dimension"
:quota-data="quota" :quota-data="quota"
:chart="chart" :chart="chart"
@onDimensionItemChange="dimensionItemChange" @onDimensionItemChange="dimensionExtItemChange"
@onDimensionItemRemove="dimensionItemRemove" @onDimensionItemRemove="dimensionItemRemove"
@editItemFilter="showDimensionEditFilter" @editItemFilter="showDimensionEditFilter"
@onNameEdit="showRename" @onNameEdit="showRename"
@ -755,7 +762,7 @@
</el-row> </el-row>
<!--yaxis--> <!--yaxis-->
<el-row <el-row
v-if="!equalsAny(view.type , 'table-info', 'label', 'flow-map')" v-if="!equalsAny(view.type , 'table-info', 'label', 'flow-map', 'bar-time-range')"
class="padding-lr" class="padding-lr"
style="margin-top: 6px;" style="margin-top: 6px;"
> >
@ -2122,7 +2129,7 @@ export default {
return equalsAny(this.view.type, 'table-normal', 'table-info') return equalsAny(this.view.type, 'table-normal', 'table-info')
}, },
showAnalyseCfg() { showAnalyseCfg() {
if (this.view.type === 'bidirectional-bar') { if (this.view.type === 'bidirectional-bar' || this.view.type === 'bar-time-range') {
return false return false
} }
return includesAny(this.view.type, 'bar', 'line', 'area', 'gauge', 'liquid') || return includesAny(this.view.type, 'bar', 'line', 'area', 'gauge', 'liquid') ||
@ -2502,7 +2509,7 @@ export default {
} }
}) })
if (equalsAny(view.type, 'table-pivot', 'bar-group', 'bar-group-stack', 'flow-map', 'race-bar') || if (equalsAny(view.type, 'table-pivot', 'bar-group', 'bar-group-stack', 'flow-map', 'race-bar') ||
(view.render === 'antv' && (view.type === 'line' || view.type === 'scatter'))) { (view.render === 'antv' && (view.type === 'line' || view.type === 'scatter' || view.type === 'bar-time-range'))) {
view.xaxisExt.forEach(function(ele) { view.xaxisExt.forEach(function(ele) {
if (!ele.dateStyle || ele.dateStyle === '') { if (!ele.dateStyle || ele.dateStyle === '') {
ele.dateStyle = 'y_M_d' ele.dateStyle = 'y_M_d'
@ -2846,6 +2853,16 @@ export default {
this.calcData(true) this.calcData(true)
}, },
dimensionExtItemChange(item) {
if (this.view.type === 'bar-time-range') {
this.view.xaxisExt.forEach(ext => {
ext.dateStyle = item.dateStyle
ext.datePattern = item.datePattern
})
}
this.calcData(true)
},
dimensionItemRemove(item) { dimensionItemRemove(item) {
if (item.removeType === 'dimension') { if (item.removeType === 'dimension') {
this.view.xaxis.splice(item.index, 1) this.view.xaxis.splice(item.index, 1)
@ -3310,6 +3327,19 @@ export default {
if (this.view.type !== 'table-info') { if (this.view.type !== 'table-info') {
this.dragCheckType(this.view.xaxisExt, 'd') this.dragCheckType(this.view.xaxisExt, 'd')
} }
if (this.view.type === 'bar-time-range') {
//
if (this.view.xaxisExt && this.view.xaxisExt.length > 0) {
for (let i = this.view.xaxisExt.length - 1; i >= 0; i--) {
if (this.view.xaxisExt[i].deType !== 1) {
this.view.xaxisExt.splice(i, 1)
}
}
}
if (this.view.xaxisExt.length > 2) {
this.view.xaxisExt = [this.view.xaxisExt[0], this.view.xaxisExt[1]]
}
}
if ((this.view.type === 'map' || this.view.type === 'word-cloud' || this.view.type === 'scatter') && this.view.xaxisExt.length > 1) { if ((this.view.type === 'map' || this.view.type === 'word-cloud' || this.view.type === 'scatter') && this.view.xaxisExt.length > 1) {
this.view.xaxisExt = [this.view.xaxisExt[0]] this.view.xaxisExt = [this.view.xaxisExt[0]]
} }

View File

@ -471,13 +471,13 @@ export default {
return false return false
}, },
xAisTitle() { xAisTitle() {
if (this.chart.type === 'bidirectional-bar') { if (this.chart.type === 'bidirectional-bar' || this.chart.type === 'bar-time-range') {
return this.$t('chart.yAxis') return this.$t('chart.yAxis')
} }
return this.$t('chart.xAxis') return this.$t('chart.xAxis')
}, },
yAxisTitle() { yAxisTitle() {
if (this.chart.type === 'bidirectional-bar') { if (this.chart.type === 'bidirectional-bar' || this.chart.type === 'bar-time-range') {
return this.$t('chart.xAxis') return this.$t('chart.xAxis')
} }
if (this.chart.type === 'chart-mix') { if (this.chart.type === 'chart-mix') {

View File

@ -1,6 +1,6 @@
{ {
"name": "dataease-mobile", "name": "dataease-mobile",
"version": "1.18.13", "version": "1.18.14",
"private": true, "private": true,
"scripts": { "scripts": {
"serve": "npm run dev:h5", "serve": "npm run dev:h5",

View File

@ -122,6 +122,48 @@
@change="changeXAxisStyle('splitLine')" @change="changeXAxisStyle('splitLine')"
/> />
</el-form-item> </el-form-item>
<el-form-item
:label="$t('chart.dash_show')"
class="form-item"
>
<el-checkbox
v-model="axisForm.splitLine.enableDash"
@change="changeXAxisStyle('splitLine')"
>{{ $t('chart.dash_show') }}</el-checkbox>
</el-form-item>
<template v-if="axisForm.splitLine.enableDash">
<el-form-item
:label="$t('chart.dash_width')"
class="form-item form-item-slider"
>
<el-slider
v-model="axisForm.splitLine.dashStyle.width"
:min="1"
:max="10"
show-input
:show-input-controls="false"
input-size="mini"
@change="changeXAxisStyle('splitLine')"
/>
</el-form-item>
<el-form-item
:label="$t('chart.dash_offset')"
class="form-item form-item-slider"
>
<el-slider
v-model="axisForm.splitLine.dashStyle.offset"
:min="1"
:max="10"
show-input
:show-input-controls="false"
input-size="mini"
@change="changeXAxisStyle('splitLine')"
/>
</el-form-item>
</template>
</span> </span>
<el-divider/> <el-divider/>
<el-form-item <el-form-item
@ -325,6 +367,9 @@ export default {
if (!this.axisForm.axisLine) { if (!this.axisForm.axisLine) {
this.axisForm.axisLine = JSON.parse(JSON.stringify(DEFAULT_XAXIS_STYLE.axisLine)) this.axisForm.axisLine = JSON.parse(JSON.stringify(DEFAULT_XAXIS_STYLE.axisLine))
} }
if (!this.axisForm.splitLine.dashStyle) {
this.axisForm.splitLine.dashStyle = JSON.parse(JSON.stringify(DEFAULT_XAXIS_STYLE.splitLine.dashStyle))
}
} }
} }
}, },

View File

@ -549,6 +549,11 @@ export const DEFAULT_XAXIS_STYLE = {
color: '#cccccc', color: '#cccccc',
width: 1, width: 1,
style: 'solid' style: 'solid'
},
enableDash: false,
dashStyle: {
width: 4,
offset: 5
} }
}, },
axisValue: { axisValue: {

View File

@ -441,11 +441,16 @@ export default {
}, },
spacing: 8 spacing: 8
} : null } : null
const gridCfg = a.splitLine ? a.splitLine : DEFAULT_XAXIS_STYLE.splitLine
if (!gridCfg.dashStyle) {
gridCfg.dashStyle = DEFAULT_XAXIS_STYLE.splitLine.dashStyle
}
const grid = a.splitLine.show ? { const grid = a.splitLine.show ? {
line: { line: {
style: { style: {
stroke: a.splitLine.lineStyle.color, stroke: a.splitLine.lineStyle.color,
lineWidth: parseInt(a.splitLine.lineStyle.width) lineWidth: parseInt(a.splitLine.lineStyle.width),
lineDash: gridCfg.enableDash ? [gridCfg.dashStyle.width, gridCfg.dashStyle.offset] : undefined
} }
} }
} : null } : null

View File

@ -9,7 +9,7 @@
<packaging>pom</packaging> <packaging>pom</packaging>
<properties> <properties>
<dataease.version>1.18.13</dataease.version> <dataease.version>1.18.14</dataease.version>
</properties> </properties>
<name>dataease</name> <name>dataease</name>

View File

@ -36,4 +36,8 @@ public class XpackEmailTaskRequest extends XpackTaskCreateRequest {
private String groups; private String groups;
private Integer extWaitTime = 0; private Integer extWaitTime = 0;
private String roleList;
private String orgList;
} }

View File

@ -39,4 +39,8 @@ public class XpackEmailTemplateDTO implements Serializable {
private Integer extWaitTime = 0; private Integer extWaitTime = 0;
private String roleList;
private String orgList;
} }