diff --git a/backend/src/main/java/io/dataease/auth/filter/F2CDocFilter.java b/backend/src/main/java/io/dataease/auth/filter/F2CDocFilter.java index 022180c4b3..78ff0a82f2 100644 --- a/backend/src/main/java/io/dataease/auth/filter/F2CDocFilter.java +++ b/backend/src/main/java/io/dataease/auth/filter/F2CDocFilter.java @@ -1,26 +1,99 @@ package io.dataease.auth.filter; -import org.apache.shiro.web.filter.authc.AnonymousFilter; +import cn.hutool.core.util.ArrayUtil; +import io.dataease.auth.entity.SysUserEntity; +import io.dataease.auth.entity.TokenInfo; +import io.dataease.auth.service.AuthUserService; +import io.dataease.auth.util.JWTUtils; +import io.dataease.commons.license.DefaultLicenseService; +import io.dataease.commons.license.F2CLicenseResponse; +import io.dataease.commons.utils.CommonBeanFactory; +import io.dataease.commons.utils.LogUtil; +import org.apache.commons.lang3.ObjectUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.shiro.web.filter.AccessControlFilter; -import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; +import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; -import java.io.IOException; +import javax.servlet.http.HttpServletResponse; +import java.util.Arrays; + +import static io.dataease.commons.license.F2CLicenseResponse.Status; + +public class F2CDocFilter extends AccessControlFilter { + + private static final String RESULT_URI_KEY = "result_uri_key"; + private static final String NOLIC_PAGE = "nolic.html"; + private static final String NO_LOGIN_PAGE = "/nologin.html"; + private static final String DEFAULT_FAILED_PAGE = "/"; -public class F2CDocFilter extends AnonymousFilter { @Override - protected boolean onPreHandle(ServletRequest request, ServletResponse response, Object mappedValue) { - HttpServletRequest req = (HttpServletRequest) request; - String path = "/deApi"; + protected boolean isAccessAllowed(ServletRequest servletRequest, ServletResponse servletResponse, Object o) throws Exception { + HttpServletRequest request = (HttpServletRequest) servletRequest; try { - req.getRequestDispatcher(path).forward(req, response); - } catch (ServletException e) { - e.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); + DefaultLicenseService defaultLicenseService = CommonBeanFactory.getBean(DefaultLicenseService.class); + F2CLicenseResponse f2CLicenseResponse = defaultLicenseService.validateLicense(); + Status status = f2CLicenseResponse.getStatus(); + if (status != Status.valid) { + request.setAttribute(RESULT_URI_KEY, NOLIC_PAGE); + return false; + } + } catch (Exception e) { + request.setAttribute(RESULT_URI_KEY, NOLIC_PAGE); + LogUtil.error(e.getMessage(), e); + return false; } + + try { + Boolean isLogin = validateLogin(request); + if (!isLogin) { + request.setAttribute(RESULT_URI_KEY, NO_LOGIN_PAGE); + return false; + } + } catch (Exception e) { + request.setAttribute(RESULT_URI_KEY, NO_LOGIN_PAGE); + LogUtil.error(e.getMessage(), e); + return false; + } + return true; } + + private Boolean validateLogin(HttpServletRequest request) throws Exception{ + String authorization = request.getHeader("Authorization"); + if (StringUtils.isBlank(authorization)) { + Cookie[] cookies = request.getCookies(); + if (ArrayUtil.isNotEmpty(cookies)) { + Cookie cookie = Arrays.stream(cookies).filter(item -> StringUtils.equals(item.getName(), "Authorization")).findFirst().orElse(null); + if (ObjectUtils.isNotEmpty(cookie) && StringUtils.isNotBlank(cookie.getValue())) { + authorization = cookie.getValue(); + } + } + } + if (StringUtils.isBlank(authorization)) { + return false; + } + TokenInfo tokenInfo = JWTUtils.tokenInfoByToken(authorization); + AuthUserService authUserService = CommonBeanFactory.getBean(AuthUserService.class); + SysUserEntity user = authUserService.getUserById(tokenInfo.getUserId()); + if (user == null) { + return false; + } + String password = user.getPassword(); + boolean verify = JWTUtils.verify(authorization, tokenInfo, password); + return verify; + } + + @Override + protected boolean onAccessDenied(ServletRequest req, ServletResponse res) throws Exception { + HttpServletResponse response = (HttpServletResponse) res; + HttpServletRequest request = (HttpServletRequest) req; + Object attribute = request.getAttribute(RESULT_URI_KEY); + String path = ObjectUtils.isNotEmpty(attribute) ? attribute.toString() : DEFAULT_FAILED_PAGE; + request.getRequestDispatcher(path).forward(request, response); + return false; + } } diff --git a/backend/src/main/java/io/dataease/auth/filter/JWTFilter.java b/backend/src/main/java/io/dataease/auth/filter/JWTFilter.java index a68673c3c1..2d60576759 100644 --- a/backend/src/main/java/io/dataease/auth/filter/JWTFilter.java +++ b/backend/src/main/java/io/dataease/auth/filter/JWTFilter.java @@ -1,5 +1,6 @@ package io.dataease.auth.filter; +import cn.hutool.core.util.URLUtil; import com.auth0.jwt.algorithms.Algorithm; import io.dataease.auth.entity.ASKToken; import io.dataease.auth.entity.JWTToken; @@ -23,8 +24,10 @@ import org.springframework.web.bind.annotation.RequestMethod; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; +import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import java.nio.charset.Charset; public class JWTFilter extends BasicHttpAuthenticationFilter { @@ -158,4 +161,18 @@ public class JWTFilter extends BasicHttpAuthenticationFilter { httpServletResponse.setHeader("authentication-status", "login_expire"); } + @Override + protected boolean onAccessDenied(ServletRequest req, ServletResponse res, Object mappedValue) throws Exception { + HttpServletResponse response = (HttpServletResponse) res; + HttpServletRequest request = (HttpServletRequest) req; + String requestURI = request.getRequestURI(); + String msg = requestURI + " has been denied"; + String encode = URLUtil.encode(msg, Charset.forName("UTF-8")); + Cookie cookie_error = new Cookie("onAccessDeniedMsg", encode); + cookie_error.setPath("/"); + response.addCookie(cookie_error); + response.sendRedirect("/"); + return false; + } + } diff --git a/backend/src/main/java/io/dataease/auth/service/impl/ShiroServiceImpl.java b/backend/src/main/java/io/dataease/auth/service/impl/ShiroServiceImpl.java index c90acdab05..d6b7c60896 100644 --- a/backend/src/main/java/io/dataease/auth/service/impl/ShiroServiceImpl.java +++ b/backend/src/main/java/io/dataease/auth/service/impl/ShiroServiceImpl.java @@ -11,6 +11,7 @@ import java.util.Map; public class ShiroServiceImpl implements ShiroService { private final static String ANON = "anon"; + private final static String DOC = "doc"; @Override public Map loadFilterChainDefinitionMap() { @@ -20,15 +21,18 @@ public class ShiroServiceImpl implements ShiroService { // ---------------------------------------------------------- // 放行Swagger2页面,需要放行这些 - filterChainDefinitionMap.put("/doc.html**", "doc"); - filterChainDefinitionMap.put("/deApi**", ANON); + filterChainDefinitionMap.put("/doc.html**", DOC); + filterChainDefinitionMap.put("/deApi**", DOC); filterChainDefinitionMap.put("/swagger-ui.html", ANON); filterChainDefinitionMap.put("/swagger-ui/**", ANON); filterChainDefinitionMap.put("/swagger/**", ANON); filterChainDefinitionMap.put("/webjars/**", ANON); - filterChainDefinitionMap.put("/swagger-resources/**", ANON); - filterChainDefinitionMap.put("/v2/**", ANON); - filterChainDefinitionMap.put("/v3/**", ANON); + filterChainDefinitionMap.put("/swagger-resources/**", DOC); + filterChainDefinitionMap.put("/v2/**", DOC); + filterChainDefinitionMap.put("/v3/**", DOC); + + filterChainDefinitionMap.put("/**.gif", ANON); + filterChainDefinitionMap.put("/**.png", ANON); filterChainDefinitionMap.put("/static/**", ANON); filterChainDefinitionMap.put("/css/**", ANON); @@ -108,6 +112,8 @@ public class ShiroServiceImpl implements ShiroService { filterChainDefinitionMap.put("/plugin/larksuite/getQrParam", ANON); filterChainDefinitionMap.put("/cas/reset/**", ANON); filterChainDefinitionMap.put("/cas/loginPage", ANON); + filterChainDefinitionMap.put("/pdf-template/queryAll", ANON); + filterChainDefinitionMap.put("/unauth", ANON); filterChainDefinitionMap.put("/display/**", ANON); @@ -122,6 +128,7 @@ public class ShiroServiceImpl implements ShiroService { filterChainDefinitionMap.put("/panel/group/exportDetails", ANON); filterChainDefinitionMap.put("/dataset/field/linkMultFieldValues", "link"); filterChainDefinitionMap.put("/dataset/field/linkMappingFieldValues", "link"); + filterChainDefinitionMap.put("/systemInfo/proxyUserLoginInfo/**", ANON); filterChainDefinitionMap.put("/**", "authc"); diff --git a/backend/src/main/java/io/dataease/controller/IndexController.java b/backend/src/main/java/io/dataease/controller/IndexController.java index aacee431cd..857ab7eadc 100644 --- a/backend/src/main/java/io/dataease/controller/IndexController.java +++ b/backend/src/main/java/io/dataease/controller/IndexController.java @@ -2,17 +2,16 @@ package io.dataease.controller; import io.dataease.commons.exception.DEException; import io.dataease.commons.license.DefaultLicenseService; -import io.dataease.commons.license.F2CLicenseResponse; import io.dataease.commons.utils.CodingUtil; import io.dataease.commons.utils.LogUtil; import io.dataease.commons.utils.ServletUtils; import io.dataease.service.panel.PanelLinkService; import org.apache.commons.lang3.StringUtils; -import org.springframework.http.HttpRequest; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; + import javax.annotation.Resource; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; @@ -42,13 +41,7 @@ public class IndexController { @GetMapping("/deApi") public String deApi() { - F2CLicenseResponse f2CLicenseResponse = defaultLicenseService.validateLicense(); - switch (f2CLicenseResponse.getStatus()) { - case valid: - return "doc.html"; - default: - return "nolic.html"; - } + return "doc.html"; } @GetMapping("/link/{index}") @@ -64,8 +57,8 @@ public class IndexController { // TODO 增加仪表板外部参数 HttpServletRequest request = ServletUtils.request(); String attachParams = request.getParameter("attachParams"); - if(StringUtils.isNotEmpty(attachParams)){ - url = url+"&attachParams="+attachParams; + if (StringUtils.isNotEmpty(attachParams)) { + url = url + "&attachParams=" + attachParams; } response.sendRedirect(url); } catch (IOException e) { diff --git a/backend/src/main/java/io/dataease/controller/sys/SystemInfoController.java b/backend/src/main/java/io/dataease/controller/sys/SystemInfoController.java index 4177a004a1..5322ca8e12 100644 --- a/backend/src/main/java/io/dataease/controller/sys/SystemInfoController.java +++ b/backend/src/main/java/io/dataease/controller/sys/SystemInfoController.java @@ -3,6 +3,7 @@ package io.dataease.controller.sys; import io.dataease.dto.UserLoginInfoDTO; import io.dataease.service.SystemInfoService; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import springfox.documentation.annotations.ApiIgnore; @@ -19,6 +20,11 @@ public class SystemInfoController { @GetMapping("userLoginInfo") public UserLoginInfoDTO userLoginInfo() throws IOException { - return systemInfoService.getUserLoginInfo(); + return systemInfoService.getUserLoginInfo(null); + } + + @GetMapping("proxyUserLoginInfo/{userId}") + public UserLoginInfoDTO proxyUserLoginInfo(@PathVariable String userId) throws IOException { + return systemInfoService.getUserLoginInfo(userId); } } diff --git a/backend/src/main/java/io/dataease/service/SystemInfoService.java b/backend/src/main/java/io/dataease/service/SystemInfoService.java index f696a6fea5..b9d2dfb7e3 100644 --- a/backend/src/main/java/io/dataease/service/SystemInfoService.java +++ b/backend/src/main/java/io/dataease/service/SystemInfoService.java @@ -1,15 +1,30 @@ package io.dataease.service; +import io.dataease.auth.api.dto.CurrentUserDto; import io.dataease.commons.utils.AuthUtils; +import io.dataease.commons.utils.BeanUtils; import io.dataease.commons.utils.IPUtils; import io.dataease.dto.UserLoginInfoDTO; +import io.dataease.plugins.common.base.domain.SysUser; +import io.dataease.plugins.common.base.mapper.SysUserMapper; +import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Service; +import javax.annotation.Resource; + @Service public class SystemInfoService { + @Resource + private SysUserMapper sysUserMapper; - public UserLoginInfoDTO getUserLoginInfo() { + public UserLoginInfoDTO getUserLoginInfo(String userId) { + if (StringUtils.isNotEmpty(userId)) { + SysUser userInfo = sysUserMapper.selectByPrimaryKey(Long.parseLong(userId)); + CurrentUserDto userDto = new CurrentUserDto(); + BeanUtils.copyBean(userDto, userInfo); + return new UserLoginInfoDTO(userDto, IPUtils.get()); + } return new UserLoginInfoDTO(AuthUtils.getUser(), IPUtils.get()); } 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 34b5601182..32d6f0f62d 100644 --- a/backend/src/main/java/io/dataease/service/chart/ChartViewService.java +++ b/backend/src/main/java/io/dataease/service/chart/ChartViewService.java @@ -908,7 +908,7 @@ public class ChartViewService { if (StringUtils.equalsIgnoreCase(table.getType(), DatasetType.DB.name())) { datasourceRequest.setTable(dataTableInfoDTO.getTable()); if (StringUtils.equalsAnyIgnoreCase(view.getType(), "text", "gauge", "liquid")) { - datasourceRequest.setQuery(qp.getSQLSummary(dataTableInfoDTO.getTable(), yAxis, fieldCustomFilter, rowPermissionsTree, extFilterList, view, ds)); + querySql = qp.getSQLSummary(dataTableInfoDTO.getTable(), yAxis, fieldCustomFilter, rowPermissionsTree, extFilterList, view, ds); } else if (StringUtils.containsIgnoreCase(view.getType(), "stack")) { querySql = qp.getSQLStack(dataTableInfoDTO.getTable(), xAxis, yAxis, fieldCustomFilter, rowPermissionsTree, extFilterList, extStack, ds, view); } else if (StringUtils.containsIgnoreCase(view.getType(), "scatter")) { diff --git a/frontend/public/dynamic.gif b/frontend/public/dynamic.gif new file mode 100644 index 0000000000..d70762819a Binary files /dev/null and b/frontend/public/dynamic.gif differ diff --git a/frontend/public/lic.png b/frontend/public/lic.png new file mode 100644 index 0000000000..27f6c77607 Binary files /dev/null and b/frontend/public/lic.png differ diff --git a/frontend/public/nolic.html b/frontend/public/nolic.html index fc6f71162b..f7bb622070 100644 --- a/frontend/public/nolic.html +++ b/frontend/public/nolic.html @@ -1,13 +1,46 @@ + DataEase + + + -
缺少许可
+ +
+ 缺少许可 +
- + + + + \ No newline at end of file diff --git a/frontend/public/nologin.html b/frontend/public/nologin.html new file mode 100644 index 0000000000..d173f43855 --- /dev/null +++ b/frontend/public/nologin.html @@ -0,0 +1,50 @@ + + + + + + + + DataEase + + + + + + +
+ 请先登录,即将跳转! +
+ + + + + + \ No newline at end of file diff --git a/frontend/src/api/systemInfo/userLogin.js b/frontend/src/api/systemInfo/userLogin.js index 95add502fb..87ab9fc4af 100644 --- a/frontend/src/api/systemInfo/userLogin.js +++ b/frontend/src/api/systemInfo/userLogin.js @@ -8,6 +8,15 @@ export function userLoginInfo() { }) } -export default { - userLoginInfo +export function proxyUserLoginInfo(userId) { + return request({ + url: '/systemInfo/proxyUserLoginInfo/' + userId, + method: 'get', + loading: false + }) +} + +export default { + userLoginInfo, + proxyUserLoginInfo } diff --git a/frontend/src/components/canvas/components/editor/CanvasOptBar.vue b/frontend/src/components/canvas/components/editor/CanvasOptBar.vue index d5643e5c3f..e41f595138 100644 --- a/frontend/src/components/canvas/components/editor/CanvasOptBar.vue +++ b/frontend/src/components/canvas/components/editor/CanvasOptBar.vue @@ -1,18 +1,35 @@ @@ -74,12 +112,13 @@ import bus from '@/utils/bus' import { buildFilterMap, buildViewKeyMap, formatCondition, valueValid, viewIdMatch } from '@/utils/conditionUtil' import { hasDataPermission } from '@/utils/permission' import { activeWatermark } from '@/components/canvas/tools/watermark' -import { userLoginInfo } from '@/api/systemInfo/userLogin' - +import { proxyUserLoginInfo, userLoginInfo } from '@/api/systemInfo/userLogin' +import html2canvas from 'html2canvasde' +import { queryAll } from '@/api/panel/pdfTemplate' const erd = elementResizeDetectorMaker() - +import PDFPreExport from '@/views/panel/export/PDFPreExport' export default { - components: { ComponentWrapper, CanvasOptBar }, + components: { ComponentWrapper, CanvasOptBar, PDFPreExport }, model: { prop: 'show', event: 'change' @@ -140,10 +179,15 @@ export default { type: String, require: false, default: 'canvas-main' + }, + userId: { + type: String, + require: false } }, data() { return { + canvasInfoTemp: 'preview-temp-canvas-main', previewMainDomId: 'preview-main-' + this.canvasId, previewDomId: 'preview-' + this.canvasId, previewRefId: 'preview-ref-' + this.canvasId, @@ -171,7 +215,15 @@ export default { searchCount: 0, // 布局展示 1.pc pc端布局 2.mobile 移动端布局 terminal: 'pc', - buttonFilterMap: null + buttonFilterMap: null, + pdfExportShow: false, + dataLoading: false, + exporting: false, + snapshotInfo: '', + pdfTemplateSelectedIndex: 0, + pdfTemplateContent: '', + templateInfo: {}, + pdfTemplateAll: [] } }, computed: { @@ -309,6 +361,7 @@ export default { } bus.$on('trigger-search-button', this.triggerSearchButton) bus.$on('trigger-reset-button', this.triggerResetButton) + this.initPdfTemplate() }, beforeDestroy() { erd.uninstall(this.$refs[this.previewTempRefId]) @@ -544,6 +597,36 @@ export default { }) } }, 1500) + }, + downloadAsPDF() { + this.dataLoading = true + const domId = this.canvasInfoTemp + setTimeout(() => { + this.exporting = true + setTimeout(() => { + html2canvas(document.getElementById(domId)).then(canvas => { + const snapshot = canvas.toDataURL('image/jpeg', 1) // 是图片质量 + this.dataLoading = false + this.exporting = false + if (snapshot !== '') { + this.snapshotInfo = snapshot + this.pdfExportShow = true + } + }) + }, 1500) + }, 500) + }, + closePreExport() { + this.pdfExportShow = false + }, + changePdfTemplate() { + this.pdfTemplateContent = this.pdfTemplateAll[this.pdfTemplateSelectedIndex] ? this.pdfTemplateAll[this.pdfTemplateSelectedIndex].templateContent : '' + }, + initPdfTemplate() { + queryAll().then(res => { + this.pdfTemplateAll = res.data + this.changePdfTemplate() + }) } } } diff --git a/frontend/src/components/canvas/customComponent/UserView.vue b/frontend/src/components/canvas/customComponent/UserView.vue index f6a0cd6c92..cfedd58b54 100644 --- a/frontend/src/components/canvas/customComponent/UserView.vue +++ b/frontend/src/components/canvas/customComponent/UserView.vue @@ -640,7 +640,7 @@ export default { }, viewInCache(param) { this.view = param.view - if (this.view.customAttr) { + if (this.view && this.view.customAttr) { this.currentPage.pageSize = parseInt(JSON.parse(this.view.customAttr).size.tablePageSize) } param.viewId && param.viewId === this.element.propValue.viewId && this.getDataEdit(param) @@ -703,7 +703,7 @@ export default { requestInfo.proxy = { userId: this.panelInfo.proxy } } // table-info明细表增加分页 - if (this.view.customAttr) { + if (this.view && this.view.customAttr) { const attrSize = JSON.parse(this.view.customAttr).size if (this.chart.type === 'table-info' && this.view.datasetMode === 0 && (!attrSize.tablePageMode || attrSize.tablePageMode === 'page')) { requestInfo.goPage = this.currentPage.page @@ -1162,7 +1162,7 @@ export default { queryFrom: 'panel' } // table-info明细表增加分页 - if (this.view.customAttr) { + if (this.view && this.view.customAttr) { const attrSize = JSON.parse(this.view.customAttr).size if (this.chart.type === 'table-info' && this.view.datasetMode === 0 && (!attrSize.tablePageMode || attrSize.tablePageMode === 'page')) { requestInfo.goPage = this.currentPage.page diff --git a/frontend/src/lang/en.js b/frontend/src/lang/en.js index eabb66daf5..9068ffd9bb 100644 --- a/frontend/src/lang/en.js +++ b/frontend/src/lang/en.js @@ -1865,8 +1865,12 @@ export default { sure_bt: 'Confirm' }, panel: { + + down: 'Down', + mobile_style_setting: 'Style setting', mobile_style_setting_tips: 'Customize the mobile background', + board: 'Border', text: 'Text', board_background: 'Background', diff --git a/frontend/src/lang/tw.js b/frontend/src/lang/tw.js index ddd3278562..2814a8f010 100644 --- a/frontend/src/lang/tw.js +++ b/frontend/src/lang/tw.js @@ -1865,8 +1865,12 @@ export default { sure_bt: '確定' }, panel: { + + down: '下載', + mobile_style_setting: '樣式設置', mobile_style_setting_tips: '自定義移動端背景', + board: '邊框', text: '文字', board_background: '背景', diff --git a/frontend/src/lang/zh.js b/frontend/src/lang/zh.js index 508b3f2dc9..b078c35d21 100644 --- a/frontend/src/lang/zh.js +++ b/frontend/src/lang/zh.js @@ -1865,8 +1865,12 @@ export default { sure_bt: '确定' }, panel: { + + down: '下载', + mobile_style_setting: '样式设置', mobile_style_setting_tips: '自定义移动端背景', + board: '边框', text: '文字', board_background: '背景', diff --git a/frontend/src/utils/index.js b/frontend/src/utils/index.js index 3fbe39e6f6..01dd7eb895 100644 --- a/frontend/src/utils/index.js +++ b/frontend/src/utils/index.js @@ -314,6 +314,16 @@ export const isSameVueObj = (source, target) => { return false } +export const isSameArr = (source, target) => { + if (!source && !target) return true + if (source?.length && target?.length && source.length === target.length) { + const sortSource = source.sort() + const sortTarget = target.sort() + return JSON.stringify(sortSource) === JSON.stringify(sortTarget) + } + return false +} + export const changeFavicon = link => { let $favicon = document.querySelector('link[rel="icon"]') if ($favicon !== null) { diff --git a/frontend/src/views/background/BackgroundItem.vue b/frontend/src/views/background/BackgroundItem.vue index 034b0146d9..27844ebaa0 100644 --- a/frontend/src/views/background/BackgroundItem.vue +++ b/frontend/src/views/background/BackgroundItem.vue @@ -77,7 +77,7 @@ export default { .testcase-template { display: inline-block; - margin: 10px 0px; + margin: 5px 0px; width: 90px; } diff --git a/frontend/src/views/background/index.vue b/frontend/src/views/background/index.vue index 3ccefee1ec..9d119dcf56 100644 --- a/frontend/src/views/background/index.vue +++ b/frontend/src/views/background/index.vue @@ -88,7 +88,7 @@ v-if="curComponent.commonBackground.enable" style="padding-left: 10px" > - + - + @@ -377,7 +376,7 @@ export default { .main-row { padding-left: 10px; - height: 140px; + height: 250px; overflow-y: auto; } diff --git a/frontend/src/views/link/view/index.vue b/frontend/src/views/link/view/index.vue index b71adaf3c5..37bda6356e 100644 --- a/frontend/src/views/link/view/index.vue +++ b/frontend/src/views/link/view/index.vue @@ -5,6 +5,7 @@ :component-data="mainCanvasComponentData" :canvas-style-data="canvasStyleData" :panel-info="panelInfo" + :user-id="user" /> diff --git a/frontend/src/views/panel/filter/FilterDialog.vue b/frontend/src/views/panel/filter/FilterDialog.vue index 23b444b139..800b383913 100644 --- a/frontend/src/views/panel/filter/FilterDialog.vue +++ b/frontend/src/views/panel/filter/FilterDialog.vue @@ -412,10 +412,6 @@ export default { this.myAttrs.fieldId = null this.myAttrs.activeName = null } - - if (this.myAttrs.sort?.sort === 'custom') { - this.myAttrs.sort.list = [] - } this.enableSureButton() }, diff --git a/frontend/src/views/panel/filter/filterMain/FilterControl.vue b/frontend/src/views/panel/filter/filterMain/FilterControl.vue index eee05b35ee..d054c00185 100644 --- a/frontend/src/views/panel/filter/filterMain/FilterControl.vue +++ b/frontend/src/views/panel/filter/filterMain/FilterControl.vue @@ -52,7 +52,7 @@ diff --git a/frontend/src/views/panel/filter/filterMain/FilterSort.vue b/frontend/src/views/panel/filter/filterMain/FilterSort.vue index a628f7375b..ede0f604cd 100644 --- a/frontend/src/views/panel/filter/filterMain/FilterSort.vue +++ b/frontend/src/views/panel/filter/filterMain/FilterSort.vue @@ -95,6 +95,7 @@ import { fieldListWithPermission } from '@/api/dataset/dataset' import FilterCustomSort from './FilterCustomSort' +import { isSameArr } from '@/utils' export default { name: 'FilterSort', components: { FilterCustomSort }, @@ -175,7 +177,7 @@ export default { }, computed: { fieldIds() { - return this.element.options.attrs.fieldId || [] + return this.element.options.attrs.fieldId }, isSortWidget() { return this.widget && this.widget.isSortWidget && this.widget.isSortWidget() @@ -195,8 +197,24 @@ export default { watch: { firstTableId(val, old) { if (val !== old) { + if (this.isSortWidget && (this.sortNode?.sort === 'asc' || this.sortNode?.sort === 'desc')) { + this.sortNode = { sort: 'none' } + this.$emit('sort-change', this.sortNode) + } this.loadFields() } + }, + fieldIds(val, old) { + if (val !== old) { + if (this.isCustomSortWidget && this.sortNode.sort === 'custom') { + const valArr = val?.length ? val.split(',') : null + const oldArr = old?.length ? old.split(',') : null + if (!isSameArr(valArr, oldArr)) { + this.sortNode = { sort: 'none' } + this.$emit('sort-change', this.sortNode) + } + } + } } }, @@ -210,12 +228,12 @@ export default { this.customSortList = JSON.parse(JSON.stringify(this.sortNode.list)) } } - if (!this.sortNode) { - this.sortNode = JSON.parse(JSON.stringify(this.defaultSortProp)) - } this.loadFields() } + if (!this.sortNode) { + this.sortNode = JSON.parse(JSON.stringify(this.defaultSortProp)) + } }, methods: { customSortChange(list) {