diff --git a/README.md b/README.md index d1daf25fe8..29a135b1b8 100644 --- a/README.md +++ b/README.md @@ -74,6 +74,7 @@ curl -sSL https://github.com/dataease/dataease/releases/latest/download/quick_st ``` - [在线文档](https://dataease.io/docs/) +- [模板市场](https://dataease.io/templates/) - [教学视频](https://dataease.io/video.html) - [在线学习班](https://edu.fit2cloud.com/page/2635362?navIndex=0) diff --git a/backend/src/main/java/io/dataease/auth/aop/DePermissionAnnotationHandler.java b/backend/src/main/java/io/dataease/auth/aop/DePermissionAnnotationHandler.java index 8756836a95..7e3e722c7a 100644 --- a/backend/src/main/java/io/dataease/auth/aop/DePermissionAnnotationHandler.java +++ b/backend/src/main/java/io/dataease/auth/aop/DePermissionAnnotationHandler.java @@ -4,9 +4,13 @@ import io.dataease.auth.annotation.DePermission; import io.dataease.auth.annotation.DePermissions; import io.dataease.auth.entity.AuthItem; import io.dataease.auth.util.ReflectUtil; +import io.dataease.commons.constants.DePermissionType; import io.dataease.commons.utils.AuthUtils; -import io.dataease.commons.utils.LogUtil; +import io.dataease.dto.log.FolderItem; +import io.dataease.i18n.Translator; +import io.dataease.service.sys.log.LogManager; import org.apache.commons.lang3.ObjectUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.shiro.authz.UnauthorizedException; import org.apache.shiro.authz.annotation.Logical; import org.aspectj.lang.ProceedingJoinPoint; @@ -15,6 +19,7 @@ import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.reflect.MethodSignature; import org.springframework.stereotype.Component; +import javax.annotation.Resource; import java.lang.reflect.Array; import java.lang.reflect.Method; import java.util.*; @@ -24,6 +29,9 @@ import java.util.stream.Collectors; @Component public class DePermissionAnnotationHandler { + @Resource + private LogManager logManager; + @Around(value = "@annotation(io.dataease.auth.annotation.DePermissions)") public Object PermissionsAround(ProceedingJoinPoint point) throws Throwable { @@ -31,66 +39,59 @@ public class DePermissionAnnotationHandler { return point.proceed(point.getArgs()); } Boolean access = false; - try { - MethodSignature ms = (MethodSignature) point.getSignature(); - Method method = ms.getMethod(); - DePermissions annotation = method.getAnnotation(DePermissions.class); - Logical logical = annotation.logical(); - DePermission[] dePermissions = annotation.value(); - Object[] args = point.getArgs(); - if (logical == Logical.AND) { - access = true; - for (int i = 0; i < dePermissions.length; i++) { - DePermission permission = dePermissions[i]; - boolean currentAccess = access(args[permission.paramIndex()], permission, 0); - if (!currentAccess) { - access = false; - break; - } - } - } else { - List exceptions = new ArrayList<>(); - for (int i = 0; i < dePermissions.length; i++) { - DePermission permission = dePermissions[i]; - try { - boolean currentAccess = access(args[permission.paramIndex()], permission, 0); - if (currentAccess) { - access = true; - break; - } - } catch (Exception e) { - exceptions.add(e); - } - } - if (!access && exceptions.size() > 0) { - throw exceptions.get(0); + MethodSignature ms = (MethodSignature) point.getSignature(); + Method method = ms.getMethod(); + DePermissions annotation = method.getAnnotation(DePermissions.class); + Logical logical = annotation.logical(); + DePermission[] dePermissions = annotation.value(); + Object[] args = point.getArgs(); + if (logical == Logical.AND) { + access = true; + for (int i = 0; i < dePermissions.length; i++) { + DePermission permission = dePermissions[i]; + boolean currentAccess = access(args[permission.paramIndex()], permission, 0); + if (!currentAccess) { + access = false; + break; } } - } catch (Throwable throwable) { - LogUtil.error(throwable.getMessage(), throwable); - throw new RuntimeException(throwable.getMessage()); + } else { + List exceptions = new ArrayList<>(); + for (int i = 0; i < dePermissions.length; i++) { + DePermission permission = dePermissions[i]; + try { + boolean currentAccess = access(args[permission.paramIndex()], permission, 0); + if (currentAccess) { + access = true; + break; + } + } catch (Exception e) { + exceptions.add(e); + } + } + if (!access && exceptions.size() > 0) { + throw exceptions.get(0); + } } + return access ? point.proceed(point.getArgs()) : null; } @Around(value = "@annotation(io.dataease.auth.annotation.DePermission)") public Object PermissionAround(ProceedingJoinPoint point) throws Throwable { Boolean access = false; - try { - if (AuthUtils.getUser().getIsAdmin()) { - return point.proceed(point.getArgs()); - } - MethodSignature ms = (MethodSignature) point.getSignature(); - Method method = ms.getMethod(); - DePermission annotation = method.getAnnotation(DePermission.class); - Object arg = point.getArgs()[annotation.paramIndex()]; - if (access(arg, annotation, 0)) { - access = true; - } - } catch (Throwable throwable) { - LogUtil.error(throwable.getMessage(), throwable); - throw new RuntimeException(throwable.getMessage()); + + if (AuthUtils.getUser().getIsAdmin()) { + return point.proceed(point.getArgs()); } + MethodSignature ms = (MethodSignature) point.getSignature(); + Method method = ms.getMethod(); + DePermission annotation = method.getAnnotation(DePermission.class); + Object arg = point.getArgs()[annotation.paramIndex()]; + if (access(arg, annotation, 0)) { + access = true; + } + return access ? point.proceed(point.getArgs()) : null; } @@ -107,8 +108,7 @@ public class DePermissionAnnotationHandler { boolean permissionValid = resourceIds.contains(arg); if (permissionValid) return true; - throw new UnauthorizedException("Subject does not have permission[" + annotation.level().name() + ":" - + annotation.type() + ":" + arg + "]"); + throw new UnauthorizedException(msgI18n(arg, annotation)); } else if (ReflectUtil.isArray(parameterType)) { for (int i = 0; i < Array.getLength(arg); i++) { Object o = Array.get(arg, i); @@ -139,4 +139,26 @@ public class DePermissionAnnotationHandler { } return true; } + + private String msgI18n(Object arg, DePermission annotation) { + int sourceTypeValue = 0; + DePermissionType type = annotation.type(); + if (type == DePermissionType.DATASOURCE) { + sourceTypeValue = 1; + } + if (type == DePermissionType.DATASET) { + sourceTypeValue = 2; + } + if (type == DePermissionType.PANEL) { + sourceTypeValue = 3; + } + String name = arg.toString(); + if (sourceTypeValue > 0) { + FolderItem sourceInfo = logManager.nameWithId(arg.toString(), sourceTypeValue); + if (ObjectUtils.isNotEmpty(sourceInfo)) + name = StringUtils.isNotBlank(sourceInfo.getName()) ? sourceInfo.getName() : arg.toString(); + } + String msg = Translator.get("I18N_NO_PERMISSION") + "[" + Translator.get("I18N_" + annotation.level().name()) + ": " + Translator.get("SOURCE_TYPE_" + annotation.type().name()) + ": " + name + "]," + Translator.get("I18N_PLEASE_CONCAT_ADMIN"); + return msg; + } } diff --git a/backend/src/main/java/io/dataease/auth/aop/DePermissionProxyHandler.java b/backend/src/main/java/io/dataease/auth/aop/DePermissionProxyHandler.java index b37dc86f11..386bd8e98c 100644 --- a/backend/src/main/java/io/dataease/auth/aop/DePermissionProxyHandler.java +++ b/backend/src/main/java/io/dataease/auth/aop/DePermissionProxyHandler.java @@ -44,7 +44,6 @@ public class DePermissionProxyHandler { return point.proceed(args); } catch (Throwable throwable) { LogUtil.error(throwable.getMessage(), throwable); - /* throw new RuntimeException(throwable.getMessage()); */ DataEaseException.throwException(throwable); } finally { AuthUtils.cleanProxyUser(); diff --git a/backend/src/main/java/io/dataease/controller/sys/SystemParameterController.java b/backend/src/main/java/io/dataease/controller/sys/SystemParameterController.java index 456bab17b7..5da168408c 100644 --- a/backend/src/main/java/io/dataease/controller/sys/SystemParameterController.java +++ b/backend/src/main/java/io/dataease/controller/sys/SystemParameterController.java @@ -68,11 +68,12 @@ public class SystemParameterController { @RequiresPermissions("sysparam:read") @PostMapping("/edit/basic") public CasSaveResult editBasic(@RequestBody List systemParameter) { - int timeout = Integer.parseInt(systemParameter.stream().filter( - parameter -> parameter.getParamKey().equals("basic.frontTimeOut") - ).findFirst().get().getParamValue()); - if (timeout < 0 || timeout > 300) { //增加了合法性检验 - throw new NumberFormatException("Timeout Range Error!"); + String value = systemParameter.stream().filter(parameter -> parameter.getParamKey().equals("basic.frontTimeOut")).findFirst().get().getParamValue(); + if (StringUtils.isNotBlank(value)) { + int timeout = Integer.parseInt(value); + if (timeout < 0 || timeout > 300) { //增加了合法性检验 + throw new NumberFormatException("Timeout Range Error!"); + } } return systemParameterService.editBasic(systemParameter); } diff --git a/backend/src/main/java/io/dataease/service/chart/ChartViewFieldService.java b/backend/src/main/java/io/dataease/service/chart/ChartViewFieldService.java index 4cee1015c8..7ae96f9676 100644 --- a/backend/src/main/java/io/dataease/service/chart/ChartViewFieldService.java +++ b/backend/src/main/java/io/dataease/service/chart/ChartViewFieldService.java @@ -63,6 +63,12 @@ public class ChartViewFieldService { chartViewFieldMapper.deleteByExample(chartViewFieldExample); } + public void deleteByChartIds(List chartIds) { + ChartViewFieldExample chartViewFieldExample = new ChartViewFieldExample(); + chartViewFieldExample.createCriteria().andChartIdIn(chartIds); + chartViewFieldMapper.deleteByExample(chartViewFieldExample); + } + public void checkFieldName(ChartViewField chartViewField) { if (StringUtils.isNotEmpty(chartViewField.getName()) && StringUtils.isNotEmpty(chartViewField.getChartId())) { ChartViewFieldExample chartViewFieldExample = new ChartViewFieldExample(); @@ -77,4 +83,17 @@ public class ChartViewFieldService { } } } + + public void copyField(String sourceChartId, String targetChartId) { + ChartViewFieldExample chartViewFieldExample = new ChartViewFieldExample(); + chartViewFieldExample.createCriteria().andChartIdEqualTo(sourceChartId); + List chartViewFields = chartViewFieldMapper.selectByExampleWithBLOBs(chartViewFieldExample); + if (CollectionUtils.isNotEmpty(chartViewFields)) { + for (ChartViewField field : chartViewFields) { + field.setId(null); + field.setChartId(targetChartId); + save(field); + } + } + } } diff --git a/backend/src/main/java/io/dataease/service/chart/ChartViewService.java b/backend/src/main/java/io/dataease/service/chart/ChartViewService.java index 6ecf0b84a0..7e4a2add2d 100644 --- a/backend/src/main/java/io/dataease/service/chart/ChartViewService.java +++ b/backend/src/main/java/io/dataease/service/chart/ChartViewService.java @@ -103,6 +103,8 @@ public class ChartViewService { private ExtPanelGroupExtendDataMapper extPanelGroupExtendDataMapper; @Resource private ChartViewCacheService chartViewCacheService; + @Resource + private ChartViewFieldService chartViewFieldService; //默认使用非公平 @@ -450,7 +452,7 @@ public class ChartViewService { datasourceRequest.setQuery(qp.getSQL(dataTableInfoDTO.getTable(), xAxis, yAxis, fieldCustomFilter, extFilterList, ds, view)); } } else if (StringUtils.equalsIgnoreCase(table.getType(), DatasetType.SQL.name())) { - String sql = dataTableInfoDTO.getSql(); + String sql = dataTableInfoDTO.getSql(); sql = handleVariable(sql, requestList); if (StringUtils.equalsIgnoreCase("text", view.getType()) || StringUtils.equalsIgnoreCase("gauge", view.getType()) || StringUtils.equalsIgnoreCase("liquid", view.getType())) { datasourceRequest.setQuery(qp.getSQLSummaryAsTmp(sql, yAxis, fieldCustomFilter, extFilterList, view)); @@ -821,7 +823,7 @@ public class ChartViewService { datasourceRequest.setQuery(qp.getSQL(dataTableInfoDTO.getTable(), xAxis, yAxis, fieldCustomFilter, extFilterList, ds, view)); } } else if (StringUtils.equalsIgnoreCase(table.getType(), DatasetType.SQL.name())) { - String sql = dataTableInfoDTO.getSql(); + String sql = dataTableInfoDTO.getSql(); sql = handleVariable(sql, requestList); if (StringUtils.equalsIgnoreCase("text", view.getType()) || StringUtils.equalsIgnoreCase("gauge", view.getType()) || StringUtils.equalsIgnoreCase("liquid", view.getType())) { datasourceRequest.setQuery(qp.getSQLSummaryAsTmp(sql, yAxis, fieldCustomFilter, extFilterList, view)); @@ -1344,6 +1346,7 @@ public class ChartViewService { extChartViewMapper.copyCache(sourceViewId, newViewId); extPanelGroupExtendDataMapper.copyExtendData(sourceViewId, newViewId, panelId); chartViewCacheService.refreshCache(newViewId); + chartViewFieldService.copyField(sourceViewId, newViewId); return newViewId; } @@ -1492,17 +1495,17 @@ public class ChartViewService { chartViewMapper.updateByPrimaryKeySelective(chartView); } - private String handleVariable(String sql, ChartExtRequest requestList)throws Exception{ - if(requestList !=null &&CollectionUtils.isNotEmpty(requestList.getFilter()) ){ + private String handleVariable(String sql, ChartExtRequest requestList) throws Exception { + if (requestList != null && CollectionUtils.isNotEmpty(requestList.getFilter())) { for (ChartExtFilterRequest chartExtFilterRequest : requestList.getFilter()) { - if(CollectionUtils.isEmpty(chartExtFilterRequest.getValue())){ + if (CollectionUtils.isEmpty(chartExtFilterRequest.getValue())) { continue; } - if(chartExtFilterRequest.getValue().size() > 1){ + if (chartExtFilterRequest.getValue().size() > 1) { for (String parameter : chartExtFilterRequest.getParameters()) { sql = sql.replace("${" + parameter + "}", String.join(",", chartExtFilterRequest.getValue())); } - }else { + } else { for (String parameter : chartExtFilterRequest.getParameters()) { sql = sql.replace("${" + parameter + "}", chartExtFilterRequest.getValue().get(0)); } diff --git a/backend/src/main/java/io/dataease/service/chart/ViewPluginBaseServiceImpl.java b/backend/src/main/java/io/dataease/service/chart/ViewPluginBaseServiceImpl.java index 44db22b56b..618606c0b1 100644 --- a/backend/src/main/java/io/dataease/service/chart/ViewPluginBaseServiceImpl.java +++ b/backend/src/main/java/io/dataease/service/chart/ViewPluginBaseServiceImpl.java @@ -107,6 +107,7 @@ public class ViewPluginBaseServiceImpl implements ViewPluginBaseService { break; case SQL: tableName = dataSetTableService.handleVariableDefaultValue(dataTableInfoDTO.getSql(), pluginViewSet.getSqlVariableDetails()); + tableName = "(" + tableName + ")"; break; case CUSTOM: List list = dataSetTableUnionService.listByTableId(dataTableInfoDTO.getList().get(0).getTableId()); diff --git a/backend/src/main/resources/i18n/messages_en_US.properties b/backend/src/main/resources/i18n/messages_en_US.properties index 511fc52823..58413830be 100644 --- a/backend/src/main/resources/i18n/messages_en_US.properties +++ b/backend/src/main/resources/i18n/messages_en_US.properties @@ -163,3 +163,28 @@ i18n_user_not_exist=user does not exist i18n_default_login_reset=Switched back to default login mode + +I18N_COMMON_LEVEL_USE=Consult + +I18N_PANNEL_LEVEL_VIEW=Consult +I18N_PANNEL_LEVEL_EXPORT=Export +I18N_PANNEL_LEVEL_MANAGE=Manage +I18N_PANNEL_LEVEL_GRANT=Grant + +I18N_DATASET_LEVEL_USE=Consult +I18N_DATASET_LEVEL_MANAGE=Manage +I18N_DATASET_LEVEL_GRANT=Grant + +I18N_LINK_LEVEL_USE=Consult +I18N_LINK_LEVEL_MANAGE=Manage +I18N_LINK_LEVEL_GRANT=Grant + +I18N_DATASOURCE_LEVEL_USE=Consult +I18N_DATASOURCE_LEVEL_MANAGE=Manage +I18N_DATASOURCE_LEVEL_GRANT=Grant + +I18N_NO_PERMISSION=You do not have permission to + +I18N_PLEASE_CONCAT_ADMIN=Please contact the administrator for authorization + + diff --git a/backend/src/main/resources/i18n/messages_zh_CN.properties b/backend/src/main/resources/i18n/messages_zh_CN.properties index eacdf7fdc1..a79c70d0b5 100644 --- a/backend/src/main/resources/i18n/messages_zh_CN.properties +++ b/backend/src/main/resources/i18n/messages_zh_CN.properties @@ -166,4 +166,27 @@ i18n_not_admin_error=不是管理员账号 i18n_user_not_exist=用户不存在 -i18n_default_login_reset=已切换回默认登录方式 \ No newline at end of file +i18n_default_login_reset=已切换回默认登录方式 + +I18N_COMMON_LEVEL_USE=查看 + +I18N_PANNEL_LEVEL_VIEW=查看 +I18N_PANNEL_LEVEL_EXPORT=导出 +I18N_PANNEL_LEVEL_MANAGE=管理 +I18N_PANNEL_LEVEL_GRANT=授权 + +I18N_DATASET_LEVEL_USE=查看 +I18N_DATASET_LEVEL_MANAGE=管理 +I18N_DATASET_LEVEL_GRANT=授权 + +I18N_LINK_LEVEL_USE=查看 +I18N_LINK_LEVEL_MANAGE=管理 +I18N_LINK_LEVEL_GRANT=授权 + +I18N_DATASOURCE_LEVEL_USE=查看 +I18N_DATASOURCE_LEVEL_MANAGE=管理 +I18N_DATASOURCE_LEVEL_GRANT=授权 + +I18N_NO_PERMISSION=当前用户没有权限 + +I18N_PLEASE_CONCAT_ADMIN=请联系管理员开通 diff --git a/backend/src/main/resources/i18n/messages_zh_TW.properties b/backend/src/main/resources/i18n/messages_zh_TW.properties index e839966095..d322edc322 100644 --- a/backend/src/main/resources/i18n/messages_zh_TW.properties +++ b/backend/src/main/resources/i18n/messages_zh_TW.properties @@ -159,4 +159,29 @@ I18N_DRIVER_NOT_FOUND=未找到驅動 i18n_not_admin_error=不是管理員賬號 i18n_user_not_exist=用戶不存在 -i18n_default_login_reset=已切換回默認登錄方式 \ No newline at end of file +i18n_default_login_reset=已切換回默認登錄方式 + + + +I18N_COMMON_LEVEL_USE=查看 + +I18N_PANNEL_LEVEL_VIEW=查看 +I18N_PANNEL_LEVEL_EXPORT=導出 +I18N_PANNEL_LEVEL_MANAGE=管理 +I18N_PANNEL_LEVEL_GRANT=授權 + +I18N_DATASET_LEVEL_USE=查看 +I18N_DATASET_LEVEL_MANAGE=管理 +I18N_DATASET_LEVEL_GRANT=授權 + +I18N_LINK_LEVEL_USE=查看 +I18N_LINK_LEVEL_MANAGE=管理 +I18N_LINK_LEVEL_GRANT=授權 + +I18N_DATASOURCE_LEVEL_USE=查看 +I18N_DATASOURCE_LEVEL_MANAGE=管理 +I18N_DATASOURCE_LEVEL_GRANT=授權 + +I18N_NO_PERMISSION=當前用戶沒有權限 + +I18N_PLEASE_CONCAT_ADMIN=請聯系管理員開通 \ No newline at end of file diff --git a/frontend/src/components/ElTreeSelect/index.vue b/frontend/src/components/ElTreeSelect/index.vue index c135597b03..86bcb61a68 100644 --- a/frontend/src/components/ElTreeSelect/index.vue +++ b/frontend/src/components/ElTreeSelect/index.vue @@ -562,6 +562,7 @@ export default { // 显示弹出框的时候容错,查看是否和el宽度一致 _popoverShowFun(val) { this._updateH() + this.$emit('onFoucs') }, // 判断是否隐藏弹出框 _popoverHideFun(e) { diff --git a/frontend/src/components/dataease/DeOutWidget.vue b/frontend/src/components/dataease/DeOutWidget.vue index 8735cb4f8b..5cb6289de0 100644 --- a/frontend/src/components/dataease/DeOutWidget.vue +++ b/frontend/src/components/dataease/DeOutWidget.vue @@ -19,6 +19,7 @@
@@ -27,6 +28,7 @@ v-if="element.type==='custom'" :id="'component' + element.id" class="component-custom" + ref="deOutWidget" :out-style="element.style" :element="element" :in-draw="inDraw" @@ -44,8 +46,10 @@ - diff --git a/frontend/src/components/widget/DeWidget/DeInputSearch.vue b/frontend/src/components/widget/DeWidget/DeInputSearch.vue index f38ddef05c..56987e306c 100644 --- a/frontend/src/components/widget/DeWidget/DeInputSearch.vue +++ b/frontend/src/components/widget/DeWidget/DeInputSearch.vue @@ -6,6 +6,8 @@ resize="vertical" :placeholder="$t(element.options.attrs.placeholder)" :size="size" + class="de-range-tag" + ref="de-input-search" @input="valueChange" @keypress.enter.native="search" @dblclick="setEdit" @@ -111,6 +113,10 @@ export default { } - diff --git a/frontend/src/components/widget/DeWidget/DeNumberRange.vue b/frontend/src/components/widget/DeWidget/DeNumberRange.vue index c98a430b30..fcdde09fb5 100644 --- a/frontend/src/components/widget/DeWidget/DeNumberRange.vue +++ b/frontend/src/components/widget/DeWidget/DeNumberRange.vue @@ -3,11 +3,11 @@
- + {{ $t('denumberrange.split_placeholder') }} - +
diff --git a/frontend/src/components/widget/DeWidget/DeSelect.vue b/frontend/src/components/widget/DeWidget/DeSelect.vue index 04668dc91f..749ad44920 100644 --- a/frontend/src/components/widget/DeWidget/DeSelect.vue +++ b/frontend/src/components/widget/DeWidget/DeSelect.vue @@ -11,6 +11,8 @@ :popper-append-to-body="inScreen" :size="size" :filterable="true" + class="de-select-tag" + popper-class="coustom-de-select" @change="changeValue" @focus="setOptionWidth" @blur="onBlur" @@ -32,8 +34,10 @@ import { multFieldValues, linkMultFieldValues } from '@/api/dataset/dataset' import bus from '@/utils/bus' import { getLinkToken, getToken } from '@/utils/auth' -export default { +import customInput from '@/components/widget/DeWidget/customInput' +export default { + mixins: [customInput], props: { element: { type: Object, @@ -120,6 +124,7 @@ export default { this.show = false this.$nextTick(() => { this.show = true + this.handleCoustomStyle() }) }, 'element.options.attrs.sort': function(value, old) { @@ -253,6 +258,7 @@ export default { this.$nextTick(() => { // this.selectOptionWidth = event.srcElement.offsetWidth + 'px' this.selectOptionWidth = event.srcElement.parentElement.parentElement.offsetWidth + 'px' + this.handleCoustomStyle() }) } @@ -261,6 +267,45 @@ export default { } - + .popper__arrow, + .popper__arrow::after { + display: none !important; + } + + .el-select-dropdown__item { + color: var(--SelectColor, #606266); + } + + .el-select-dropdown__item.selected { + color: #409eff; + background-color: rgb(245, 247, 250, .5); + } + + .el-select-dropdown__item.hover { + background-color: rgb(245, 247, 250, .5); + } +} +.de-select-tag { + .el-select__tags { + .el-tag { + background-color: var(--BgSelectColor, #f4f4f5) !important; + border-color: var(--BrSelectColor, #e9e9eb) !important; + color: var(--SelectColor, #909399) !important; + + i { + color: var(--SelectColor, #909399) !important; + } + } + .el-icon-close { + background-color: var(--BgSelectColor, #C0C4CC) !important; + } + } +} + \ No newline at end of file diff --git a/frontend/src/components/widget/DeWidget/DeSelectGrid.vue b/frontend/src/components/widget/DeWidget/DeSelectGrid.vue index 1ca3012362..20c7e5885a 100644 --- a/frontend/src/components/widget/DeWidget/DeSelectGrid.vue +++ b/frontend/src/components/widget/DeWidget/DeSelectGrid.vue @@ -6,6 +6,7 @@ v-model="keyWord" :placeholder="$t('deinputsearch.placeholder')" :size="size" + ref="de-select-grid" prefix-icon="el-icon-search" clearable /> @@ -39,8 +40,9 @@ import { multFieldValues, linkMultFieldValues } from '@/api/dataset/dataset' import { getLinkToken, getToken } from '@/utils/auth' import bus from '@/utils/bus' -export default { +import { attrsMap, styleAttrs, textSelectGridWidget } from '@/components/widget/DeWidget/serviceNameFn.js' +export default { props: { element: { type: Object, @@ -76,7 +78,7 @@ export default { show: true, datas: [], isIndeterminate: false, - checkAll: false + checkAll: false, } }, computed: { @@ -96,6 +98,10 @@ export default { }, panelInfo() { return this.$store.state.panel.panelInfo + }, + cssArr() { + const { brColor, wordColor, innerBgColor } = this.element.style; + return { brColor, wordColor, innerBgColor } } }, watch: { @@ -130,6 +136,7 @@ export default { this.element.options.attrs.fieldId.length > 0 && method(param).then(res => { this.datas = this.optionDatas(res.data) + this.changeInputStyle() }) || (this.element.options.value = '') }, 'element.options.attrs.multiple': function(value, old) { @@ -148,6 +155,7 @@ export default { this.checkAll = this.value.length === this.datas.length this.isIndeterminate = this.value.length > 0 && this.value.length < this.datas.length } + this.changeInputStyle(); }) }, 'element.options.attrs.sort': function(value, old) { @@ -167,8 +175,14 @@ export default { this.element.options.attrs.fieldId.length > 0 && method(param).then(res => { this.datas = this.optionDatas(res.data) + this.changeInputStyle() }) || (this.element.options.value = '') - } + }, + cssArr: { + handler: 'changeInputStyle', + deep: true + }, + keyWord: 'changeInputStyle' }, created() { if (!this.element.options.attrs.sort) { @@ -191,6 +205,24 @@ export default { }, methods: { + changeInputStyle() { + if (!this.$parent.handlerInputStyle) return; + this.$nextTick(() => { + this.handlerInputStyle(this.element.style) + }) + }, + handlerInputStyle(newValue) { + let nodeCache = ''; + if (!this.$refs['de-select-grid']) return + styleAttrs.forEach(ele => { + if (!nodeCache) { + nodeCache = this.$refs['de-select-grid'].$el.querySelector('.el-input__inner') + } + nodeCache.style[attrsMap[ele]] = newValue[ele]; + this.textSelectGridWidget(this.$el, ele, newValue[ele]) + }) + }, + textSelectGridWidget: textSelectGridWidget, initLoad() { this.value = this.element.options.attrs.multiple ? [] : null if (this.element.options.attrs.fieldId) { @@ -202,6 +234,7 @@ export default { } method({ fieldIds: this.element.options.attrs.fieldId.split(','), sort: this.element.options.attrs.sort }).then(res => { this.datas = this.optionDatas(res.data) + this.changeInputStyle() if (this.element.options.attrs.multiple) { this.checkAll = this.value.length === this.datas.length this.isIndeterminate = this.value.length > 0 && this.value.length < this.datas.length diff --git a/frontend/src/components/widget/DeWidget/DeSelectTree.vue b/frontend/src/components/widget/DeWidget/DeSelectTree.vue index a7f29ed2d7..b08009db08 100644 --- a/frontend/src/components/widget/DeWidget/DeSelectTree.vue +++ b/frontend/src/components/widget/DeWidget/DeSelectTree.vue @@ -15,6 +15,7 @@ @removeTag="changeNodeIds" @check="changeCheckNode" @select-clear="selectClear" + @onFoucs="onFoucs" /> @@ -24,8 +25,11 @@ import { mappingFieldValues, linkMappingFieldValues } from '@/api/dataset/datase import bus from '@/utils/bus' import { getLinkToken, getToken } from '@/utils/auth' import ElTreeSelect from '@/components/ElTreeSelect' +import customInput from '@/components/widget/DeWidget/customInput' + export default { components: { ElTreeSelect }, + mixins: [customInput], props: { element: { type: Object, @@ -208,6 +212,11 @@ export default { }, methods: { + onFoucs() { + this.$nextTick(() => { + this.handleCoustomStyle() + }) + }, selectClear() { this.changeValue(this.value) }, @@ -354,6 +363,33 @@ export default { } - diff --git a/frontend/src/components/widget/DeWidget/customInput.js b/frontend/src/components/widget/DeWidget/customInput.js new file mode 100644 index 0000000000..a33343629d --- /dev/null +++ b/frontend/src/components/widget/DeWidget/customInput.js @@ -0,0 +1,39 @@ +// 通过控制css变量控制过滤组件弹框样式 de-select-grid除外 +import { attrsMap, styleAttrs } from '@/components/widget/DeWidget/serviceNameFn.js' + +export default { + data() { + return { + attrsMap, + styleAttrs, + // 过滤组件名css变量映射 + refComNameMap: { + 'de-date': ['--BgDateColor', '--DateColor', '--BrDateColor'], + 'de-select': ['--BgSelectColor', '--SelectColor', '--BrSelectColor'], + 'de-select-tree': ['--BgSelectTreeColor', '--SelectTreeColor', '--BrSelectTreeColor'], + "de-input-search": ['--BgSearchColor', '--SearchColor', '--BrSearchColor'], + "de-number-range": ['--BgRangeColor', '--RangeColor', '--BrRangeColor'] + } + } + }, + mounted() { + this.handleCoustomStyle() + }, + methods: { + typeTransform() { + let refNode = this.refComNameMap[this.element.component]; + if (!refNode) return []; + return refNode + }, + handleCoustomStyle() { + // 判断组件是否是在仪表板内部 否则css样式取默认值 + const isPanelDe = this.$parent.handlerInputStyle; + const { brColor, wordColor, innerBgColor } = this.element.style; + const newValue = { brColor, wordColor, innerBgColor }; + const cssVar = this.typeTransform(); + this.styleAttrs.forEach((ele, index) => { + document.documentElement.style.setProperty(cssVar[index], !isPanelDe ? '' : newValue[ele]) + }) + }, + } +} \ No newline at end of file diff --git a/frontend/src/components/widget/DeWidget/inputStyleMixin.js b/frontend/src/components/widget/DeWidget/inputStyleMixin.js new file mode 100644 index 0000000000..5c9b52d6cb --- /dev/null +++ b/frontend/src/components/widget/DeWidget/inputStyleMixin.js @@ -0,0 +1,74 @@ +// 通过控制 js 控制过滤组件输入框样式 如需额外处理 声明组件serviceName同名函数处理 +import { timeDateRangeWidget, textInputWidget, attrsMap, styleAttrs } from '@/components/widget/DeWidget/serviceNameFn.js' +export default { + data() { + return { + attrsMap, + styleAttrs, + // 过滤组件名ref映射 + refComNameMap: { + 'de-date': 'dateRef', + 'de-select-grid': 'de-select-grid', + 'de-select': 'deSelect', + 'de-select-tree': 'deSelectTree', + "de-input-search": "de-input-search", + "de-number-range": ['de-number-range-min', 'de-number-range-max'] + } + } + }, + watch: { + cssArr: { + handler(newValue) { + if (!this.isFilterComponent) return; + this.typeTransform().forEach(ele => { + this.handlerInputStyle(ele, newValue) + }) + }, + deep: true + }, + }, + computed: { + cssArr() { + const { brColor, wordColor, innerBgColor } = this.element.style; + return { brColor, wordColor, innerBgColor } + } + }, + mounted() { + if (!this.isFilterComponent) return; + this.typeTransform().forEach(item => { + const nodeCache = this.$refs.deOutWidget.$refs[item].$el.querySelector('.el-input__inner') || this.$refs.deOutWidget.$refs[item].$el + this.styleAttrs.forEach(ele => { + nodeCache.style[this.attrsMap[ele]] = this.element.style[ele]; + this[this.element.serviceName] && this[this.element.serviceName](this.selectRange(item), ele, this.element.style[ele]) + }) + }) + }, + methods: { + handlerInputStyle(type, newValue) { + let nodeCache = ''; + this.styleAttrs.forEach(ele => { + if (!nodeCache) { + nodeCache = this.$refs.deOutWidget.$refs[type].$el.querySelector('.el-input__inner') || this.$refs.deOutWidget.$refs[type].$el + } + nodeCache.style[this.attrsMap[ele]] = newValue[ele]; + this[this.element.serviceName] && this[this.element.serviceName](this.selectRange(type), ele, newValue[ele]) + }) + }, + selectRange(item) { + if (this.element.component === 'de-select-grid') { + return this.$refs.deOutWidget.$el; + } + return this.$refs.deOutWidget.$refs[item].$el; + }, + timeDateRangeWidget: timeDateRangeWidget, + textInputWidget: textInputWidget, + typeTransform() { + let refNode = this.refComNameMap[this.element.component]; + if (!refNode) return []; + if (!Array.isArray(refNode)) { + refNode = [refNode] + } + return refNode + } + } +} \ No newline at end of file diff --git a/frontend/src/components/widget/DeWidget/serviceNameFn.js b/frontend/src/components/widget/DeWidget/serviceNameFn.js new file mode 100644 index 0000000000..da8a9faacc --- /dev/null +++ b/frontend/src/components/widget/DeWidget/serviceNameFn.js @@ -0,0 +1,46 @@ +const attrsMap = { brColor: 'borderColor', wordColor: 'color', innerBgColor: 'backgroundColor' } +const styleAttrs = ['innerBgColor', 'wordColor', 'brColor'] +function timeDateRangeWidget (nodeCache, name, value) { + const classList = ['.el-range-input', '.el-range-separator'] + classList.forEach(ele => { + let nodeList = nodeCache.querySelectorAll(ele); + if (!nodeList.length) return; + nodeList.forEach(ele => { + ele.style[attrsMap[name]] = value; + }) + }) +} +function textInputWidget (nodeCache, name, value) { + let groupAppend = nodeCache.querySelector('.el-input-group__append'); + groupAppend.style[attrsMap[name]] = value; + if (name === 'brColor') { + groupAppend.style.borderLeft = 'none' + } +} + +function textSelectGridWidget (nodeCache, name, value) { + if (name === 'innerBgColor') { + nodeCache.querySelector('.list').style.backgroundColor = value; + } + if (name === 'wordColor') { + let elRadio = nodeCache.querySelectorAll('.el-radio') + let elCheckbox = nodeCache.querySelectorAll('.el-checkbox') + if (elRadio.length) { + elRadio.forEach(ele => { + ele.style.color = value; + }); + } + if (elCheckbox.length) { + elCheckbox.forEach(ele => { + ele.style.color = value; + }); + } + } +} +export { + attrsMap, + styleAttrs, + timeDateRangeWidget, + textInputWidget, + textSelectGridWidget, +} \ No newline at end of file diff --git a/frontend/src/styles/theme/dark.scss b/frontend/src/styles/theme/dark.scss index 9f81402905..ba6728df40 100644 --- a/frontend/src/styles/theme/dark.scss +++ b/frontend/src/styles/theme/dark.scss @@ -22,6 +22,32 @@ $--color-black: #FFFFFF; $--background-color-base: #171b22; +/* 定义全局变量 */ +:root{ + --BgSelectColor: #ffffff; + --SelectColor: #fff; + --BrSelectColor: #fff; + + --BgSelectTreeColor: #ffffff; + --SelectTreeColor: #fff; + --BrSelectTreeColor: #fff; + + --BgDateColor: #ffffff; + --DateColor: #fff; + --BrDateColor: #fff; + + --BgRangeColor: #ffffff; + --RangeColor: #fff; + --BrRangeColor: #fff; + + --BgSerachColor: #ffffff; + --SerachColor: #fff; + --BrSerachColor: #fff; + + --BgSelectGridColor: #ffffff; + --SelectGridColor: #fff; + --BrSelectGridColor: #fff; +} // 与CSS原生变量映射 #app { @@ -56,3 +82,4 @@ $--background-color-base: #171b22; } + diff --git a/frontend/src/views/background/index.vue b/frontend/src/views/background/index.vue index d47352fb5c..8f433ad1a9 100644 --- a/frontend/src/views/background/index.vue +++ b/frontend/src/views/background/index.vue @@ -93,6 +93,29 @@ + + + 输入框样式(颜色): + + + 边框 + + + + + + 文字 + + + + + + 背景 + + + + + @@ -139,7 +162,10 @@ export default { ...mapState([ 'curComponent', 'componentData' - ]) + ]), + isFilterComponent() { + return ['de-select', 'de-select-grid', 'de-date', "de-input-search", "de-number-range", "de-select-tree"].includes(this.curComponent.component) + } }, methods: { init() { diff --git a/frontend/src/views/system/plugin/index.vue b/frontend/src/views/system/plugin/index.vue index 794e8bde69..0688c6b4d5 100644 --- a/frontend/src/views/system/plugin/index.vue +++ b/frontend/src/views/system/plugin/index.vue @@ -118,6 +118,16 @@ export default { }, uploadFail(response, file, fileList) { const msg = response && response.message || '安装失败' + try { + const result = JSON.parse(msg) + if (result && result.message) { + this.$error(result.message) + this.uploading = false + } + return + } catch (e) { + console.error(e) + } this.$error(msg) this.uploading = false },