diff --git a/README.md b/README.md index e9e02822..bc7cb811 100644 --- a/README.md +++ b/README.md @@ -7,19 +7,19 @@ JEECG BOOT 低代码开发平台(前后端分离版本) =============== -当前最新版本: 3.2.0(发布日期:2022-04-25) +当前最新版本: 3.3.0(发布日期:2022-07-25) [![AUR](https://img.shields.io/badge/license-Apache%20License%202.0-blue.svg)](https://github.com/zhangdaiscott/jeecg-boot/blob/master/LICENSE) [![](https://img.shields.io/badge/Author-北京国炬软件-orange.svg)](http://www.jeecg.com) -[![](https://img.shields.io/badge/Blog-官方博客-blue.svg)](https://jeecg.blog.csdn.net) -[![](https://img.shields.io/badge/version-3.2.0-brightgreen.svg)](https://github.com/zhangdaiscott/jeecg-boot) +[![](https://img.shields.io/badge/Blog-官方博客-blue.svg)](https://my.oschina.net/jeecg) +[![](https://img.shields.io/badge/version-3.3.0-brightgreen.svg)](https://github.com/zhangdaiscott/jeecg-boot) [![GitHub stars](https://img.shields.io/github/stars/zhangdaiscott/jeecg-boot.svg?style=social&label=Stars)](https://github.com/zhangdaiscott/jeecg-boot) [![GitHub forks](https://img.shields.io/github/forks/zhangdaiscott/jeecg-boot.svg?style=social&label=Fork)](https://github.com/zhangdaiscott/jeecg-boot) -项目介绍: +项目介绍 -----------------------------------

Java Low Code Platform for Enterprise web applications

@@ -34,12 +34,21 @@ JeecgBoot 提供了一系列`低代码模块`,实现在线开发`真正的零 `JEECG业务流程:` 采用工作流来实现、扩展出任务接口,供开发编写业务逻辑,表单提供多种解决方案: 表单设计器、online配置表单、编码表单。同时实现了流程与表单的分离设计(松耦合)、并支持任务节点灵活配置,既保证了公司流程的保密性,又减少了开发人员的工作量。 +项目源码 +----------------------------------- +| 仓库 |前端源码Vue3版 | 前端源码Vue2版 | 后端源码 | +|-|-|-|-| +| Github | [jeecgboot-vue3](https://github.com/jeecgboot/jeecgboot-vue3) | [ant-design-vue-jeecg](https://github.com/jeecgboot/jeecg-boot/tree/master/ant-design-vue-jeecg) | [jeecg-boot](https://github.com/jeecgboot/jeecg-boot) | +| 码云 | [jeecgboot-vue3](https://gitee.com/jeecg/jeecgboot-vue3) | [ant-design-vue-jeecg](https://gitee.com/jeecg/jeecg-boot/tree/master/ant-design-vue-jeecg) | [jeecg-boot](https://gitee.com/jeecg/jeecg-boot) | -| 项目名 | 说明 | 传送门 | -|--------------------|------------------------|-------------------------------------------------------------------------------------------------------------------------------------| -| `jeecg-boot` | JAVA后台(支持微服务) | [Github](https://github.com/jeecgboot/jeecg-boot)    [Gitee](https://gitee.com/jeecg/jeecg-boot) | -| `ant-design-vue-jeecg` |Vue2版前端代码(默认与主项目一起) | | -| `jeecgboot-vue3` | Vue3版前端代码 | [Github](https://github.com/jeecgboot/jeecgboot-vue3)    [Gitee](https://gitee.com/jeecg/jeecgboot-vue3) | + +##### 项目说明 + +| 项目名 | 说明 | +|--------------------|------------------------| +| `jeecg-boot` | SpringBoot后台源码(支持微服务) | +| `ant-design-vue-jeecg` |Vue2版前端源码(与主项目一起) | +| `jeecgboot-vue3` | Vue3版前端源码 | 适用项目 @@ -62,10 +71,10 @@ Jeecg-Boot低代码开发平台,可以应用在任何J2EE项目的开发中, - 微服务开发: [单体切换为微服务](http://doc.jeecg.com/2704725) - QQ交流群 : ⑥730954414、VUE3群683903138、⑤860162132(满)、④774126647(满)、③816531124(满)、②769925425(满)、①284271917(满) - > ` 提醒:【QQ群是自助服务群,建议给帮助您解决问题的同学发送指定红包,表示感谢!】 ` + 为什么选择JEECG-BOOT? ----------------------------------- * 1.采用最新主流前后分离框架(Springboot+Mybatis+antd),容易上手; 代码生成器依赖性低,灵活的扩展能力,可快速实现二次开发; @@ -340,16 +349,16 @@ Jeecg-Boot低代码开发平台,可以应用在任何J2EE项目的开发中, │ ├─Online在线表单 - 功能已开放 │ ├─Online代码生成器 - 功能已开放 │ ├─Online在线报表 - 功能已开放 -│ ├─Online在线图表(商业功能) -│ ├─Online图表模板配置(商业功能) -│ ├─Online布局设计(商业功能) +│ ├─Online在线图表(未开源) +│ ├─Online图表模板配置(未开源) +│ ├─Online布局设计(未开源) │ ├─多数据源管理 - 功能已开放 ├─积木报表设计器(低代码) │ ├─打印设计器 │ ├─数据报表设计 │ ├─图形报表设计(支持echart) -│ ├─大屏设计器(商业功能) -│─流程模块功能 (商业功能) +│ ├─大屏设计器(未开源) +│─流程模块功能 (未开源) │ ├─流程设计器 │ ├─表单设计器 ├─大屏设计器 @@ -364,7 +373,7 @@ Jeecg-Boot低代码开发平台,可以应用在任何J2EE项目的开发中, │ └─我的抄送 │ └─流程委派、抄送、跳转 │ └─。。。 -│─OA办公组件 (商业功能) +│─OA办公组件 (未开源) │ ├─更多功能 │ └─。。。 └─其他模块 diff --git a/ant-design-vue-jeecg/README.md b/ant-design-vue-jeecg/README.md index 1a76874e..40dfbc8a 100644 --- a/ant-design-vue-jeecg/README.md +++ b/ant-design-vue-jeecg/README.md @@ -1,7 +1,7 @@ Ant Design Jeecg Vue ==== -当前最新版本: 3.1.0(发布日期:20220301) +当前最新版本: 3.3.0(发布日期:20220725) Overview ---- diff --git a/ant-design-vue-jeecg/package.json b/ant-design-vue-jeecg/package.json index be5423e1..e47e4738 100644 --- a/ant-design-vue-jeecg/package.json +++ b/ant-design-vue-jeecg/package.json @@ -10,8 +10,8 @@ "lint": "vue-cli-service lint" }, "dependencies": { - "ant-design-vue": "^1.7.2", "@jeecg/antd-online-mini": "3.1.0-beta", + "ant-design-vue": "^1.7.2", "@antv/data-set": "^0.11.4", "viser-vue": "^2.4.8", "axios": "^0.18.0", @@ -29,7 +29,7 @@ "vue-ls": "^3.2.0", "vue-router": "^3.0.1", "vuex": "^3.1.0", - "vue-print-nb-jeecg": "^1.0.9", + "vue-print-nb-jeecg": "^1.0.11", "clipboard": "^2.0.4", "vue-photo-preview": "^1.1.3", "vue-splitpane": "^1.0.4", @@ -45,7 +45,8 @@ "vxe-table": "2.9.13", "vxe-table-plugin-antd": "1.8.10", "cron-parser": "^2.10.0", - "qiankun": "^2.5.1" + "qiankun": "^2.5.1", + "xss": "^1.0.13" }, "devDependencies": { "@babel/polyfill": "^7.2.5", diff --git a/ant-design-vue-jeecg/src/api/api.js b/ant-design-vue-jeecg/src/api/api.js index e3d3bb73..d03d7624 100644 --- a/ant-design-vue-jeecg/src/api/api.js +++ b/ant-design-vue-jeecg/src/api/api.js @@ -69,7 +69,6 @@ export const ajaxGetDictItems = (code, params)=>getAction(`/sys/dict/getDictItem function getDictItemsFromCache(dictCode) { if (Vue.ls.get(UI_CACHE_DB_DICT_DATA) && Vue.ls.get(UI_CACHE_DB_DICT_DATA)[dictCode]) { let dictItems = Vue.ls.get(UI_CACHE_DB_DICT_DATA)[dictCode]; - //console.log("-----------getDictItemsFromCache----------dictCode="+dictCode+"---- dictItems=",dictItems) return dictItems; } } @@ -91,6 +90,7 @@ const loadCategoryData = (params)=>getAction("/sys/category/loadAllData",params) const checkRuleByCode = (params) => getAction('/sys/checkRule/checkByCode', params) //加载我的通告信息 const getUserNoticeInfo= (params)=>getAction("/sys/sysAnnouncementSend/getMyAnnouncementSend",params); +//查询图表数据 const getTransitURL = url => `/sys/common/transitRESTful?url=${encodeURIComponent(url)}` // 中转HTTP请求 export const transitRESTful = { @@ -101,8 +101,6 @@ export const transitRESTful = { } export { - // imgView, - // doMian, addRole, editRole, checkRoleCode, diff --git a/ant-design-vue-jeecg/src/api/manage.js b/ant-design-vue-jeecg/src/api/manage.js index 4abe6dc2..45153ed8 100644 --- a/ant-design-vue-jeecg/src/api/manage.js +++ b/ant-design-vue-jeecg/src/api/manage.js @@ -16,7 +16,9 @@ export default api export function postAction(url,parameter) { let sign = signMd5Utils.getSign(url, parameter); //将签名和时间戳,添加在请求接口 Header - let signHeader = {"X-Sign": sign,"X-TIMESTAMP": signMd5Utils.getDateTimeToString()}; + // update-begin--author:taoyan---date:20220421--for: VUEN-410【签名改造】 X-TIMESTAMP牵扯 + let signHeader = {"X-Sign": sign,"X-TIMESTAMP": signMd5Utils.getTimestamp()}; + // update-end--author:taoyan---date:20220421--for: VUEN-410【签名改造】 X-TIMESTAMP牵扯 return axios({ url: url, @@ -30,7 +32,9 @@ export function postAction(url,parameter) { export function httpAction(url,parameter,method) { let sign = signMd5Utils.getSign(url, parameter); //将签名和时间戳,添加在请求接口 Header - let signHeader = {"X-Sign": sign,"X-TIMESTAMP": signMd5Utils.getDateTimeToString()}; + // update-begin--author:taoyan---date:20220421--for: VUEN-410【签名改造】 X-TIMESTAMP牵扯 + let signHeader = {"X-Sign": sign,"X-TIMESTAMP": signMd5Utils.getTimestamp()}; + // update-end--author:taoyan---date:20220421--for: VUEN-410【签名改造】 X-TIMESTAMP牵扯 return axios({ url: url, @@ -53,7 +57,9 @@ export function putAction(url,parameter) { export function getAction(url,parameter) { let sign = signMd5Utils.getSign(url, parameter); //将签名和时间戳,添加在请求接口 Header - let signHeader = {"X-Sign": sign,"X-TIMESTAMP": signMd5Utils.getDateTimeToString()}; + // update-begin--author:taoyan---date:20220421--for: VUEN-410【签名改造】 X-TIMESTAMP牵扯 + let signHeader = {"X-Sign": sign,"X-TIMESTAMP": signMd5Utils.getTimestamp()}; + // update-end--author:taoyan---date:20220421--for: VUEN-410【签名改造】 X-TIMESTAMP牵扯 return axios({ url: url, @@ -120,13 +126,23 @@ export function saveService(parameter) { * @param parameter * @returns {*} */ -export function downFile(url,parameter){ - return axios({ - url: url, - params: parameter, - method:'get' , - responseType: 'blob' - }) +export function downFile(url,parameter, method='get'){ + if(method=='get'){ + return axios({ + url: url, + params: parameter, + method: method , + responseType: 'blob' + }) + }else{ + return axios({ + url: url, + method: method, + data: parameter, + responseType: 'blob' + }) + } + } /** diff --git a/ant-design-vue-jeecg/src/components/jeecg/JEditableTable.vue b/ant-design-vue-jeecg/src/components/jeecg/JEditableTable.vue index 1f04b2cb..cb378f35 100644 --- a/ant-design-vue-jeecg/src/components/jeecg/JEditableTable.vue +++ b/ant-design-vue-jeecg/src/components/jeecg/JEditableTable.vue @@ -387,7 +387,7 @@  下载 - +  删除 @@ -475,7 +475,7 @@  下载 - +  删除 @@ -532,7 +532,7 @@  下载 - +  删除 @@ -1865,6 +1865,8 @@ }) // 强制更新formValues this.forceUpdateFormValues() + // 【issues/3828】重新计算统计列 + this.recalcAllStatisticsColumns() }, /** * 设置单个组件的值 @@ -2590,8 +2592,9 @@ return id; }, - handleClickDelFile(id) { + handleClickDelFile(id, row, col) { this.uploadValues[id] = null + this.elemValueChange(col.type, row, col, null); }, handleClickDownloadFile(id) { let { path } = this.uploadValues[id] || {} @@ -3074,7 +3077,11 @@ return false } return true; - } + }, + // 根据id获取dataSource中的一行数据 + getOriginData(id){ + return this.dataSource.filter(item=>item.id == id); + }, }, beforeDestroy() { diff --git a/ant-design-vue-jeecg/src/components/jeecg/JEditor.vue b/ant-design-vue-jeecg/src/components/jeecg/JEditor.vue index a5e9d358..91780351 100644 --- a/ant-design-vue-jeecg/src/components/jeecg/JEditor.vue +++ b/ant-design-vue-jeecg/src/components/jeecg/JEditor.vue @@ -68,6 +68,9 @@ branding: false, menubar: false, toolbar_drawer: false, + //update-begin-author:taoyan date:2022-5-6 for: issues/I4BCC3 富文本编辑器在服务器图片上传是相对路径 + convert_urls: false, + //update-end-author:taoyan date:2022-5-6 for: issues/I4BCC3 富文本编辑器在服务器图片上传是相对路径 images_upload_handler: (blobInfo, success) => { let formData = new FormData() formData.append('file', blobInfo.blob(), blobInfo.filename()); diff --git a/ant-design-vue-jeecg/src/components/jeecg/JFormContainer.vue b/ant-design-vue-jeecg/src/components/jeecg/JFormContainer.vue index c941ed3d..0aa2c325 100644 --- a/ant-design-vue-jeecg/src/components/jeecg/JFormContainer.vue +++ b/ant-design-vue-jeecg/src/components/jeecg/JFormContainer.vue @@ -49,7 +49,8 @@ .jeecg-form-container-disabled .ant-upload-select{display:none} .jeecg-form-container-disabled .ant-upload-list{cursor:grabbing} - .jeecg-form-container-disabled fieldset[disabled] .ant-upload-list{ + .jeecg-form-container-disabled fieldset[disabled] .ant-upload-list, + .jeecg-form-container-disabled fieldset[disabled] iframe{ -ms-pointer-events: auto !important; pointer-events: auto !important; } diff --git a/ant-design-vue-jeecg/src/components/jeecg/JModal/JModal.vue b/ant-design-vue-jeecg/src/components/jeecg/JModal/JModal.vue index 1e5bb9f2..e282765e 100644 --- a/ant-design-vue-jeecg/src/components/jeecg/JModal/JModal.vue +++ b/ant-design-vue-jeecg/src/components/jeecg/JModal/JModal.vue @@ -8,7 +8,7 @@ v-on="$listeners" @ok="handleOk" @cancel="handleCancel" - destroyOnClose + :destroyOnClose="destroyOnClose" > @@ -49,13 +49,17 @@ import { getClass, getStyle } from '@/utils/props-util' import { triggerWindowResizeEvent } from '@/utils/util' +import ModalDragMixins from './ModalDragMixins' export default { name: 'JModal', + mixins: [ModalDragMixins], props: { title: String, // 可使用 .sync 修饰符 visible: Boolean, + // 是否开启拖拽 + draggable: Boolean, // 是否全屏弹窗,当全屏时无论如何都会禁止 body 滚动。可使用 .sync 修饰符 fullscreen: { type: Boolean, @@ -71,6 +75,11 @@ export default { type: Boolean, default: true }, + // 关闭时销毁弹窗内容 + destroyOnClose: { + type: Boolean, + default: true + }, }, data() { return { @@ -162,6 +171,16 @@ export default { toggleFullscreen() { this.innerFullscreen = !this.innerFullscreen triggerWindowResizeEvent() + // 全屏的时候禁止拖动 + if (this.innerFullscreen) { + // 还原弹窗的位置为0,0 + this.setModalPosition(0, 0, false) + this.dragSettings.headerEl.style.cursor = null + } else { + // 取消全屏的时候,将弹窗移动到上次记录的位置 + this.resetModalPosition() + this.dragSettings.headerEl.style.cursor = 'move' + } }, } diff --git a/ant-design-vue-jeecg/src/components/jeecg/JModal/ModalDragMixins.js b/ant-design-vue-jeecg/src/components/jeecg/JModal/ModalDragMixins.js new file mode 100644 index 00000000..cfd1c33d --- /dev/null +++ b/ant-design-vue-jeecg/src/components/jeecg/JModal/ModalDragMixins.js @@ -0,0 +1,152 @@ +import {getRefPromise} from '@/utils/util' + +/** JModal 的拖拽混入 */ +export default { + data() { + return { + // 拖动配置 + dragSettings: { + // 上次拖动top记录 + top: null, + // 上次拖动left记录 + left: null, + wrapEl: null, + dragEl: null, + headerEl: null, + }, + } + }, + watch: { + visible() { + if (!this.visible || !this.draggable) { + return + } + this.handleDrag() + }, + draggable() { + if (!this.visible || !this.draggable) { + return + } + this.handleDrag() + }, + }, + methods: { + async handleDrag() { + let modalRef = await getRefPromise(this, 'modal') + const dragWraps = modalRef.$el.querySelectorAll('.ant-modal-wrap') + let wrapEl = dragWraps[0] + if (!wrapEl) return + this.dragSettings.wrapEl = wrapEl + this.dragSettings.dragEl = wrapEl.querySelector('.ant-modal') + this.dragSettings.headerEl = wrapEl.querySelector('.ant-modal-header') + const display = getStyle(wrapEl, 'display') + const draggable = wrapEl.getAttribute('data-drag') + if (display !== 'none') { + // 拖拽位置 + if (draggable === null || this.destroyOnClose) { + this.enableDrag(wrapEl) + } + } + }, + /** 启用拖拽 */ + enableDrag() { + let {wrapEl, dragEl, headerEl} = this.dragSettings + if (!wrapEl) return + wrapEl.setAttribute('data-drag', this.draggable) + if (!headerEl || !dragEl || !this.draggable) return + + // 还原上一次移动的位置 + this.resetModalPosition() + + headerEl.style.cursor = 'move' + headerEl.onmousedown = (e) => { + if (!e) return + // 鼠标按下,计算当前元素距离可视区的距离 + const disX = e.clientX + const disY = e.clientY + const screenWidth = document.body.clientWidth // body当前宽度 + const screenHeight = document.documentElement.clientHeight // 可见区域高度(应为body高度,可某些环境下无法获取) + + const dragElWidth = dragEl.offsetWidth // 对话框宽度 + const dragElHeight = dragEl.offsetHeight // 对话框高度 + + const minDragElLeft = dragEl.offsetLeft + + const maxDragElLeft = screenWidth - dragEl.offsetLeft - dragElWidth + const minDragElTop = dragEl.offsetTop + const maxDragElTop = screenHeight - dragEl.offsetTop - dragElHeight + // 获取到的值带px 正则匹配替换 + const domLeft = getStyle(dragEl, 'left') + const domTop = getStyle(dragEl, 'top') + let styL = +domLeft + let styT = +domTop + + // 注意在ie中 第一次获取到的值为组件自带50% 移动之后赋值为px + if (domLeft.includes('%')) { + styL = +document.body.clientWidth * (+domLeft.replace(/%/g, '') / 100) + styT = +document.body.clientHeight * (+domTop.replace(/%/g, '') / 100) + } else { + styL = +domLeft.replace(/px/g, '') + styT = +domTop.replace(/px/g, '') + } + + document.onmousemove = (e) => { + // 全屏时不触发移动方法 + if (this.innerFullscreen) { + return + } + // 通过事件委托,计算移动的距离 + let left = e.clientX - disX + let top = e.clientY - disY + + // 边界处理 + if (-left > minDragElLeft) { + left = -minDragElLeft + } else if (left > maxDragElLeft) { + left = maxDragElLeft + } + + if (-top > minDragElTop) { + top = -minDragElTop + } else if (top > maxDragElTop) { + top = maxDragElTop + } + + this.setModalPosition(top + styT, left + styL) + } + + document.onmouseup = () => { + document.onmousemove = null + document.onmouseup = null + } + } + }, + + /** + * 移动弹窗位置 + * @param top 顶部位置 + * @param left 左侧位置 + * @param remember 是否记录位置,默认 true + */ + setModalPosition(top, left, remember = true) { + // 记录移动位置 + if (remember) { + this.dragSettings.top = top + this.dragSettings.left = left + } + // 移动当前元素 + this.dragSettings.dragEl.style.cssText += `;left:${left}px;top:${top}px;` + }, + /** + * 将弹窗移动到上次记录的位置 + */ + resetModalPosition() { + this.setModalPosition(this.dragSettings.top, this.dragSettings.left, false) + }, + + }, +} + +function getStyle(dom, attr) { + return getComputedStyle(dom)[attr] +} diff --git a/ant-design-vue-jeecg/src/components/jeecg/JSuperQuery.vue b/ant-design-vue-jeecg/src/components/jeecg/JSuperQuery.vue index 3791abe3..52feb8d2 100644 --- a/ant-design-vue-jeecg/src/components/jeecg/JSuperQuery.vue +++ b/ant-design-vue-jeecg/src/components/jeecg/JSuperQuery.vue @@ -29,6 +29,7 @@ @cancel="handleCancel" :mask="false" :fullscreen="izMobile" + draggable class="j-super-query-modal" style="top:5%;max-height: 95%;" > @@ -163,8 +164,10 @@ - - + + + + @@ -426,10 +429,17 @@ item['dictCode'] = dictCode item['dictTable'] = dictTable item['dictText'] = dictText + //update-begin-author:taoyan for: VUEN-242【online表单 高级查询】开关组件设置扩展参数为[0,1] 时,高级查询选择后查询仍然是Y/N + item['extendOption'] = node.dataRef.extendOption || ['Y', 'N'] + //update-begin-author:taoyan for: VUEN-242【online表单 高级查询】开关组件设置扩展参数为[0,1] 时,高级查询选择后查询仍然是Y/N item['customReturnField'] = customReturnField if (popup) { item['popup'] = popup } + // 格式化字符串,一般用于高级查询的日期格式处理 + if (node.dataRef.formatStr) { + item['formatStr'] = node.dataRef.formatStr + } this.$set(item, 'val', undefined) }, handleOpen() { diff --git a/ant-design-vue-jeecg/src/components/jeecg/JVxeTable/components/JVxeSubPopover.vue b/ant-design-vue-jeecg/src/components/jeecg/JVxeTable/components/JVxeSubPopover.vue index 610de076..4e65df34 100644 --- a/ant-design-vue-jeecg/src/components/jeecg/JVxeTable/components/JVxeSubPopover.vue +++ b/ant-design-vue-jeecg/src/components/jeecg/JVxeTable/components/JVxeSubPopover.vue @@ -71,6 +71,12 @@ let className = target.className || '' className = typeof className === 'string' ? className : className.toString() + // 获取 td 父级 + let td = getParentNodeByTagName(target, 'td'); + // 点击的是拖拽排序列,不做处理 + if (td && td.querySelector('.j-vxe-ds-icons')) { + return + } // 点击的是expand,不做处理 if (className.includes('vxe-table--expand-btn')) { return diff --git a/ant-design-vue-jeecg/src/components/jeecg/JVxeTable/components/JVxeTable.js b/ant-design-vue-jeecg/src/components/jeecg/JVxeTable/components/JVxeTable.js index 3c2ad8df..bf9b1344 100644 --- a/ant-design-vue-jeecg/src/components/jeecg/JVxeTable/components/JVxeTable.js +++ b/ant-design-vue-jeecg/src/components/jeecg/JVxeTable/components/JVxeTable.js @@ -763,6 +763,8 @@ export default { console.warn(`JVxeTable.setValues:必须传递数组`) return } + // 是否更新了数据 + let updated = false values.forEach((item, idx) => { let {rowKey, values: record} = item let {row} = this.getIfRowById(rowKey) @@ -775,6 +777,7 @@ export default { let oldValue = row[colKey] let newValue = record[colKey] if (newValue !== oldValue) { + updated = true this.$set(row, colKey, newValue) // 触发 valueChange 事件 this.trigger('valueChange', { @@ -791,6 +794,14 @@ export default { } }) }) + // 【issues/3828】数据更新后,重新计算统计列 + if (updated && this.statistics.has) { + this.$nextTick(async () => { + let {xTable} = this.$refs.vxe.$refs; + await xTable.updateCache(true); + await xTable.updateData(); + }); + } }, /** 获取所有的数据,包括values、deleteIds */ @@ -1406,7 +1417,7 @@ const fooPatterns = [ {title: '字母', value: 's', pattern: /^[A-Z|a-z]+$/}, {title: '数字', value: 'n', pattern: /^-?\d+(\.?\d+|\d?)$/}, {title: '整数', value: 'z', pattern: /^-?\d+$/}, - {title: '金额', value: 'money', pattern: /^(([1-9][0-9]*)|([0]\.\d{0,2}|[1-9][0-9]*\.\d{0,2}))$/}, + {title: '金额', value: 'money', pattern: /^(([1-9][0-9]*)|([0]\.\d{0,2}|[1-9][0-9]*\.\d{0,5}))$/}, ] /** 旧版handler转为新版Validator */ diff --git a/ant-design-vue-jeecg/src/components/jeecg/JVxeTable/components/cells/JVxeUploadCell.vue b/ant-design-vue-jeecg/src/components/jeecg/JVxeTable/components/cells/JVxeUploadCell.vue index f653aa0a..cce749f4 100644 --- a/ant-design-vue-jeecg/src/components/jeecg/JVxeTable/components/cells/JVxeUploadCell.vue +++ b/ant-design-vue-jeecg/src/components/jeecg/JVxeTable/components/cells/JVxeUploadCell.vue @@ -133,6 +133,10 @@ value['message'] = file.response.message || '未知错误' } this.innerFile = value + // issues/I5FTO6 JVxeTypes.upload 文件上传的时候,触发不了事件 + if (value.path) { + this.handleChangeCommon(fileGetValue(value)); + } }, // handleClickPreviewFile(id) { diff --git a/ant-design-vue-jeecg/src/components/jeecg/JVxeTable/mixins/vxe.web.socket.mixins.js b/ant-design-vue-jeecg/src/components/jeecg/JVxeTable/mixins/vxe.web.socket.mixins.js index 0385e625..3d0ea79e 100644 --- a/ant-design-vue-jeecg/src/components/jeecg/JVxeTable/mixins/vxe.web.socket.mixins.js +++ b/ant-design-vue-jeecg/src/components/jeecg/JVxeTable/mixins/vxe.web.socket.mixins.js @@ -1,5 +1,8 @@ import store from '@/store/' import { randomUUID } from '@/utils/util' +import Vue from 'vue' +import { ACCESS_TOKEN } from '@/store/mutation-types' + // vxe socket const vs = { // 页面唯一 id,用于标识同一用户,不同页面的websocket @@ -52,7 +55,10 @@ const vs = { const domain = window._CONFIG['domianURL'].replace('https://', 'wss://').replace('http://', 'ws://') const url = `${domain}/vxeSocket/${userId}/${this.pageId}` - this.ws = new WebSocket(url) + //update-begin-author:taoyan date:2022-4-22 for: v2.4.6 的 websocket 服务端,存在性能和安全问题。 #3278 + let token = Vue.ls.get(ACCESS_TOKEN) + this.ws = new WebSocket(url, [token]) + //update-end-author:taoyan date:2022-4-22 for: v2.4.6 的 websocket 服务端,存在性能和安全问题。 #3278 this.ws.onopen = this.on.open.bind(this) this.ws.onerror = this.on.error.bind(this) this.ws.onmessage = this.on.message.bind(this) diff --git a/ant-design-vue-jeecg/src/components/layouts/IframePageView.vue b/ant-design-vue-jeecg/src/components/layouts/IframePageView.vue index 1770b07b..e9475445 100644 --- a/ant-design-vue-jeecg/src/components/layouts/IframePageView.vue +++ b/ant-design-vue-jeecg/src/components/layouts/IframePageView.vue @@ -7,12 +7,15 @@ diff --git a/ant-design-vue-jeecg/src/views/modules/message/modules/SysMessageTemplateModal.vue b/ant-design-vue-jeecg/src/views/modules/message/modules/SysMessageTemplateModal.vue index b88fb873..6602065d 100644 --- a/ant-design-vue-jeecg/src/views/modules/message/modules/SysMessageTemplateModal.vue +++ b/ant-design-vue-jeecg/src/views/modules/message/modules/SysMessageTemplateModal.vue @@ -50,6 +50,17 @@ + + + + + + + { if(this.useEditor){ - this.form.setFieldsValue(pick(this.model, 'templateCode', 'templateName', 'templateTestJson', 'templateType')) + this.form.setFieldsValue(pick(this.model, 'useStatus', 'templateCode', 'templateName', 'templateTestJson', 'templateType')) }else{ - this.form.setFieldsValue(pick(this.model, 'templateCode', 'templateContent', 'templateName', 'templateTestJson', 'templateType')) + this.form.setFieldsValue(pick(this.model, 'useStatus', 'templateCode', 'templateContent', 'templateName', 'templateTestJson', 'templateType')) } }); }, diff --git a/ant-design-vue-jeecg/src/views/modules/message/modules/SysMessageTestModal.vue b/ant-design-vue-jeecg/src/views/modules/message/modules/SysMessageTestModal.vue index 78483983..9feb97b3 100644 --- a/ant-design-vue-jeecg/src/views/modules/message/modules/SysMessageTestModal.vue +++ b/ant-design-vue-jeecg/src/views/modules/message/modules/SysMessageTestModal.vue @@ -34,14 +34,15 @@ label="消息类型"> + dictCode="messageType"/> - + @@ -50,9 +51,13 @@ ", Pattern.CASE_INSENSITIVE), + //src='...' + Pattern.compile("src[\r\n]*=[\r\n]*\\\'(.*?)\\\'", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL), + Pattern.compile("src[\r\n]*=[\r\n]*\\\"(.*?)\\\"", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL), + //script tags + Pattern.compile("", Pattern.CASE_INSENSITIVE), + Pattern.compile("", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL), + //eval(...) + Pattern.compile("eval\\((.*?)\\)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL), + //expression(...) + Pattern.compile("e­xpression\\((.*?)\\)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL), + //javascript:... + Pattern.compile("javascript:", Pattern.CASE_INSENSITIVE), + //vbscript:... + Pattern.compile("vbscript:", Pattern.CASE_INSENSITIVE), + //onload(...)=... + Pattern.compile("onload(.*?)=", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL), + }; + + public static String scriptXss(String value) { if (value != null) { value = value.replaceAll(" ", ""); - Pattern scriptPattern = Pattern.compile("", Pattern.CASE_INSENSITIVE); - value = scriptPattern.matcher(value).replaceAll(""); - scriptPattern = Pattern.compile("src[\r\n]*=[\r\n]*\\\'(.*?)\\\'", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL); - value = scriptPattern.matcher(value).replaceAll(""); - scriptPattern = Pattern.compile("src[\r\n]*=[\r\n]*\\\"(.*?)\\\"", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL); - value = scriptPattern.matcher(value).replaceAll(""); - scriptPattern = Pattern.compile("", Pattern.CASE_INSENSITIVE); - value = scriptPattern.matcher(value).replaceAll(""); - scriptPattern = Pattern.compile("", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL); - value = scriptPattern.matcher(value).replaceAll(""); - scriptPattern = Pattern.compile("eval\\((.*?)\\)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL); - value = scriptPattern.matcher(value).replaceAll(""); - scriptPattern = Pattern.compile("e­xpression\\((.*?)\\)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL); - value = scriptPattern.matcher(value).replaceAll(""); - scriptPattern = Pattern.compile("javascript:", Pattern.CASE_INSENSITIVE); - value = scriptPattern.matcher(value).replaceAll(""); - scriptPattern = Pattern.compile("vbscript:", Pattern.CASE_INSENSITIVE); - value = scriptPattern.matcher(value).replaceAll(""); - scriptPattern = Pattern.compile("onload(.*?)=", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL); - value = scriptPattern.matcher(value).replaceAll(""); + for(Pattern scriptPattern: patterns){ + value = scriptPattern.matcher(value).replaceAll(""); + } } return HtmlUtils.htmlEscape(value); } public static void main(String[] args) { - String s = striptXSS("javascript:eval()\\\\."); + String s = scriptXss("javascript:eval()\\\\."); System.err.println("s======>" + s); } } diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/java/org/jeecg/modules/system/util/XssUtils.java b/jeecg-boot/jeecg-boot-module-system/src/main/java/org/jeecg/modules/system/util/XssUtils.java new file mode 100644 index 00000000..1fbb3804 --- /dev/null +++ b/jeecg-boot/jeecg-boot-module-system/src/main/java/org/jeecg/modules/system/util/XssUtils.java @@ -0,0 +1,49 @@ +package org.jeecg.modules.system.util; + +import org.springframework.web.util.HtmlUtils; + +import java.util.regex.Pattern; + +/** + * @Description: 工具类XSSUtils,现在的做法是替换成空字符,CSDN的是进行转义,比如文字开头的"<"转成< + * @author: lsq + * @date: 2021年07月26日 19:13 + */ +public class XssUtils { + + private static Pattern[] patterns = new Pattern[]{ + //Script fragments + Pattern.compile("", Pattern.CASE_INSENSITIVE), + //src='...' + Pattern.compile("src[\r\n]*=[\r\n]*\\\'(.*?)\\\'", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL), + Pattern.compile("src[\r\n]*=[\r\n]*\\\"(.*?)\\\"", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL), + //script tags + Pattern.compile("", Pattern.CASE_INSENSITIVE), + Pattern.compile("", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL), + //eval(...) + Pattern.compile("eval\\((.*?)\\)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL), + //expression(...) + Pattern.compile("e­xpression\\((.*?)\\)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL), + //javascript:... + Pattern.compile("javascript:", Pattern.CASE_INSENSITIVE), + //vbscript:... + Pattern.compile("vbscript:", Pattern.CASE_INSENSITIVE), + //onload(...)=... + Pattern.compile("onload(.*?)=", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL), + }; + + public static String scriptXss(String value) { + if (value != null) { + value = value.replaceAll(" ", ""); + for(Pattern scriptPattern: patterns){ + value = scriptPattern.matcher(value).replaceAll(""); + } + } + return HtmlUtils.htmlEscape(value); + } + + public static void main(String[] args) { + String s = scriptXss("javascript:eval()\\\\."); + System.err.println("s======>" + s); + } +} diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/application-dev.yml b/jeecg-boot/jeecg-boot-module-system/src/main/resources/application-dev.yml index d8057f01..0cb86e26 100644 --- a/jeecg-boot/jeecg-boot-module-system/src/main/resources/application-dev.yml +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/application-dev.yml @@ -185,6 +185,10 @@ jeecg: signatureSecret: dd05f1c54d63749eda95f9fa6d49v442a # 本地:local\Minio:minio\阿里云:alioss uploadType: local + # 前端访问地址 + domainUrl: + pc: http://localhost:3100 + app: http://localhost:8051 path: #文件上传根目录 设置 upload: /opt/upFiles @@ -328,4 +332,4 @@ third-app: client-id: ?? # appSecret client-secret: ?? - agent-id: ?? \ No newline at end of file + agent-id: ?? diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/application-prod.yml b/jeecg-boot/jeecg-boot-module-system/src/main/resources/application-prod.yml index 2db8fb02..773ad147 100644 --- a/jeecg-boot/jeecg-boot-module-system/src/main/resources/application-prod.yml +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/application-prod.yml @@ -39,10 +39,10 @@ spring: quartz: job-store-type: jdbc initialize-schema: embedded - #延迟1秒启动定时任务 - startup-delay: 1s #定时任务启动开关,true-开 false-关 auto-startup: true + #延迟1秒启动定时任务 + startup-delay: 1s #启动时更新己存在的Job overwrite-existing-jobs: true properties: @@ -185,6 +185,10 @@ jeecg: signatureSecret: dd05f1c54d63749eda95f9fa6d49v442a # 本地:local\Minio:minio\阿里云:alioss uploadType: alioss + # 前端访问地址 + domainUrl: + pc: http://localhost:3100 + app: http://localhost:8051 path: #文件上传根目录 设置 upload: /opt/jeecg-boot/upload diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/application-test.yml b/jeecg-boot/jeecg-boot-module-system/src/main/resources/application-test.yml index 671e5592..1371d312 100644 --- a/jeecg-boot/jeecg-boot-module-system/src/main/resources/application-test.yml +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/application-test.yml @@ -185,6 +185,10 @@ jeecg: signatureSecret: dd05f1c54d63749eda95f9fa6d49v442a # 本地:local\Minio:minio\阿里云:alioss uploadType: local + # 前端访问地址 + domainUrl: + pc: http://localhost:3100 + app: http://localhost:8051 path: #文件上传根目录 设置 upload: D://opt//upFiles diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/banner.txt b/jeecg-boot/jeecg-boot-module-system/src/main/resources/banner.txt index 21783e00..14ea5688 100644 --- a/jeecg-boot/jeecg-boot-module-system/src/main/resources/banner.txt +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/banner.txt @@ -9,6 +9,6 @@ ${AnsiColor.BRIGHT_BLUE} ${AnsiColor.BRIGHT_GREEN} -Jeecg Boot Version: 3.2.0 +Jeecg Boot Version: 3.3.0 Spring Boot Version: ${spring-boot.version}${spring-boot.formatted-version} ${AnsiColor.BLACK} diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/common/sql/menu_insert.ftl b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/common/sql/menu_insert.ftl index ac352000..ced8333e 100644 --- a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/common/sql/menu_insert.ftl +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/common/sql/menu_insert.ftl @@ -1,5 +1,27 @@ -- 注意:该页面对应的前台目录为views/${entityPackage}文件夹下 -- 如果你想更改到其他目录,请修改sql中component字段对应的值 +<#assign id = '${.now?string["yyyyMMddhhmmSSsss"]}0'> + INSERT INTO sys_permission(id, parent_id, name, url, component, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_route, is_leaf, keep_alive, hidden, hide_tab, description, status, del_flag, rule_flag, create_by, create_time, update_by, update_time, internal_or_external) -VALUES ('${.now?string["yyyyMMddhhmmSSsss"]}', NULL, '${tableVo.ftlDescription}', '/${entityPackage}/${entityName?uncap_first}List', '${entityPackage}/${entityName}List', NULL, NULL, 0, NULL, '1', 1.00, 0, NULL, 1, 1, 0, 0, 0, NULL, '1', 0, 0, 'admin', '${.now?string["yyyy-MM-dd HH:mm:ss"]}', NULL, NULL, 0); \ No newline at end of file +VALUES ('${id}', NULL, '${tableVo.ftlDescription}', '/${entityPackage}/${entityName?uncap_first}List', '${entityPackage}/${entityName}List', NULL, NULL, 0, NULL, '1', 1.00, 0, NULL, 1, 1, 0, 0, 0, NULL, '1', 0, 0, 'admin', '${.now?string["yyyy-MM-dd HH:mm:ss"]}', NULL, NULL, 0); + +-- 权限控制sql +-- 新增 +INSERT INTO sys_permission(id, parent_id, name, url, component, is_route, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_leaf, keep_alive, hidden, hide_tab, description, create_by, create_time, update_by, update_time, del_flag, rule_flag, status, internal_or_external) +VALUES ('${.now?string["yyyyMMddhhmmSSsss"]}1', '${id}', '添加${tableVo.ftlDescription}', NULL, NULL, 0, NULL, NULL, 2, '${bussiPackage}:${tableName}:add', '1', NULL, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '${.now?string["yyyy-MM-dd HH:mm:ss"]}', NULL, NULL, 0, 0, '1', 0); +-- 编辑 +INSERT INTO sys_permission(id, parent_id, name, url, component, is_route, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_leaf, keep_alive, hidden, hide_tab, description, create_by, create_time, update_by, update_time, del_flag, rule_flag, status, internal_or_external) +VALUES ('${.now?string["yyyyMMddhhmmSSsss"]}2', '${id}', '编辑${tableVo.ftlDescription}', NULL, NULL, 0, NULL, NULL, 2, '${bussiPackage}:${tableName}:edit', '1', NULL, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '${.now?string["yyyy-MM-dd HH:mm:ss"]}', NULL, NULL, 0, 0, '1', 0); +-- 删除 +INSERT INTO sys_permission(id, parent_id, name, url, component, is_route, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_leaf, keep_alive, hidden, hide_tab, description, create_by, create_time, update_by, update_time, del_flag, rule_flag, status, internal_or_external) +VALUES ('${.now?string["yyyyMMddhhmmSSsss"]}3', '${id}', '删除${tableVo.ftlDescription}', NULL, NULL, 0, NULL, NULL, 2, '${bussiPackage}:${tableName}:delete', '1', NULL, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '${.now?string["yyyy-MM-dd HH:mm:ss"]}', NULL, NULL, 0, 0, '1', 0); +-- 批量删除 +INSERT INTO sys_permission(id, parent_id, name, url, component, is_route, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_leaf, keep_alive, hidden, hide_tab, description, create_by, create_time, update_by, update_time, del_flag, rule_flag, status, internal_or_external) +VALUES ('${.now?string["yyyyMMddhhmmSSsss"]}4', '${id}', '批量删除${tableVo.ftlDescription}', NULL, NULL, 0, NULL, NULL, 2, '${bussiPackage}:${tableName}:deleteBatch', '1', NULL, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '${.now?string["yyyy-MM-dd HH:mm:ss"]}', NULL, NULL, 0, 0, '1', 0); +-- 导出excel +INSERT INTO sys_permission(id, parent_id, name, url, component, is_route, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_leaf, keep_alive, hidden, hide_tab, description, create_by, create_time, update_by, update_time, del_flag, rule_flag, status, internal_or_external) +VALUES ('${.now?string["yyyyMMddhhmmSSsss"]}5', '${id}', '导出excel_${tableVo.ftlDescription}', NULL, NULL, 0, NULL, NULL, 2, '${bussiPackage}:${tableName}:exportXls', '1', NULL, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '${.now?string["yyyy-MM-dd HH:mm:ss"]}', NULL, NULL, 0, 0, '1', 0); +-- 导入excel +INSERT INTO sys_permission(id, parent_id, name, url, component, is_route, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_leaf, keep_alive, hidden, hide_tab, description, create_by, create_time, update_by, update_time, del_flag, rule_flag, status, internal_or_external) +VALUES ('${.now?string["yyyyMMddhhmmSSsss"]}6', '${id}', '导入excel_${tableVo.ftlDescription}', NULL, NULL, 0, NULL, NULL, 2, '${bussiPackage}:${tableName}:importExcel', '1', NULL, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '${.now?string["yyyy-MM-dd HH:mm:ss"]}', NULL, NULL, 0, 0, '1', 0); \ No newline at end of file diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/common/validatorRulesTemplate/core.ftl b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/common/validatorRulesTemplate/core.ftl index 2b43ff63..c3a2143d 100644 --- a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/common/validatorRulesTemplate/core.ftl +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/common/validatorRulesTemplate/core.ftl @@ -32,7 +32,7 @@ { pattern: /^1[3456789]\d{9}$/, message: '请输入正确的手机号码!'}, <#-- 邮政编码 --> <#elseif fieldValidType == 'p'> - { pattern: /^[1-9]\d{5}$/, message: '请输入正确的邮政编码!'}, + { pattern: /^[0-9]\d{5}$/, message: '请输入正确的邮政编码!'}, <#-- 字母 --> <#elseif fieldValidType == 's'> { pattern: /^[A-Z|a-z]+$/, message: '请输入字母!'}, diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/common/validatorRulesTemplate/native/vue3CoreNative.ftl b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/common/validatorRulesTemplate/native/vue3CoreNative.ftl index 45b269f6..2c395d5e 100644 --- a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/common/validatorRulesTemplate/native/vue3CoreNative.ftl +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/common/validatorRulesTemplate/native/vue3CoreNative.ftl @@ -28,7 +28,7 @@ { pattern: /^1[3456789]\d{9}$/, message: '请输入正确的手机号码!'}<#rt>, <#-- 邮政编码 --> <#elseif fieldValidType == 'p'> - { pattern: /^[1-9]\d{5}$/, message: '请输入正确的邮政编码!'}<#rt>, + { pattern: /^[0-9]\d{5}$/, message: '请输入正确的邮政编码!'}<#rt>, <#-- 字母 --> <#elseif fieldValidType == 's'> { pattern: /^[A-Z|a-z]+$/, message: '请输入字母!'}<#rt>, diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/controller/${entityName}Controller.javai b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/controller/${entityName}Controller.javai index d7236b2c..d12e75ce 100644 --- a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/controller/${entityName}Controller.javai +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/controller/${entityName}Controller.javai @@ -86,6 +86,7 @@ public class ${entityName}Controller extends JeecgController<${entityName}, I${e */ @AutoLog(value = "${tableVo.ftlDescription}-添加") @ApiOperation(value="${tableVo.ftlDescription}-添加", notes="${tableVo.ftlDescription}-添加") + //@RequiresPermissions("${bussiPackage}:${tableName}:add") @PostMapping(value = "/add") public Result add(@RequestBody ${entityName} ${entityName?uncap_first}) { <#if bpm_flag> @@ -103,6 +104,7 @@ public class ${entityName}Controller extends JeecgController<${entityName}, I${e */ @AutoLog(value = "${tableVo.ftlDescription}-编辑") @ApiOperation(value="${tableVo.ftlDescription}-编辑", notes="${tableVo.ftlDescription}-编辑") + //@RequiresPermissions("${bussiPackage}:${tableName}:edit") @RequestMapping(value = "/edit", method = {RequestMethod.PUT,RequestMethod.POST}) public Result edit(@RequestBody ${entityName} ${entityName?uncap_first}) { ${entityName?uncap_first}Service.updateById(${entityName?uncap_first}); @@ -117,6 +119,7 @@ public class ${entityName}Controller extends JeecgController<${entityName}, I${e */ @AutoLog(value = "${tableVo.ftlDescription}-通过id删除") @ApiOperation(value="${tableVo.ftlDescription}-通过id删除", notes="${tableVo.ftlDescription}-通过id删除") + //@RequiresPermissions("${bussiPackage}:${tableName}:delete") @DeleteMapping(value = "/delete") public Result delete(@RequestParam(name="id",required=true) String id) { ${entityName?uncap_first}Service.removeById(id); @@ -131,6 +134,7 @@ public class ${entityName}Controller extends JeecgController<${entityName}, I${e */ @AutoLog(value = "${tableVo.ftlDescription}-批量删除") @ApiOperation(value="${tableVo.ftlDescription}-批量删除", notes="${tableVo.ftlDescription}-批量删除") + //@RequiresPermissions("${bussiPackage}:${tableName}:deleteBatch") @DeleteMapping(value = "/deleteBatch") public Result deleteBatch(@RequestParam(name="ids",required=true) String ids) { this.${entityName?uncap_first}Service.removeByIds(Arrays.asList(ids.split(","))); @@ -160,6 +164,7 @@ public class ${entityName}Controller extends JeecgController<${entityName}, I${e * @param request * @param ${entityName?uncap_first} */ + //@RequiresPermissions("${bussiPackage}:${tableName}:exportXls") @RequestMapping(value = "/exportXls") public ModelAndView exportXls(HttpServletRequest request, ${entityName} ${entityName?uncap_first}) { return super.exportXls(request, ${entityName?uncap_first}, ${entityName}.class, "${tableVo.ftlDescription}"); @@ -172,6 +177,7 @@ public class ${entityName}Controller extends JeecgController<${entityName}, I${e * @param response * @return */ + //@RequiresPermissions("${tableName}:importExcel") @RequestMapping(value = "/importExcel", method = RequestMethod.POST) public Result importExcel(HttpServletRequest request, HttpServletResponse response) { return super.importExcel(request, response, ${entityName}.class); diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue3/${entityName}List.vuei b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue3/${entityName}List.vuei index 3a85e4bc..32f1e394 100644 --- a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue3/${entityName}List.vuei +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue3/${entityName}List.vuei @@ -77,6 +77,9 @@ import { getAuthCache, setAuthCache } from '/@/utils/auth'; import { DB_DICT_DATA_KEY } from '/@/enums/cacheEnum'; + <#if bpm_flag==true> + import { startProcess } from '/@/api/common/api'; + const checkedKeys = ref>([]); //注册model const [registerModal, {openModal}] = useModal(); @@ -196,19 +199,61 @@ * 下拉操作栏 */ function getDropDownAction(record){ - return [ - { - label: '详情', - onClick: handleDetail.bind(null, record), - }, { - label: '删除', - popConfirm: { - title: '是否确认删除', - confirm: handleDelete.bind(null, record), - } +<#if bpm_flag==true> + let dropDownAction = [ + { + label: '详情', + onClick: handleDetail.bind(null, record), + }, { + label: '删除', + popConfirm: { + title: '是否确认删除', + confirm: handleDelete.bind(null, record), } - ] + } + ]; + if(record.bpmStatus == '1'){ + dropDownAction.push({ + label: '发起流程', + popConfirm: { + title: '确认提交流程吗?', + confirm: handleProcess.bind(null, record), + } + }) + } + return dropDownAction; +<#else> + return [ + { + label: '详情', + onClick: handleDetail.bind(null, record), + }, { + label: '删除', + popConfirm: { + title: '是否确认删除', + confirm: handleDelete.bind(null, record), + } + } + ] + } + + <#if bpm_flag==true> + /** + * 提交流程 + */ + async function handleProcess(record) { + let params = { + flowCode: 'dev_${tableName}_001', + id: record.id, + formUrl: '${entityPackage}/modules/${entityName}Form', + formUrlMobile: '' + } + await startProcess(params); + handleSuccess(); + } + + <#if list_need_category> /** * 初始化字典配置 diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue3/${entityName}__api.tsi b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue3/${entityName}__api.tsi index c579f917..c3a9d5d6 100644 --- a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue3/${entityName}__api.tsi +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue3/${entityName}__api.tsi @@ -1,5 +1,7 @@ import {defHttp} from '/@/utils/http/axios'; -import {Modal} from 'ant-design-vue'; +import { useMessage } from "/@/hooks/web/useMessage"; + +const { createConfirm } = useMessage(); enum Api { list = '/${entityPackage}/${entityName?uncap_first}/list', @@ -39,7 +41,8 @@ export const deleteOne = (params,handleSuccess) => { * @param params */ export const batchDelete = (params, handleSuccess) => { - Modal.confirm({ + createConfirm({ + iconType: 'warning', title: '确认删除', content: '是否删除选中数据', okText: '确认', diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue3/${entityName}__data.tsi b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue3/${entityName}__data.tsi index 70872400..a3352497 100644 --- a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue3/${entityName}__data.tsi +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue3/${entityName}__data.tsi @@ -122,7 +122,8 @@ export const searchFormSchema: FormSchema[] = [ <#elseif po.classType=='datetime'> component: 'DatePicker', componentProps: { - showTime:true + showTime:true, + valueFormat: 'YYYY-MM-DD HH:mm:ss' }, <#elseif po.classType =='time'> component: 'TimePicker', @@ -194,6 +195,15 @@ export const formSchema: FormSchema[] = [ { label: '${po.filedComment}', field: ${autoStringSuffix(po)}, + <#-- update-begin-author:taoyan date:2022-6-24 for: VUEN-1190【代码生成】默认值未生成 --> + <#if po.defaultVal??> + <#if po.fieldDbType=="BigDecimal" || po.fieldDbType=="double" || po.fieldDbType=="int"> + defaultValue: ${po.defaultVal}, + <#else> + defaultValue: "${po.defaultVal}", + + + <#-- update-end-author:taoyan date:2022-6-24 for: VUEN-1190【代码生成】默认值未生成 --> <#if po.classType =='date'> component: 'DatePicker', <#elseif po.classType =='datetime'> @@ -324,7 +334,7 @@ export const formSchema: FormSchema[] = [ { pattern: /^1[3456789]\d{9}$/, message: '请输入正确的手机号码!'}, <#-- 邮政编码 --> <#elseif fieldValidType == 'p'> - { pattern: /^[1-9]\d{5}$/, message: '请输入正确的邮政编码!'}, + { pattern: /^[0-9]\d{5}$/, message: '请输入正确的邮政编码!'}, <#-- 字母 --> <#elseif fieldValidType == 's'> { pattern: /^[A-Z|a-z]+$/, message: '请输入字母!'}, diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue3Native/${entityName}__api.tsi b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue3Native/${entityName}__api.tsi index 75dfbdf1..d51805c8 100644 --- a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue3Native/${entityName}__api.tsi +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue3Native/${entityName}__api.tsi @@ -1,5 +1,7 @@ import { defHttp } from '/@/utils/http/axios'; -import { Modal } from 'ant-design-vue'; +import { useMessage } from "/@/hooks/web/useMessage"; + +const { createConfirm } = useMessage(); enum Api { list = '/${entityPackage}/${entityName?uncap_first}/list', @@ -45,7 +47,8 @@ export const deleteOne = (params,handleSuccess) => { * @param handleSuccess */ export const batchDelete = (params, handleSuccess) => { - Modal.confirm({ + createConfirm({ + iconType: 'warning', title: '确认删除', content: '是否删除选中数据', okText: '确认', diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue3Native/${entityName}__data.tsi b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue3Native/${entityName}__data.tsi index 03a5779f..b5272c92 100644 --- a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue3Native/${entityName}__data.tsi +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue3Native/${entityName}__data.tsi @@ -324,7 +324,7 @@ export const formSchema: FormSchema[] = [ { pattern: /^1[3456789]\d{9}$/, message: '请输入正确的手机号码!'}, <#-- 邮政编码 --> <#elseif fieldValidType == 'p'> - { pattern: /^[1-9]\d{5}$/, message: '请输入正确的邮政编码!'}, + { pattern: /^[0-9]\d{5}$/, message: '请输入正确的邮政编码!'}, <#-- 字母 --> <#elseif fieldValidType == 's'> { pattern: /^[A-Z|a-z]+$/, message: '请输入字母!'}, diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue3Native/components/${entityName}Form.vuei b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue3Native/components/${entityName}Form.vuei index 0a835d24..e66fa64b 100644 --- a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue3Native/components/${entityName}Form.vuei +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue3Native/components/${entityName}Form.vuei @@ -64,6 +64,7 @@ const emit = defineEmits(['register', 'ok']); const formData = reactive>({ <#list columns as po> + id: '', <#if po.isShow == 'Y'> <#if po.fieldDbType=='int' || po.fieldDbType=='double' || po.fieldDbType=='BigDecimal'> ${po.fieldName}: undefined, diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/vue3/${entityName}List.vuei b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/vue3/${entityName}List.vuei index d71792a3..85cb7ff4 100644 --- a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/vue3/${entityName}List.vuei +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/vue3/${entityName}List.vuei @@ -1,5 +1,6 @@ <#assign pidFieldName = ""> <#assign hasChildrenField = ""> +<#assign bpm_flag=false> <#list originalColumns as po> <#if po.fieldDbName == tableVo.extendParams.pidField> <#assign pidFieldName = po.fieldName> @@ -11,6 +12,9 @@ <#assign list_need_pca=false> <#-- 开始循环 --> <#list columns as po> + <#if po.fieldDbName=='bpm_status'> + <#assign bpm_flag=true> + <#if po.classType=='pca'> <#assign list_need_pca=true> @@ -74,6 +78,9 @@ <#if list_need_pca> import { getAreaTextByCode } from '/@/components/Form/src/utils/Area'; + <#if bpm_flag==true> + import { startProcess } from '/@/api/common/api'; + const expandedRowKeys = ref([]); //字典model const [registerModal, {openModal}] = useModal(); @@ -116,6 +123,7 @@ }, actionColumn: { width: 240, + fixed:'right' }, }, exportConfig: { @@ -329,19 +337,61 @@ * 下拉操作栏 */ function getDropDownAction(record){ - return [ - { - label: '详情', - onClick: handleDetail.bind(null, record), - }, { - label: '删除', - popConfirm: { - title: '确定删除吗?', - confirm: handleDelete.bind(null, record), - } - } - ] + <#if bpm_flag==true> + let dropDownAction = [ + { + label: '详情', + onClick: handleDetail.bind(null, record), + }, { + label: '删除', + popConfirm: { + title: '是否确认删除', + confirm: handleDelete.bind(null, record) + } + } + ]; + if(record.bpmStatus == '1'){ + dropDownAction.push({ + label: '发起流程', + popConfirm: { + title: '确认提交流程吗?', + confirm: handleProcess.bind(null, record), + } + }) + } + return dropDownAction; + <#else> + return [ + { + label: '详情', + onClick: handleDetail.bind(null, record), + }, { + label: '删除', + popConfirm: { + title: '确定删除吗?', + confirm: handleDelete.bind(null, record), + } + } + ] + } + + <#if bpm_flag==true> + /** + * 提交流程 + */ + async function handleProcess(record) { + let params = { + flowCode: 'dev_${tableName}_001', + id: record.id, + formUrl: '${entityPackage}/modules/${entityName}Form', + formUrlMobile: '' + } + await startProcess(params); + await reload(); + } + +