diff --git a/pom.xml b/pom.xml index 321e6d62..2465e441 100644 --- a/pom.xml +++ b/pom.xml @@ -18,8 +18,7 @@ UTF-8 1.8 3.1.1 - 5.3.33 - 5.7.12 + 2.5.15 1.2.23 1.21 3.0.0 @@ -31,13 +30,18 @@ 4.1.2 2.3 0.9.1 + + 9.0.96 + 1.2.13 + 5.7.12 + 5.3.39 - + org.springframework spring-framework-bom @@ -46,7 +50,7 @@ import - + org.springframework.security spring-security-bom @@ -59,11 +63,43 @@ org.springframework.boot spring-boot-dependencies - 2.5.15 + ${spring-boot.version} pom import + + + ch.qos.logback + logback-core + ${logback.version} + + + + ch.qos.logback + logback-classic + ${logback.version} + + + + + org.apache.tomcat.embed + tomcat-embed-core + ${tomcat.version} + + + + org.apache.tomcat.embed + tomcat-embed-el + ${tomcat.version} + + + + org.apache.tomcat.embed + tomcat-embed-websocket + ${tomcat.version} + + com.alibaba diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Excel.java b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Excel.java index 0d69d394..cfb5f9c9 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Excel.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Excel.java @@ -83,6 +83,11 @@ public @interface Excel */ public String prompt() default ""; + /** + * 是否允许内容换行 + */ + public boolean wrapText() default false; + /** * 设置只能选择不能输入的列内容. */ diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelUtil.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelUtil.java index 64f97baa..7472849d 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelUtil.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelUtil.java @@ -194,6 +194,11 @@ public class ExcelUtil */ public Class clazz; + /** + * 需要显示列属性 + */ + public String[] includeFields; + /** * 需要排除列属性 */ @@ -204,11 +209,20 @@ public class ExcelUtil this.clazz = clazz; } + /** + * 仅在Excel中显示列属性 + * + * @param fields 列属性名 示例[单个"name"/多个"id","name"] + */ + public void showColumn(String... fields) + { + this.includeFields = fields; + } + /** * 隐藏Excel中列属性 * * @param fields 列属性名 示例[单个"name"/多个"id","name"] - * @throws Exception */ public void hideColumn(String... fields) { @@ -238,8 +252,6 @@ public class ExcelUtil { if (StringUtils.isNotEmpty(title)) { - subMergedFirstRowNum++; - subMergedLastRowNum++; int titleLastCol = this.fields.size() - 1; if (isSubList()) { @@ -250,7 +262,7 @@ public class ExcelUtil Cell titleCell = titleRow.createCell(0); titleCell.setCellStyle(styles.get("title")); titleCell.setCellValue(title); - sheet.addMergedRegion(new CellRangeAddress(titleRow.getRowNum(), titleRow.getRowNum(), titleRow.getRowNum(), titleLastCol)); + sheet.addMergedRegion(new CellRangeAddress(titleRow.getRowNum(), titleRow.getRowNum(), 0, titleLastCol)); } } @@ -261,23 +273,31 @@ public class ExcelUtil { if (isSubList()) { - subMergedFirstRowNum++; - subMergedLastRowNum++; Row subRow = sheet.createRow(rownum); - int excelNum = 0; + int column = 0; + int subFieldSize = subFields != null ? subFields.size() : 0; for (Object[] objects : fields) { + Field field = (Field) objects[0]; Excel attr = (Excel) objects[1]; - Cell headCell1 = subRow.createCell(excelNum); - headCell1.setCellValue(attr.name()); - headCell1.setCellStyle(styles.get(StringUtils.format("header_{}_{}", attr.headerColor(), attr.headerBackgroundColor()))); - excelNum++; - } - int headFirstRow = excelNum - 1; - int headLastRow = headFirstRow + subFields.size() - 1; - if (headLastRow > headFirstRow) - { - sheet.addMergedRegion(new CellRangeAddress(rownum, rownum, headFirstRow, headLastRow)); + if (Collection.class.isAssignableFrom(field.getType())) + { + Cell cell = subRow.createCell(column); + cell.setCellValue(attr.name()); + cell.setCellStyle(styles.get(StringUtils.format("header_{}_{}", attr.headerColor(), attr.headerBackgroundColor()))); + if (subFieldSize > 1) + { + CellRangeAddress cellAddress = new CellRangeAddress(rownum, rownum, column, column + subFieldSize - 1); + sheet.addMergedRegion(cellAddress); + } + column += subFieldSize; + } + else + { + Cell cell = subRow.createCell(column++); + cell.setCellValue(attr.name()); + cell.setCellStyle(styles.get(StringUtils.format("header_{}_{}", attr.headerColor(), attr.headerBackgroundColor()))); + } } rownum++; } @@ -711,64 +731,91 @@ public class ExcelUtil { int startNo = index * sheetSize; int endNo = Math.min(startNo + sheetSize, list.size()); - int rowNo = (1 + rownum) - startNo; + int currentRowNum = rownum + 1; // 从标题行后开始 + for (int i = startNo; i < endNo; i++) { - rowNo = isSubList() ? (i > 1 ? rowNo + 1 : rowNo + i) : i + 1 + rownum - startNo; - row = sheet.createRow(rowNo); - // 得到导出对象. + row = sheet.createRow(currentRowNum); T vo = (T) list.get(i); - Collection> subList = null; - if (isSubList()) - { - if (isSubListValue(vo)) - { - subList = getListCellValue(vo); - subMergedLastRowNum = subMergedLastRowNum + subList.size(); - } - else - { - subMergedFirstRowNum++; - subMergedLastRowNum++; - } - } int column = 0; + int maxSubListSize = getCurrentMaxSubListSize(vo); for (Object[] os : fields) { Field field = (Field) os[0]; Excel excel = (Excel) os[1]; - if (Collection.class.isAssignableFrom(field.getType()) && StringUtils.isNotNull(subList)) + if (Collection.class.isAssignableFrom(field.getType())) { - boolean subFirst = false; - for (Object obj : subList) + try { - if (subFirst) + Collection> subList = (Collection>) getTargetValue(vo, field, excel); + if (subList != null && !subList.isEmpty()) { - rowNo++; - row = sheet.createRow(rowNo); - } - List subFields = FieldUtils.getFieldsListWithAnnotation(obj.getClass(), Excel.class); - int subIndex = 0; - for (Field subField : subFields) - { - if (subField.isAnnotationPresent(Excel.class)) + int subIndex = 0; + for (Object subVo : subList) { - subField.setAccessible(true); - Excel attr = subField.getAnnotation(Excel.class); - this.addCell(attr, row, (T) obj, subField, column + subIndex); + Row subRow = sheet.getRow(currentRowNum + subIndex); + if (subRow == null) + { + subRow = sheet.createRow(currentRowNum + subIndex); + } + + int subColumn = column; + for (Field subField : subFields) + { + Excel subExcel = subField.getAnnotation(Excel.class); + addCell(subExcel, subRow, (T) subVo, subField, subColumn++); + } + subIndex++; } - subIndex++; + column += subFields.size(); } - subFirst = true; } - this.subMergedFirstRowNum = this.subMergedFirstRowNum + subList.size(); + catch (Exception e) + { + log.error("填充集合数据失败", e); + } } else { - this.addCell(excel, row, vo, field, column++); + // 创建单元格并设置值 + addCell(excel, row, vo, field, column); + if (maxSubListSize > 1 && excel.needMerge()) + { + sheet.addMergedRegion(new CellRangeAddress(currentRowNum, currentRowNum + maxSubListSize - 1, column, column)); + } + column++; + } + } + currentRowNum += maxSubListSize; + } + } + + /** + * 获取子列表最大数 + */ + private int getCurrentMaxSubListSize(T vo) + { + int maxSubListSize = 1; + for (Object[] os : fields) + { + Field field = (Field) os[0]; + if (Collection.class.isAssignableFrom(field.getType())) + { + try + { + Collection> subList = (Collection>) getTargetValue(vo, field, (Excel) os[1]); + if (subList != null && !subList.isEmpty()) + { + maxSubListSize = Math.max(maxSubListSize, subList.size()); + } + } + catch (Exception e) + { + log.error("获取集合大小失败", e); } } } + return maxSubListSize; } /** @@ -903,7 +950,7 @@ public class ExcelUtil */ public void annotationDataStyles(Map styles, Field field, Excel excel) { - String key = StringUtils.format("data_{}_{}_{}_{}", excel.align(), excel.color(), excel.backgroundColor(), excel.cellType()); + String key = StringUtils.format("data_{}_{}_{}_{}_{}", excel.align(), excel.color(), excel.backgroundColor(), excel.cellType(), excel.wrapText()); if (!styles.containsKey(key)) { CellStyle style = wb.createCellStyle(); @@ -919,6 +966,7 @@ public class ExcelUtil style.setBottomBorderColor(IndexedColors.GREY_50_PERCENT.getIndex()); style.setFillPattern(FillPatternType.SOLID_FOREGROUND); style.setFillForegroundColor(excel.backgroundColor().getIndex()); + style.setWrapText(excel.wrapText()); Font dataFont = wb.createFont(); dataFont.setFontName("Arial"); dataFont.setFontHeightInPoints((short) 10); @@ -947,7 +995,7 @@ public class ExcelUtil if (isSubList()) { // 填充默认样式,防止合并单元格样式失效 - sheet.setDefaultColumnStyle(column, styles.get(StringUtils.format("data_{}_{}_{}_{}", attr.align(), attr.color(), attr.backgroundColor(), attr.cellType()))); + sheet.setDefaultColumnStyle(column, styles.get(StringUtils.format("data_{}_{}_{}_{}_{}", attr.align(), attr.color(), attr.backgroundColor(), attr.cellType(), attr.wrapText()))); if (attr.needMerge()) { sheet.addMergedRegion(new CellRangeAddress(rownum - 1, rownum, column, column)); @@ -1085,10 +1133,12 @@ public class ExcelUtil cell = row.createCell(column); if (isSubListValue(vo) && getListCellValue(vo).size() > 1 && attr.needMerge()) { - CellRangeAddress cellAddress = new CellRangeAddress(subMergedFirstRowNum, subMergedLastRowNum, column, column); - sheet.addMergedRegion(cellAddress); + if (subMergedLastRowNum >= subMergedFirstRowNum) + { + sheet.addMergedRegion(new CellRangeAddress(subMergedFirstRowNum, subMergedLastRowNum, column, column)); + } } - cell.setCellStyle(styles.get(StringUtils.format("data_{}_{}_{}_{}", attr.align(), attr.color(), attr.backgroundColor(), attr.cellType()))); + cell.setCellStyle(styles.get(StringUtils.format("data_{}_{}_{}_{}_{}", attr.align(), attr.color(), attr.backgroundColor(), attr.cellType(), attr.wrapText()))); // 用于读取对象中的属性 Object value = getTargetValue(vo, field, attr); @@ -1429,6 +1479,7 @@ public class ExcelUtil */ private Object getTargetValue(T vo, Field field, Excel excel) throws Exception { + field.setAccessible(true); Object o = field.get(vo); if (StringUtils.isNotEmpty(excel.targetAttr())) { @@ -1488,46 +1539,83 @@ public class ExcelUtil List tempFields = new ArrayList<>(); tempFields.addAll(Arrays.asList(clazz.getSuperclass().getDeclaredFields())); tempFields.addAll(Arrays.asList(clazz.getDeclaredFields())); - for (Field field : tempFields) + if (StringUtils.isNotEmpty(includeFields)) { - if (!ArrayUtils.contains(this.excludeFields, field.getName())) + for (Field field : tempFields) { - // 单注解 - if (field.isAnnotationPresent(Excel.class)) + if (ArrayUtils.contains(this.includeFields, field.getName()) || field.isAnnotationPresent(Excels.class)) { - Excel attr = field.getAnnotation(Excel.class); - if (attr != null && (attr.type() == Type.ALL || attr.type() == type)) + addField(fields, field); + } + } + } + else if (StringUtils.isNotEmpty(excludeFields)) + { + for (Field field : tempFields) + { + if (!ArrayUtils.contains(this.excludeFields, field.getName())) + { + addField(fields, field); + } + } + } + else + { + for (Field field : tempFields) + { + addField(fields, field); + } + } + return fields; + } + + /** + * 添加字段信息 + */ + public void addField(List fields, Field field) + { + // 单注解 + if (field.isAnnotationPresent(Excel.class)) + { + Excel attr = field.getAnnotation(Excel.class); + if (attr != null && (attr.type() == Type.ALL || attr.type() == type)) + { + fields.add(new Object[] { field, attr }); + } + if (Collection.class.isAssignableFrom(field.getType())) + { + subMethod = getSubMethod(field.getName(), clazz); + ParameterizedType pt = (ParameterizedType) field.getGenericType(); + Class> subClass = (Class>) pt.getActualTypeArguments()[0]; + this.subFields = FieldUtils.getFieldsListWithAnnotation(subClass, Excel.class); + } + } + + // 多注解 + if (field.isAnnotationPresent(Excels.class)) + { + Excels attrs = field.getAnnotation(Excels.class); + Excel[] excels = attrs.value(); + for (Excel attr : excels) + { + if (StringUtils.isNotEmpty(includeFields)) + { + if (ArrayUtils.contains(this.includeFields, field.getName() + "." + attr.targetAttr()) + && (attr != null && (attr.type() == Type.ALL || attr.type() == type))) { - field.setAccessible(true); fields.add(new Object[] { field, attr }); } - if (Collection.class.isAssignableFrom(field.getType())) - { - subMethod = getSubMethod(field.getName(), clazz); - ParameterizedType pt = (ParameterizedType) field.getGenericType(); - Class> subClass = (Class>) pt.getActualTypeArguments()[0]; - this.subFields = FieldUtils.getFieldsListWithAnnotation(subClass, Excel.class); - } } - - // 多注解 - if (field.isAnnotationPresent(Excels.class)) + else { - Excels attrs = field.getAnnotation(Excels.class); - Excel[] excels = attrs.value(); - for (Excel attr : excels) + if (!ArrayUtils.contains(this.excludeFields, field.getName() + "." + attr.targetAttr()) + && (attr != null && (attr.type() == Type.ALL || attr.type() == type))) { - if (!ArrayUtils.contains(this.excludeFields, field.getName() + "." + attr.targetAttr()) - && (attr != null && (attr.type() == Type.ALL || attr.type() == type))) - { - field.setAccessible(true); - fields.add(new Object[] { field, attr }); - } + fields.add(new Object[] { field, attr }); } } } } - return fields; } /** diff --git a/ruoyi-ui/.env.staging b/ruoyi-ui/.env.staging index a47af9a2..730af342 100644 --- a/ruoyi-ui/.env.staging +++ b/ruoyi-ui/.env.staging @@ -1,6 +1,8 @@ # 页面标题 VUE_APP_TITLE = 若依管理系统 +BABEL_ENV = production + NODE_ENV = production # 测试环境配置 diff --git a/ruoyi-ui/package.json b/ruoyi-ui/package.json index 81904c39..02d41880 100644 --- a/ruoyi-ui/package.json +++ b/ruoyi-ui/package.json @@ -52,6 +52,7 @@ "quill": "2.0.2", "screenfull": "5.0.2", "sortablejs": "1.10.2", + "splitpanes": "2.4.1", "vue": "2.6.12", "vue-count-to": "1.0.13", "vue-cropper": "0.5.5", diff --git a/ruoyi-ui/src/assets/styles/ruoyi.scss b/ruoyi-ui/src/assets/styles/ruoyi.scss index 4e298744..7e44513c 100644 --- a/ruoyi-ui/src/assets/styles/ruoyi.scss +++ b/ruoyi-ui/src/assets/styles/ruoyi.scss @@ -118,7 +118,7 @@ /** 表格布局 **/ .pagination-container { position: relative; - height: 25px; + height: 32px; margin-bottom: 10px; margin-top: 15px; padding: 10px 20px !important; @@ -289,3 +289,8 @@ position: relative; float: right; } + +/* 分割面板样式 */ +.splitpanes.default-theme .splitpanes__pane { + background-color: #fff!important; +} diff --git a/ruoyi-ui/src/components/Breadcrumb/index.vue b/ruoyi-ui/src/components/Breadcrumb/index.vue index 1696f547..080595a4 100644 --- a/ruoyi-ui/src/components/Breadcrumb/index.vue +++ b/ruoyi-ui/src/components/Breadcrumb/index.vue @@ -1,7 +1,7 @@ - + {{ item.meta.title }} {{ item.meta.title }} @@ -31,15 +31,45 @@ export default { methods: { getBreadcrumb() { // only show routes with meta.title - let matched = this.$route.matched.filter(item => item.meta && item.meta.title) - const first = matched[0] - - if (!this.isDashboard(first)) { - matched = [{ path: '/index', meta: { title: '首页' }}].concat(matched) + let matched = [] + const router = this.$route + const pathNum = this.findPathNum(router.path) + // multi-level menu + if (pathNum > 2) { + const reg = /\/\w+/gi + const pathList = router.path.match(reg).map((item, index) => { + if (index !== 0) item = item.slice(1) + return item + }) + this.getMatched(pathList, this.$store.getters.defaultRoutes, matched) + } else { + matched = router.matched.filter(item => item.meta && item.meta.title) + } + // 判断是否为首页 + if (!this.isDashboard(matched[0])) { + matched = [{ path: "/index", meta: { title: "首页" } }].concat(matched) } - this.levelList = matched.filter(item => item.meta && item.meta.title && item.meta.breadcrumb !== false) }, + findPathNum(str, char = "/") { + let index = str.indexOf(char) + let num = 0 + while (index !== -1) { + num++ + index = str.indexOf(char, index + 1) + } + return num + }, + getMatched(pathList, routeList, matched) { + let data = routeList.find(item => item.path == pathList[0] || (item.name += '').toLowerCase() == pathList[0]) + if (data) { + matched.push(data) + if (data.children && pathList.length) { + pathList.shift() + this.getMatched(pathList, data.children, matched) + } + } + }, isDashboard(route) { const name = route && route.name if (!name) { @@ -65,7 +95,6 @@ export default { font-size: 14px; line-height: 50px; margin-left: 8px; - .no-redirect { color: #97a8be; cursor: text; diff --git a/ruoyi-ui/src/components/HeaderSearch/index.vue b/ruoyi-ui/src/components/HeaderSearch/index.vue index a01325a5..5dd4ca9e 100644 --- a/ruoyi-ui/src/components/HeaderSearch/index.vue +++ b/ruoyi-ui/src/components/HeaderSearch/index.vue @@ -22,6 +22,7 @@ // make search results more in line with expectations import Fuse from 'fuse.js/dist/fuse.min.js' import path from 'path' +import { isHttp } from '@/utils/validate' export default { name: 'HeaderSearch', @@ -72,7 +73,7 @@ export default { change(val) { const path = val.path; const query = val.query; - if(this.ishttp(val.path)) { + if(isHttp(val.path)) { // http(s):// 路径新窗口打开 const pindex = path.indexOf("http"); window.open(path.substr(pindex, path.length), "_blank"); @@ -115,7 +116,7 @@ export default { if (router.hidden) { continue } const data = { - path: !this.ishttp(router.path) ? path.resolve(basePath, router.path) : router.path, + path: !isHttp(router.path) ? path.resolve(basePath, router.path) : router.path, title: [...prefixTitle] } @@ -149,9 +150,6 @@ export default { } else { this.options = [] } - }, - ishttp(url) { - return url.indexOf('http://') !== -1 || url.indexOf('https://') !== -1 } } } diff --git a/ruoyi-ui/src/components/TopNav/index.vue b/ruoyi-ui/src/components/TopNav/index.vue index 86a91c4c..75e2bb61 100644 --- a/ruoyi-ui/src/components/TopNav/index.vue +++ b/ruoyi-ui/src/components/TopNav/index.vue @@ -14,7 +14,7 @@ - + 更多菜单 import { constantRoutes } from "@/router"; +import { isHttp } from "@/utils/validate"; // 隐藏侧边栏路由 const hideList = ['/index', '/user/profile']; @@ -78,7 +79,7 @@ export default { if(router.path === "/") { router.children[item].path = "/" + router.children[item].path; } else { - if(!this.ishttp(router.children[item].path)) { + if(!isHttp(router.children[item].path)) { router.children[item].path = router.path + "/" + router.children[item].path; } } @@ -126,7 +127,7 @@ export default { handleSelect(key, keyPath) { this.currentIndex = key; const route = this.routers.find(item => item.path === key); - if (this.ishttp(key)) { + if (isHttp(key)) { // http(s):// 路径新窗口打开 window.open(key, "_blank"); } else if (!route || !route.children) { @@ -160,9 +161,6 @@ export default { } else { this.$store.dispatch('app/toggleSideBarHide', true); } - }, - ishttp(url) { - return url.indexOf('http://') !== -1 || url.indexOf('https://') !== -1 } }, }; diff --git a/ruoyi-ui/src/layout/components/AppMain.vue b/ruoyi-ui/src/layout/components/AppMain.vue index a25c5625..66b33bf8 100644 --- a/ruoyi-ui/src/layout/components/AppMain.vue +++ b/ruoyi-ui/src/layout/components/AppMain.vue @@ -22,6 +22,22 @@ export default { key() { return this.$route.path } + }, + watch: { + $route() { + this.addIframe() + } + }, + mounted() { + this.addIframe() + }, + methods: { + addIframe() { + const {name} = this.$route + if (name && this.$route.meta.link) { + this.$store.dispatch('tagsView/addIframeView', this.$route) + } + } } } diff --git a/ruoyi-ui/src/layout/components/Sidebar/SidebarItem.vue b/ruoyi-ui/src/layout/components/Sidebar/SidebarItem.vue index ca3ae183..3a81d29a 100644 --- a/ruoyi-ui/src/layout/components/Sidebar/SidebarItem.vue +++ b/ruoyi-ui/src/layout/components/Sidebar/SidebarItem.vue @@ -62,11 +62,10 @@ export default { const showingChildren = children.filter(item => { if (item.hidden) { return false - } else { - // Temp set(will be used if only has one showing child) - this.onlyOneChild = item - return true } + // Temp set(will be used if only has one showing child) + this.onlyOneChild = item + return true }) // When there is only one child router, the child router is displayed by default diff --git a/ruoyi-ui/src/layout/components/TagsView/index.vue b/ruoyi-ui/src/layout/components/TagsView/index.vue index 1fc23235..44eff7d4 100644 --- a/ruoyi-ui/src/layout/components/TagsView/index.vue +++ b/ruoyi-ui/src/layout/components/TagsView/index.vue @@ -133,11 +133,7 @@ export default { const { name } = this.$route if (name) { this.$store.dispatch('tagsView/addView', this.$route) - if (this.$route.meta.link) { - this.$store.dispatch('tagsView/addIframeView', this.$route) - } } - return false }, moveToCurrentTag() { const tags = this.$refs.tag diff --git a/ruoyi-ui/src/permission.js b/ruoyi-ui/src/permission.js index c5689790..9aad0984 100644 --- a/ruoyi-ui/src/permission.js +++ b/ruoyi-ui/src/permission.js @@ -4,11 +4,16 @@ import { Message } from 'element-ui' import NProgress from 'nprogress' import 'nprogress/nprogress.css' import { getToken } from '@/utils/auth' +import { isPathMatch } from '@/utils/validate' import { isRelogin } from '@/utils/request' NProgress.configure({ showSpinner: false }) -const whiteList = ['/login', '/register'] +const whiteList = ['/login', '/register', '/register*', '/register/*'] + +const isWhiteList = (path) => { + return whiteList.some(pattern => isPathMatch(pattern, path)) +} router.beforeEach((to, from, next) => { NProgress.start() @@ -18,7 +23,7 @@ router.beforeEach((to, from, next) => { if (to.path === '/login') { next({ path: '/' }) NProgress.done() - } else if (whiteList.indexOf(to.path) !== -1) { + } else if (isWhiteList(to.path)) { next() } else { if (store.getters.roles.length === 0) { @@ -43,7 +48,7 @@ router.beforeEach((to, from, next) => { } } else { // 没有token - if (whiteList.indexOf(to.path) !== -1) { + if (isWhiteList(to.path)) { // 在免登录白名单,直接进入 next() } else { diff --git a/ruoyi-ui/src/plugins/cache.js b/ruoyi-ui/src/plugins/cache.js index 6f71b8e5..e912c9a2 100644 --- a/ruoyi-ui/src/plugins/cache.js +++ b/ruoyi-ui/src/plugins/cache.js @@ -26,6 +26,7 @@ const sessionCache = { if (value != null) { return JSON.parse(value) } + return null }, remove (key) { sessionStorage.removeItem(key); @@ -59,6 +60,7 @@ const localCache = { if (value != null) { return JSON.parse(value) } + return null }, remove (key) { localStorage.removeItem(key); diff --git a/ruoyi-ui/src/store/modules/user.js b/ruoyi-ui/src/store/modules/user.js index 01c86833..be565c5f 100644 --- a/ruoyi-ui/src/store/modules/user.js +++ b/ruoyi-ui/src/store/modules/user.js @@ -1,5 +1,7 @@ import { login, logout, getInfo } from '@/api/login' import { getToken, setToken, removeToken } from '@/utils/auth' +import { isHttp, isEmpty } from "@/utils/validate" +import defAva from '@/assets/images/profile.jpg' const user = { state: { @@ -55,7 +57,10 @@ const user = { return new Promise((resolve, reject) => { getInfo().then(res => { const user = res.user - const avatar = (user.avatar == "" || user.avatar == null) ? require("@/assets/images/profile.jpg") : process.env.VUE_APP_BASE_API + user.avatar; + let avatar = user.avatar || "" + if (!isHttp(avatar)) { + avatar = (isEmpty(avatar)) ? defAva : process.env.VUE_APP_BASE_API + avatar + } if (res.roles && res.roles.length > 0) { // 验证返回的roles是否是一个非空数组 commit('SET_ROLES', res.roles) commit('SET_PERMISSIONS', res.permissions) diff --git a/ruoyi-ui/src/utils/validate.js b/ruoyi-ui/src/utils/validate.js index 79864331..13b7a15c 100644 --- a/ruoyi-ui/src/utils/validate.js +++ b/ruoyi-ui/src/utils/validate.js @@ -1,4 +1,38 @@ /** + * 路径匹配器 + * @param {string} pattern + * @param {string} path + * @returns {Boolean} + */ +export function isPathMatch(pattern, path) { + const regexPattern = pattern.replace(/\//g, '\\/').replace(/\*\*/g, '.*').replace(/\*/g, '[^\\/]*') + const regex = new RegExp(`^${regexPattern}$`) + return regex.test(path) +} + +/** + * 判断value字符串是否为空 + * @param {string} value + * @returns {Boolean} + */ +export function isEmpty(value) { + if (value == null || value == "" || value == undefined || value == "undefined") { + return true + } + return false +} + +/** + * 判断url是否是http或https + * @param {string} url + * @returns {Boolean} + */ +export function isHttp(url) { + return url.indexOf('http://') !== -1 || url.indexOf('https://') !== -1 +} + +/** + * 判断path是否为外链 * @param {string} path * @returns {Boolean} */ @@ -65,7 +99,7 @@ export function validEmail(email) { * @returns {Boolean} */ export function isString(str) { - return typeof str === 'string' || str instanceof String; + return typeof str === 'string' || str instanceof String } /** diff --git a/ruoyi-ui/src/views/system/config/index.vue b/ruoyi-ui/src/views/system/config/index.vue index 3ab81fc2..6bde2ee0 100644 --- a/ruoyi-ui/src/views/system/config/index.vue +++ b/ruoyi-ui/src/views/system/config/index.vue @@ -157,7 +157,7 @@ - + diff --git a/ruoyi-ui/src/views/system/role/index.vue b/ruoyi-ui/src/views/system/role/index.vue index cc9e5410..db861e5f 100644 --- a/ruoyi-ui/src/views/system/role/index.vue +++ b/ruoyi-ui/src/views/system/role/index.vue @@ -522,8 +522,8 @@ export default { }) }); }); - this.title = "修改角色"; }); + this.title = "修改角色"; }, /** 选择角色权限范围触发 */ dataScopeSelectChange(value) { @@ -543,8 +543,8 @@ export default { this.$refs.dept.setCheckedKeys(res.checkedKeys); }); }); - this.title = "分配数据权限"; }); + this.title = "分配数据权限"; }, /** 分配用户操作 */ handleAuthUser: function(row) { diff --git a/ruoyi-ui/src/views/system/user/index.vue b/ruoyi-ui/src/views/system/user/index.vue index ff798945..6a0ffcf3 100644 --- a/ruoyi-ui/src/views/system/user/index.vue +++ b/ruoyi-ui/src/views/system/user/index.vue @@ -1,205 +1,97 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - 搜索 - 重置 - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 搜索 + 重置 + + - - - 新增 - - - 修改 - - - 删除 - - - 导入 - - - 导出 - - - + + + 新增 + + + 修改 + + + 删除 + + + 导入 + + + 导出 + + + - - - - - - - - - - - - - - - {{ parseTime(scope.row.createTime) }} - - - - - 修改 - 删除 - handleCommand(command, scope.row)" v-hasPermi="['system:user:resetPwd', 'system:user:edit']"> - 更多 - - 重置密码 - 分配角色 - - - - - + + + + + + + + + + + + + + + {{ parseTime(scope.row.createTime) }} + + + + + 修改 + 删除 + handleCommand(command, scope.row)" v-hasPermi="['system:user:resetPwd', 'system:user:edit']"> + 更多 + + 重置密码 + 分配角色 + + + + + - - + + + + @@ -237,7 +129,7 @@ - + @@ -245,23 +137,14 @@ - + - {{dict.label}} + {{ dict.label }} @@ -270,26 +153,14 @@ - + - + @@ -310,26 +181,15 @@ - + 将文件拖到此处,或点击上传 - 是否更新已经存在的用户数据 + 是否更新已经存在的用户数据 仅允许导入xls、xlsx格式文件。 - 下载模板 + 下载模板