dangsn
2024-06-06 33321f5486fd586fda6fd3f46b7e71754fede28b
调整项目,新增基础模块
已修改3个文件
已添加171个文件
25851 ■■■■■ 文件已修改
Source/plt-web/plt-web-parent/plt-poi/pom.xml 53 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-poi/src/main/java/com/aspose/words/zzZLS.java 231 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-poi/src/main/java/com/vci/starter/poi/annotation/ExcelColumn.java 70 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-poi/src/main/java/com/vci/starter/poi/annotation/ExcelRefer.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-poi/src/main/java/com/vci/starter/poi/annotation/ExcelTitle.java 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-poi/src/main/java/com/vci/starter/poi/bo/AppendDataExcelOption.java 87 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-poi/src/main/java/com/vci/starter/poi/bo/DownloadTempOption.java 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-poi/src/main/java/com/vci/starter/poi/bo/ExcelColumnMap.java 109 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-poi/src/main/java/com/vci/starter/poi/bo/ReadExcelOption.java 100 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-poi/src/main/java/com/vci/starter/poi/bo/SheetDataSet.java 59 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-poi/src/main/java/com/vci/starter/poi/bo/SheetRowData.java 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-poi/src/main/java/com/vci/starter/poi/bo/VciCellStyle.java 86 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-poi/src/main/java/com/vci/starter/poi/bo/VciPoiFont.java 116 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-poi/src/main/java/com/vci/starter/poi/bo/WriteExcelData.java 400 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-poi/src/main/java/com/vci/starter/poi/bo/WriteExcelOption.java 154 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-poi/src/main/java/com/vci/starter/poi/constant/ExcelLangCodeConstant.java 68 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-poi/src/main/java/com/vci/starter/poi/util/ExcelUtil.java 1662 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-poi/src/main/java/com/vci/starter/poi/util/PoiImportProcesser.java 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-poi/src/main/java/com/vci/starter/poi/util/PoiTemplateProcesser.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-poi/src/main/java/com/vci/starter/word/bo/WordMergeListDataSource.java 181 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-poi/src/main/java/com/vci/starter/word/bo/WordMergeStartTableDataBO.java 88 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-poi/src/main/java/com/vci/starter/word/util/WordUtil.java 429 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-starter/pom.xml 56 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/pom.xml 51 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/common/log/VciComponentLogAspect.java 212 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/common/log/autoconfigure/VciAutoLogConfigure.java 48 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/revision/bo/TreeWrapperOptions.java 194 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/revision/model/ReleasedObjDO.java 76 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/revision/model/RevisionInfo.java 221 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/revision/provider/CommonAnnotationProvider.java 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/revision/provider/CommonLifeCycleProvider.java 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/revision/provider/CommonRevisionRuleProvider.java 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/revision/service/RevisionModelUtil.java 1616 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/revision/service/VciRevisionServiceI.java 104 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/undo/bo/UndoTaskBO.java 63 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/undo/query/UndoTaskQuery.java 147 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/undo/vo/UndoTaskVO.java 145 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/annotation/Column.java 101 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/annotation/Id.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/annotation/LifeCycleEvent.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/annotation/SOAService.java 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/annotation/Transient.java 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/annotation/VciBtmType.java 143 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/annotation/VciColumnDefinition.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/annotation/VciEnum.java 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/annotation/VciFieldType.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/annotation/VciLifeCycle.java 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/annotation/VciLifeCycleTranEvent.java 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/annotation/VciLifeCycleTrans.java 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/annotation/VciLinkType.java 57 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/annotation/VciPlatformScan.java 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/annotation/VciRevisionRule.java 62 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/annotation/VciUseEnum.java 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/annotation/VciUseRefer.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/annotation/XmlType.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/annotation/bus/PortalTodoPublishImpl.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/annotation/bus/VciChangeDataAfter.java 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/annotation/bus/VciChangeDataBefore.java 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/annotation/bus/VciChangeDataPlugin.java 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/annotation/bus/VciChangeDocument.java 55 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/annotation/bus/VciLoginAfter.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/annotation/bus/VciLoginBefore.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/annotation/bus/VciLoginPlugin.java 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/annotation/bus/VciLogoutAfter.java 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/annotation/bus/VciLogoutBefore.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/annotation/bus/VciLogoutPlugin.java 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/annotation/bus/VciNoUseBaseResult.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/annotation/bus/VciTaskAfter.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/annotation/bus/VciTaskBefore.java 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/annotation/bus/VciTaskPlugin.java 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/annotation/config/VciConfigField.java 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/annotation/config/VciConfigFieldSelect.java 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/annotation/config/VciConfigModule.java 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/annotation/controller/VciReturnErrorUseFile.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/annotation/controller/VciUnCheckRight.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/annotation/controller/VciUnUseResponseAdvice.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/annotation/log/VciBusinessLog.java 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/annotation/log/VciUnLog.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/annotation/permission/VciPermission.java 137 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/annotation/permission/VciReferPermission.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/annotation/permission/VciUseReferMethod.java 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/annotation/undo/UndoTaskCount.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/annotation/undo/UndoTaskMethod.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/annotation/undo/UndoTaskPlugin.java 68 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/annotation/workflow/WorkflowEvent.java 51 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/annotation/workflow/WorkflowEventField.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/autoconfigure/AppAutoConfigure.java 113 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/autoconfigure/DubboConfig.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/autoconfigure/FeignConfig.java 223 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/autoconfigure/ResponseModifyAdvice.java 149 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/autoconfigure/SpringMVCConfig.java 421 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/autoconfigure/VciAsyncConfig.java 109 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/autoconfigure/VciThreadPoolTaskExecutor.java 113 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/clientutil/BaseClientUtil.java 103 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/clientutil/ClientUtilProcesser.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/constant/CommonReturnCodeConstant.java 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/constant/FileExtensionConstant.java 79 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/constant/FrameWorkLcStatusConstant.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/constant/QueryOptionConstant.java 76 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/constant/RegExpConstant.java 84 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/constant/RevisionConstant.java 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/constant/SpecialCharacterConstant.java 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/constant/TokenKeyConstant.java 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/constant/VciSystemVarConstants.java 152 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/enumpck/BaseEnum.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/enumpck/BaseEnumInt.java 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/enumpck/BooleanEnum.java 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/enumpck/DataBaseEnum.java 148 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/enumpck/DataSecretEnum.java 122 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/enumpck/LangCodeEnum.java 85 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/enumpck/LogLevelEnum.java 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/enumpck/ResultCodeEnum.java 57 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/enumpck/SessionStorageTypeEnum.java 93 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/enumpck/UserSecretEnum.java 119 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/enumpck/VciChangeDocumentTypeEnum.java 120 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/enumpck/VciFieldTypeEnum.java 134 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/enumpck/VciReturnFileTypeEnum.java 100 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/enumpck/VciTaskBusTypeEnum.java 116 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/exception/ExceptionAdviceHandler.java 173 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/exception/VciBaseException.java 160 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/interceptor/VciLocaleInterceptor.java 82 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/interceptor/VciLogAfterInterceptor.java 65 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/interceptor/VciLogBeforeInterceptor.java 75 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/interceptor/VciLogStorageI.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/interceptor/VciNoticePopLoginI.java 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/interceptor/VciSecurityInterceptor.java 198 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/interceptor/VciSessionForLoginI.java 71 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/model/BaseLinkModel.java 255 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/model/BaseModel.java 545 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/pagemodel/BaseLinkModelVO.java 229 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/pagemodel/BaseModelVO.java 502 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/pagemodel/BaseQueryObject.java 239 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/pagemodel/BaseResult.java 393 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/pagemodel/DataGrid.java 177 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/pagemodel/ImportResult.java 163 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/pagemodel/KeyValue.java 68 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/pagemodel/PageHelper.java 416 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/pagemodel/RequestClientInfo.java 131 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/pagemodel/SessionInfo.java 669 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/pagemodel/Tree.java 406 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/pagemodel/TreeGrid.java 86 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/pagemodel/TreeQueryObject.java 203 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/properties/CorsProperties.java 130 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/properties/VciSessionProperties.java 148 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/service/BaseService.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/service/LanguageServiceI.java 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/service/VciSecretServiceI.java 43 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/toolmodel/DateConverter.java 307 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/toolmodel/String2DateConverterForSpringMvc.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/toolmodel/StringEscapeEditor.java 75 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/util/ApplicationContextProvider.java 107 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/util/BeanUtil.java 222 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/util/BeanUtilForVCI.java 258 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/util/BusAnnotationUtil.java 52 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/util/ClassUtil.java 85 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/util/ControllerUtil.java 326 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/util/LangBaseUtil.java 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/util/LocalFileUtil.java 386 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/util/Lunar.java 282 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/util/Md5.java 120 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/util/MessageUtils.java 54 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/util/VciBaseUtil.java 1932 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/util/VciDateUtil.java 1090 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/util/WebThreadLocalUtil.java 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/wrapper/VciParentQueryOption.java 182 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/wrapper/VciQueryWrapperForDO.java 1613 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/wrapper/VciQueryWrapperOption.java 117 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/wrapper/VciReferFieldInfo.java 128 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/yml/YamlPropertySourceFactory.java 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/workflow/dto/WFWorkflowRuntimeDTO.java 94 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/workflow/pagemodel/WFWorkflowTaskHisVO.java 345 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web-base/src/main/resources/application-web.yml 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-web/pom.xml 47 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/pom.xml 192 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-parent/plt-poi/pom.xml
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,53 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.vci</groupId>
        <artifactId>plt-web-parent</artifactId>
        <version>2024.1-SNAPSHOT</version>
    </parent>
    <artifactId>plt-poi</artifactId>
    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <poi.version>4.1.0</poi.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>com.aspose</groupId>
            <artifactId>aspose-words</artifactId>
            <version>18.10.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>com.vci</groupId>
            <artifactId>plt-web-base</artifactId>
        </dependency>
        <dependency><!--需要读取excel-->
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>${poi.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-excelant</artifactId>
            <version>${poi.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml-schemas</artifactId>
            <version>${poi.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>${poi.version}</version>
        </dependency>
    </dependencies>
</project>
Source/plt-web/plt-web-parent/plt-poi/src/main/java/com/aspose/words/zzZLS.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,231 @@
package com.aspose.words;
import com.aspose.words.internal.zz29;
import com.aspose.words.internal.zz2H;
import com.aspose.words.internal.zz2I;
import com.aspose.words.internal.zz6M;
import com.aspose.words.internal.zz97;
import com.aspose.words.internal.zzQB;
import com.aspose.words.internal.zzZ;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.InputStream;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
 * ç ´è§£aspose-word
 * @author weidy
 */
final class zzZLS
{
    private String[] zzYRe;
    private String zzYRd;
    private Date zzYRc;
    private Date zzYRb;
    final void zzY(String var1, Class var2)
            throws Exception
    {
        if (!"".equals(var1)) {
            zz2H var10000;
            File var8;
            if ((var8 = new File(var1)).exists()) {
                var10000 = new zz2H(var8);
            } else {
                String var9 = zz29.zzC(this.getClass());
                if ((var8 = new File(var9, var1)).exists()) {
                    var10000 = new zz2H(var8);
                } else {
                    var9 = zz29.zzC(var2);
                    if (!(var8 = new File(var9, var1)).exists()) {
                        throw new IllegalStateException("Cannot find license '" + var1 + "'.");
                    }
                    var10000 = new zz2H(var8);
                }
            }
            zz2H var3 = var10000;
            try {
                this.zzW(var3);
            } finally {
                var3.close();
            }
        } else {
            zzYR9 = this;
        }
    }
    final void zzW(InputStream paramInputStream)
            throws Exception
    {
        this.zzYRa = 1;zzYR9 = this;
    }
    static int zzZIV()
    {
        return 1;
    }
    static int zzZIU()
    {
        return 1;
    }
    private void zzV(InputStream paramInputStream)
            throws Exception
    {
        byte[] arrayOfByte1 = zzZ.getBytesFromStream(paramInputStream);byte[] arrayOfByte2 = zz6M.zzZ(zz6M.zzBZ(), zz6M.zzUF(1252), arrayOfByte1);
        DocumentBuilderFactory localDocumentBuilderFactory;
        DocumentBuilder localDocumentBuilder;
        Document localDocument;
        Element localElement1;
        Element localElement2 = zzX(localElement1 = (localDocument = (localDocumentBuilder = (localDocumentBuilderFactory = zz97.zzEc()).newDocumentBuilder()).parse(new ByteArrayInputStream(arrayOfByte2))).getDocumentElement(), "Data");Element localElement3 = zzX(localElement1, "Signature");zzZ(localElement2, localElement3);
        Element localElement4;
        NodeList localNodeList = (localElement4 = zzX(localElement2, "Products")).getElementsByTagName("Product");this.zzYRe = new String[localNodeList.getLength()];
        for (int i = 0; i < this.zzYRe.length; i++) {
            this.zzYRe[i] = localNodeList.item(i).getFirstChild().getNodeValue();
        }
        String str = zzZ(localElement2, "EditionType");
        if ((!"Professional".equals(str)) && (!"Enterprise".equals(str))) {
            throw new IllegalStateException("Invalid edition type.");
        }
        this.zzYRd = zzZ(localElement2, "SerialNumber");this.zzYRc = zzY(localElement2, "SubscriptionExpiry");this.zzYRb = zzY(localElement2, "LicenseExpiry");
    }
    private static void zzZ(Node var0, Node var1)
            throws Exception
    {
        byte[] var2;
        if (var0 != null) {
            StringBuilder var3;
            zzZ(var3 = new StringBuilder(), var0);
            var2 = var3.toString().getBytes("UTF-16LE");
        } else {
            var2 = new byte[0];
        }
        byte[] var6;
        if (var1 != null) {
            var6 = zz2I.decode(var1.getFirstChild().getNodeValue());
        } else {
            var6 = new byte[0];
        }
        zzZ(var2, var6, "0nRuwNEddXwLfXB7pw66G71MS93gW8mNzJ7vuh3Sf4VAEOBfpxtHLCotymv1PoeukxYe31K441Ivq0Pkvx1yZZG4O1KCv3Omdbs7uqzUB4xXHlOub4VsTODzDJ5MWHqlRCB1HHcGjlyT2sVGiovLt0Grvqw5+QXBuinoBY0suX0=");
        if (zzYS0.zzZ9e() > 0) {
            zzYS0.clear();
            zzZ(var2, var6, "qKFqqhFovZvEYCHeD3N8Oy+AuxrOA8cVvIl4u4qIBMQlzejGyXkiTUjoryuzlhlS2bG80FGmFsH+wUKbYiEkW/4zseZCV/Ej/usbu6yHACQKO/SCy3pYw68Pcv901pvywUnoaYCI2ccCG29+XM+FwpFQuiPb2H7YbI/++SQs6Hk=");
        }
        if (zzYS0.zzZ9e() > 0) {
            zzYS0.clear();
            zzZ(var2, var6, "3ki45T6C4lt12J5MbKfrADBCZcE8OTefdngc9IDKg+lzCGYLuxJFDt16awhJFnA23sX+kQ4/eZQ5pNAYjc+ZJ0+pWwvQR4h8GJ3eWvecdFs7KSWwNmFXZCSN+sbrxwEjzzns1kIHuLNf5r+Zaggns+8rqXR19RSJBOcuFqVipIHv56lF53Hc+hx+y9URIaadO1W8dkTqgwExyfjnbDOaCBEH0CqUL1YIICS/wIUTEKhM0ZlwEcIcHl8XTHLVx96DMX4bbVajj78L4KzevQc442DX28KGDJTveEB1pSKWsr0d4FTx7wKS36RBnWv5lwsRErtTZb5ciVIG1iIJrp87VQ==");
        }
    }
    private static void zzZ(byte[] paramArrayOfByte1, byte[] paramArrayOfByte2, String paramString)
            throws Exception
    {
        String str;
        byte[] arrayOfByte1 = zz2I.decode(str = "AQAB");
        byte[] arrayOfByte2 = zz2I.decode(str = paramString);
        zzZ3V localzzZ3V;
        (localzzZ3V = new zzZ3V(arrayOfByte2, arrayOfByte1)).zzS(paramArrayOfByte1, paramArrayOfByte2);
    }
    private static synchronized zzQB<String> zzPl(String paramString)
            throws Exception
    {
        InputStream localInputStream;
        if ((localInputStream = License.class.getResourceAsStream("/com/aspose/words/resources/" + paramString + ".Real.xml")) == null) {
            throw new IllegalStateException("Cannot find black listed licenses resource. Please report this error to Aspose.");
        }
        try
        {
            DocumentBuilderFactory localDocumentBuilderFactory;
            DocumentBuilder localDocumentBuilder;
            Document localDocument;
            Element localElement1;
            Element localElement2 = zzX(localElement1 = (localDocument = (localDocumentBuilder = (localDocumentBuilderFactory = zz97.zzEc()).newDocumentBuilder()).parse(localInputStream)).getDocumentElement(), "Data");Element localElement3 = zzX(localElement1, "Signature");zzZ(localElement2, localElement3);zzQB localzzQB1 = new zzQB();
            NodeList localNodeList = localElement2.getElementsByTagName("SN");
            for (int i = 0; i < localNodeList.getLength(); i++) {
                localzzQB1.add(localNodeList.item(i).getFirstChild().getNodeValue());
            }
            return localzzQB1;
        }
        finally
        {
            localInputStream.close();
        }
    }
    private static String zzZ(Element paramElement, String paramString)
    {
        Element localElement;
        if ((localElement = zzX(paramElement, paramString)) != null) {
            return localElement.getFirstChild().getNodeValue();
        }
        return "";
    }
    private static Date zzY(Element paramElement, String paramString)
            throws ParseException
    {
        String str = zzZ(paramElement, paramString);
        if (!"".equals(str)) {
            return new SimpleDateFormat("yyyyMMdd").parse(str);
        }
        return new Date(253402300799999L);
    }
    private static Element zzX(Element paramElement, String paramString)
    {
        NodeList localNodeList;
        if ((localNodeList = paramElement.getElementsByTagName(paramString)).getLength() > 0) {
            return (Element)localNodeList.item(0);
        }
        return null;
    }
    private static void zzZ(StringBuilder paramStringBuilder, Node paramNode)
    {
        if (paramNode.getNodeType() == 1)
        {
            paramStringBuilder.append('<');paramStringBuilder.append(paramNode.getNodeName());paramStringBuilder.append('>');
            NodeList localNodeList1;
            NodeList localNodeList2;
            Node localNode2;
            if ((((localNodeList2 = localNodeList1 = paramNode.getChildNodes()) != null) && (localNodeList2.getLength() == 1) && ((localNode2 = localNodeList2.item(0)) != null) && (localNode2.getNodeType() == 3) ? 1 : 0) != 0)
            {
                Node localNode1;
                String str = (str = (str = (str = (localNode1 = localNodeList1.item(0)).getNodeValue()).replace("&", "&amp;")).replace("<", "&lt;")).replace(">", "&gt;");paramStringBuilder.append(str);
            }
            else
            {
                for (int i = 0; i < localNodeList1.getLength(); i++) {
                    zzZ(paramStringBuilder, localNodeList1.item(i));
                }
            }
            paramStringBuilder.append('<');paramStringBuilder.append('/');
            paramStringBuilder.append(paramNode.getNodeName());paramStringBuilder.append('>');
        }
    }
    private int zzYRa = 0;
    private static zzZLS zzYR9 = null;
    private static zzQB<String> zzYR8;
    private static zzQB<String> zzYR7;
}
Source/plt-web/plt-web-parent/plt-poi/src/main/java/com/vci/starter/poi/annotation/ExcelColumn.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,70 @@
package com.vci.starter.poi.annotation;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
 * excel里的列
 * @author weidy
 * @date 2020/5/9
 */
@Target({ java.lang.annotation.ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ExcelColumn {
    /**
     * å¯¹åº”excel里的列
     * @return excel中的列名
     */
    String value() ;
    /**
     * å€¼æ˜¯å¦å¯ä»¥ä¸ºç©º
     * @return true
     */
    boolean nullable() default true;
    /**
     * æ‰€å±žæžšä¸¾çš„编号
     * @return æžšä¸¾ç¼–号
     */
    String enumId() default "";
    /**
     * æ ¡éªŒçš„æ­£åˆ™è¡¨è¾¾å¼
     * @return æœ‰æ­£åˆ™è¡¨è¾¾å¼çš„æ—¶å€™ï¼Œä¼šç›´æŽ¥æ ¡éªŒæ˜¯å¦æ­£ç¡®
     */
    String regExg() default "";
    /**
     * ä¸æ»¡è¶³æ­£åˆ™è¡¨è¾¾å¼çš„æ—¶å€™çš„æç¤ºå€¼ï¼Œå¯ä»¥æ˜¯å¤šè¯­è¨€ç¼–号
     * @return é»˜è®¤ä¸ºç©º
     */
    String regExgTitle() default "";
    /**
     * å±žæ€§åˆ†ç»„,常用于扩展属性的方式
     * @return åˆ†ç»„信息
     */
    String group() default "";
    /**
     * æ˜¯å¦ä¸ºè¡Œå·çš„列
     * @return true表示会将内容加到行号上
     */
    boolean rowIndexColumn() default false;
    /**
     * åªè¯»-导出的时候使用
     * @return true表示只读
     */
    boolean readOnly() default false;
    /**
     * å•元格宽度,单位是厘米,差不多是html上表格的宽度除以10
     * @return å®½åº¦
     */
    int width() default 0;
}
Source/plt-web/plt-web-parent/plt-poi/src/main/java/com/vci/starter/poi/annotation/ExcelRefer.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,20 @@
package com.vci.starter.poi.annotation;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
 * ä½¿ç”¨å…¶ä»–的对象来获取excel的内容
 * @author weidy
 * @date 2020/6/18
 */
@Target({ java.lang.annotation.ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ExcelRefer {
    /**
     * åŒ…含的关联类,只能是一个,否则无法区分内容
     * @return ç±»
     */
    Class<?> value();
}
Source/plt-web/plt-web-parent/plt-poi/src/main/java/com/vci/starter/poi/annotation/ExcelTitle.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,21 @@
package com.vci.starter.poi.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
 * å¯¼å‡ºåˆ°excel的标题设置
 * @author weidy
 * @date 2020/5/30
 */
@Target({ ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface ExcelTitle {
    /**
     * æ ‡é¢˜æ‰€åœ¨çš„行号
     * @return
     */
    int rowIndexForTitle() default 1;
}
Source/plt-web/plt-web-parent/plt-poi/src/main/java/com/vci/starter/poi/bo/AppendDataExcelOption.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,87 @@
package com.vci.starter.poi.bo;
import java.util.List;
/**
 * è¿½åŠ æ•°æ®åˆ°excel中的配置
 * @author weidy
 * @date 2022/10/15
 */
public class AppendDataExcelOption implements java.io.Serializable{
    /**
     * æ ‡é¢˜æ‰€åœ¨çš„行
     */
    private int titleRowIndex = 0;
    /**
     * å†™å…¥æ•°æ®çš„excel表格
     */
    private String sheetName;
    /**
     * å†™çš„字段
     */
    private List<String> writeFields;
    /**
     * åªè¯»çš„字段
     */
    private List<String> readOnlyFields;
    /**
     * ä»Žå­—段上去找只读属性
     */
    private boolean readOnlyFromField =false;
    public int getTitleRowIndex() {
        return titleRowIndex;
    }
    public void setTitleRowIndex(int titleRowIndex) {
        this.titleRowIndex = titleRowIndex;
    }
    public String getSheetName() {
        return sheetName;
    }
    public void setSheetName(String sheetName) {
        this.sheetName = sheetName;
    }
    public List<String> getWriteFields() {
        return writeFields;
    }
    public void setWriteFields(List<String> writeFields) {
        this.writeFields = writeFields;
    }
    public List<String> getReadOnlyFields() {
        return readOnlyFields;
    }
    public void setReadOnlyFields(List<String> readOnlyFields) {
        this.readOnlyFields = readOnlyFields;
    }
    public boolean isReadOnlyFromField() {
        return readOnlyFromField;
    }
    public void setReadOnlyFromField(boolean readOnlyFromField) {
        this.readOnlyFromField = readOnlyFromField;
    }
    @Override
    public String toString() {
        return "AppendDataExcelOption{" +
                "titleRowIndex=" + titleRowIndex +
                ", sheetName='" + sheetName + '\'' +
                ", writeFields=" + writeFields +
                ", readOnlyFields=" + readOnlyFields +
                ", readOnlyFromField=" + readOnlyFromField +
                '}';
    }
}
Source/plt-web/plt-web-parent/plt-poi/src/main/java/com/vci/starter/poi/bo/DownloadTempOption.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,60 @@
package com.vci.starter.poi.bo;
/**
 * ä¸‹è½½æ¨¡æ¿çš„æ—¶å€™çš„配置
 * @author weidy
 * @date 2022/9/28
 */
public class DownloadTempOption implements java.io.Serializable{
    /**
     * é»˜è®¤1000条的,只有在有下拉的时候才能体现
     */
    private Integer defaultRowSize = 1000;
    /**
     * æ–‡ä»¶çš„名称
     */
    private String excelName;
    /**
     * å·¥ä½œè¡¨çš„名称
     */
    private String sheetName;
    public DownloadTempOption(String excelName){
        this.excelName = excelName;
    }
    public String getExcelName() {
        return excelName;
    }
    public void setExcelName(String excelName) {
        this.excelName = excelName;
    }
    public Integer getDefaultRowSize() {
        return defaultRowSize;
    }
    public void setDefaultRowSize(Integer defaultRowSize) {
        this.defaultRowSize = defaultRowSize;
    }
    public String getSheetName() {
        return sheetName;
    }
    public void setSheetName(String sheetName) {
        this.sheetName = sheetName;
    }
    @Override
    public String toString() {
        return "DownloadTempOption{" +
                "defaultRowSize=" + defaultRowSize +
                '}';
    }
}
Source/plt-web/plt-web-parent/plt-poi/src/main/java/com/vci/starter/poi/bo/ExcelColumnMap.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,109 @@
package com.vci.starter.poi.bo;
/**
 * é’ˆå¯¹map的方式的读取时,内容
 * @author weidy
 * @date 2020/6/18
 */
public class ExcelColumnMap {
    /**
     * æ ‡é¢˜ä¸­æ–‡
     */
    private String title;
    /**
     * è‹±æ–‡åç§°
     */
    private String columnName;
    /**
     * æ˜¯å¦å¯ä»¥ä¸ºç©º
     */
    private  boolean nullable = true;
    /**
     * æ­£åˆ™è¡¨è¾¾å¼
     */
    private String regExg;
    /**
     * ä¸æ»¡è¶³æ­£åˆ™è¡¨è¾¾å¼çš„æ—¶å€™çš„æç¤ºå€¼ï¼Œå¯ä»¥æ˜¯å¤šè¯­è¨€ç¼–号
     * @return é»˜è®¤ä¸ºç©º
     */
    private String regExgTitle;
    /**
     * å±žæ€§åˆ†ç»„
     */
    private String group;
    public ExcelColumnMap(){
    }
    public ExcelColumnMap(String title,String columnName){
        this.title = title;
        this.columnName = columnName;
    }
    public String getTitle() {
        return title;
    }
    public void setTitle(String title) {
        this.title = title;
    }
    public String getColumnName() {
        return columnName;
    }
    public void setColumnName(String columnName) {
        this.columnName = columnName;
    }
    public boolean isNullable() {
        return nullable;
    }
    public void setNullable(boolean nullable) {
        this.nullable = nullable;
    }
    public String getRegExg() {
        return regExg;
    }
    public void setRegExg(String regExg) {
        this.regExg = regExg;
    }
    public String getRegExgTitle() {
        return regExgTitle;
    }
    public void setRegExgTitle(String regExgTitle) {
        this.regExgTitle = regExgTitle;
    }
    public String getGroup() {
        return group;
    }
    public void setGroup(String group) {
        this.group = group;
    }
    @Override
    public String toString() {
        return "ExcelColumnMap{" +
                "title='" + title + '\'' +
                ", columnName='" + columnName + '\'' +
                ", nullable=" + nullable +
                ", regExg='" + regExg + '\'' +
                ", regExgTitle='" + regExgTitle + '\'' +
                ", group='" + group + '\'' +
                '}';
    }
}
Source/plt-web/plt-web-parent/plt-poi/src/main/java/com/vci/starter/poi/bo/ReadExcelOption.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,100 @@
package com.vci.starter.poi.bo;
import java.util.List;
import java.util.Map;
/**
 * è¯»å–excel的选项
 * @author weidy
 * @date 2020/5/9
 */
public class ReadExcelOption {
    /**
     * é¦–行,默认为第二行,因为一般首行都是标题
     */
    private int fristRow = 1;
    /**
     * è¯»å–那个工作表
     */
    private int sheetIndex = 0;
    /**
     * è¯»å–那个名称的工作表
     */
    private String sheetName ;
    /**
     * æ˜¯å¦è¯»å–全部的工作表
     */
    private boolean readAllSheet = false;
    /**
     * æ‰©å±•属性的映射配置,po对象上属性是map的形式时使用,key与excelColumn注解的value()相同,值是对应的标题
     */
    private Map<String, List<ExcelColumnMap>> extendAttrMap ;
    public String getSheetName() {
        return sheetName;
    }
    public void setSheetName(String sheetName) {
        this.sheetName = sheetName;
    }
    public ReadExcelOption(){
    }
    public ReadExcelOption(int fristRow){
        this.fristRow = fristRow;
    }
    public ReadExcelOption(int fristRow,boolean readAllSheet){
        this.fristRow = fristRow;
        this.readAllSheet = readAllSheet;
    }
    public int getFristRow() {
        return fristRow;
    }
    public void setFristRow(int fristRow) {
        this.fristRow = fristRow;
    }
    public int getSheetIndex() {
        return sheetIndex;
    }
    public void setSheetIndex(int sheetIndex) {
        this.sheetIndex = sheetIndex;
    }
    public boolean isReadAllSheet() {
        return readAllSheet;
    }
    public void setReadAllSheet(boolean readAllSheet) {
        this.readAllSheet = readAllSheet;
    }
    public Map<String, List<ExcelColumnMap>> getExtendAttrMap() {
        return extendAttrMap;
    }
    public void setExtendAttrMap(Map<String, List<ExcelColumnMap>> extendAttrMap) {
        this.extendAttrMap = extendAttrMap;
    }
    @Override
    public String toString() {
        return "ReadExcelOption{" +
                "fristRow=" + fristRow +
                ", sheetIndex=" + sheetIndex +
                ", sheetName='" + sheetName + '\'' +
                ", readAllSheet=" + readAllSheet +
                ", extendAttrMap=" + extendAttrMap +
                '}';
    }
}
Source/plt-web/plt-web-parent/plt-poi/src/main/java/com/vci/starter/poi/bo/SheetDataSet.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,59 @@
package com.vci.starter.poi.bo;
import java.util.ArrayList;
import java.util.List;
/**
 * å·¥ä½œè¡¨æ•°æ®çš„集合
 * @author weidy
 */
public class SheetDataSet {
    /**
     * å·¥ä½œè¡¨åç§°
     */
    private String sheetName;
    public String getSheetName() {
        return sheetName;
    }
    public void setSheetName(String sheetName) {
        this.sheetName = sheetName;
    }
    public List<SheetRowData> getRowData() {
        return rowData;
    }
    public void setRowData(List<SheetRowData> rowData) {
        this.rowData = rowData;
    }
    /**
     * åˆ—的名称
     */
    private List<String> colName = new ArrayList<String>();
    public List<String> getColName() {
        return colName;
    }
    public void setColName(List<String> colName) {
        this.colName = colName;
    }
    /**
     * åŒ…含数据
     */
    private List<SheetRowData> rowData = new ArrayList<SheetRowData>();
    @Override
    public String toString() {
        return "SheetDataSet{" +
                "sheetName='" + sheetName + '\'' +
                ", colName=" + colName +
                ", rowData=" + rowData +
                '}';
    }
}
Source/plt-web/plt-web-parent/plt-poi/src/main/java/com/vci/starter/poi/bo/SheetRowData.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,61 @@
package com.vci.starter.poi.bo;
import java.util.HashMap;
import java.util.Map;
/**
 * excel每行的数据
 * @author weidy
 */
public class SheetRowData {
    /**
     * è¡Œå·
     */
    private String rowIndex;
    /**
     * æ•°æ®ï¼Œkey是列号,从0开始,value是具体的值
     */
    private Map<Integer,String> data = new HashMap<Integer,String>();
    /**
     * èŽ·å–è¡Œå·
     * @return è¡Œå·
     */
    public String getRowIndex() {
        return rowIndex;
    }
    /**
     * è®¾ç½®è¡Œå·
     * @param rowIndex è¡Œå·
     */
    public void setRowIndex(String rowIndex) {
        this.rowIndex = rowIndex;
    }
    /**
     * èŽ·å–æ•°æ®å¯¹è±¡
     * @return è¡Œçš„æ•°æ®
     */
    public Map<Integer, String> getData() {
        return data;
    }
    /**
     * è®¾ç½®è¡Œçš„æ•°æ®
     * @param data æ•°æ®,key是列号,从0开始,value是单元格的值
     */
    public void setData(Map<Integer, String> data) {
        this.data = data;
    }
    @Override
    public String toString() {
        return "SheetRowData{" +
                "rowIndex='" + rowIndex + '\'' +
                ", data=" + data +
                '}';
    }
}
Source/plt-web/plt-web-parent/plt-poi/src/main/java/com/vci/starter/poi/bo/VciCellStyle.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,86 @@
package com.vci.starter.poi.bo;
import org.apache.poi.ss.usermodel.*;
/**
 * å•元格的样式,因为Poi里哟使用workbook.createCellStyle,而poi里的CellStyle不能new和setGet
 * @author weidy
 * @date 2022/12/19
 */
public class VciCellStyle implements java.io.Serializable{
    /**
     * æ°´å¹³å¯¹é½
     */
    private HorizontalAlignment alignment;
    /**
     * åž‚直对齐
     */
    private VerticalAlignment verticalAlignment;
    /**
     * æ˜¯å¦è‡ªåŠ¨æ¢è¡Œ
     */
    private Boolean wrapText;
    /**
     * èƒŒæ™¯è‰²
     */
    private IndexedColors fillForegroundColor;
    /**
     * å¡«å……模式
     */
    private FillPatternType fillPattern;
    /**
     * å­—体样式
     */
    private VciPoiFont font;
    /**
     * é¡¶éƒ¨è¾¹æ¡†
     */
    private BorderStyle borderTop;
    /**
     * å³ä¾§è¾¹æ¡†
     */
    private BorderStyle borderRight;
    /**
     * åº•部边框
     */
    private BorderStyle borderBottom;
    /**
     * å·¦è¾¹è¾¹æ¡†
     */
    private BorderStyle borderLeft;
    /**
     * é¡¶éƒ¨è¾¹æ¡†é¢œè‰²
     */
    private IndexedColors topBorderColor;
    /**
     * å³ä¾§è¾¹æ¡†é¢œè‰²
     */
    private IndexedColors rightBorderColor;
    /**
     * åº•部边框颜色
     */
    private IndexedColors bottomBorderColor;
    /**
     * å·¦è¾¹è¾¹æ¡†é¢œè‰²
     */
    private IndexedColors leftBorderColor;
}
Source/plt-web/plt-web-parent/plt-poi/src/main/java/com/vci/starter/poi/bo/VciPoiFont.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,116 @@
package com.vci.starter.poi.bo;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.IndexedColors;
/**
 * poi的字体对象
 * @author weidy
 * @date 2022/12/19
 */
public class VciPoiFont implements java.io.Serializable{
    /**
     * å­—体名称
     */
    private String fontName;
    /**
     * å­—体大小
     */
    private Short fontHeight;
    /**
     * å­—体颜色
     */
    private IndexedColors color;
    /**
     * æ˜¯å¦åŠ ç²—
     */
    private Boolean bold;
    /**
     * æ–œä½“
     */
    private Boolean italic;
    /**
     * ä¸‹åˆ’线,使用Font.U_NONE,Font.U_SINGLE,Font.U_DOUBLE
     */
    private byte underLine = Font.U_NONE;
    /**
     * å­—体上标下标 , Font.SS_NONE, Font.SS_SUPER, Font.SS_SUB
     */
    private byte typeOffset  = Font.SS_NONE;
    /**
     * åˆ é™¤çº¿
     */
    private Boolean strikeout;
    public String getFontName() {
        return fontName;
    }
    public void setFontName(String fontName) {
        this.fontName = fontName;
    }
    public Short getFontHeight() {
        return fontHeight;
    }
    public void setFontHeight(Short fontHeight) {
        this.fontHeight = fontHeight;
    }
    public IndexedColors getColor() {
        return color;
    }
    public void setColor(IndexedColors color) {
        this.color = color;
    }
    public Boolean getBold() {
        return bold;
    }
    public void setBold(Boolean bold) {
        this.bold = bold;
    }
    public Boolean getItalic() {
        return italic;
    }
    public void setItalic(Boolean italic) {
        this.italic = italic;
    }
    public byte getUnderLine() {
        return underLine;
    }
    public void setUnderLine(byte underLine) {
        this.underLine = underLine;
    }
    public byte getTypeOffset() {
        return typeOffset;
    }
    public void setTypeOffset(byte typeOffset) {
        this.typeOffset = typeOffset;
    }
    public Boolean getStrikeout() {
        return strikeout;
    }
    public void setStrikeout(Boolean strikeout) {
        this.strikeout = strikeout;
    }
}
Source/plt-web/plt-web-parent/plt-poi/src/main/java/com/vci/starter/poi/bo/WriteExcelData.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,400 @@
package com.vci.starter.poi.bo;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Font;
import java.util.List;
/**
 * å†™å…¥åˆ°excel里的数据
 * @author weidy
 */
public class WriteExcelData {
    //默认的属性
    /**
     * è¡Œå·ï¼Œä»Ž0开始
     */
    private int row;
    /**
     * åˆ—号,从0开始
     */
    private int col;
    /**
     * è¯»å–或者写入的值对象
     */
    private Object obj;
    //合并和样式
    /**
     * æ˜¯å¦éœ€è¦åˆå¹¶å•元格
     */
    private boolean merged = false;
    /**
     * åˆå¹¶è¡Œçš„目标行号,从0开始
     */
    private int rowTo;
    /**
     * åˆå¹¶åˆ—的目标列号,从0开始
     */
    private int colTo;
    /**
     * æ˜¯å¦æ‹·è´æ ·å¼
     */
    private boolean copyStyle = false;
    /**
     * æ‹·è´æ ·å¼çš„行
     */
    private int copyStyleRow;
    /**
     * æ‹·è´æ ·å¼çš„列
     */
    private int copyStyleCol;
    /**
     * æ˜¯å¦å±…中
     */
    private boolean center;
    //公式
    /**
     * æ˜¯å¦ä¸ºå…¬å¼,公式的值设置到obj属性上
     */
    private boolean formula = false;
    //名称管理器
    /**
     * åç§°ç®¡ç†å™¨ï¼Œçº§è”选择的时候定义,名称为obj属性,范围是row,rowto,col,colto
     */
    private boolean nameRefer = false;
    //数据有效性
    /**
     * æ•°æ®æœ‰æ•ˆæ€§,公式是Obj属性,范围是row,rowto,col,colto
     */
    private boolean validation = false;
    /**
     * æœ‰æ•ˆæ€§åºåˆ—的值
     */
    private List<String> validationDataList;
    /**
     * æœ‰æ•ˆæ€§æ ¡éªŒå¤±è´¥çš„æ—¶å€™çš„æç¤ºä¿¡æ¯ï¼Œå¦‚果设置就表示会显示错误
     */
    private String validationErrorMsg ;
    /**
     * å­—体颜色
     */
    private String fontColor;
    /**
     * æ—¶é—´æ ¼å¼
     */
    private String dateFormat;
    /**
     * åªè¯»
     */
    private boolean readOnly;
    /**
     * å•元格宽度,差不多是html上表格宽度除以10
     */
    private Integer width;
    public String getFontColor() {
        return fontColor;
    }
    public void setFontColor(String fontColor) {
        this.fontColor = fontColor;
    }
    public List<String> getValidationDataList() {
        return validationDataList;
    }
    public void setValidationDataList(List<String> validationDataList) {
        this.validationDataList = validationDataList;
    }
    /**
     * é»˜è®¤çš„æž„造方法
     */
    public WriteExcelData(){
    }
    /**
     * æž„造方法
     * @param row è¡Œ
     * @param col åˆ—
     * @param obj å€¼
     */
    public WriteExcelData(int row, int col, Object obj){
        this.row = row;
        this.col = col;
        this.obj = obj;
    }
    /**
     * å†™å…¬å¼
     * @param row è¡Œå· ä»Ž0 å¼€å§‹
     * @param col åˆ—号从0开始
     * @param foumula å…¬å¼çš„值
     */
    public void writeFormula(int row,int col, String foumula){
        this.row = row;
        this.col = col;
        this.obj = foumula;
        this.formula = true;
    }
    /**
     * å†™åç§°ç®¡ç†å™¨
     * @param row è¡Œå·
     * @param col åˆ—号
     * @param rowTo ç»“束行的行号
     * @param colTo ç»“束列的列号
     * @param name åç§°ç®¡ç†å™¨çš„名称
     */
    public void writeNameRefer(int row,int col, int rowTo,int colTo,String name){
        this.row = row;
        this.col = col;
        this.obj = name;
        this.nameRefer = true;
        this.rowTo = rowTo;
        this.colTo = colTo;
    }
    /**
     * å†™å…¥ä¸‹æ‹‰åˆ—表的值
     * @param comboBoxData ä¸‹æ‹‰èœå•的值
     * @param row  è¡Œå·
     * @param col åˆ—号
     * @param rowTo  ç»“束行号
     * @param colTo ç»“束列号
     */
    public void writeComboBox( List<String> comboBoxData,int row,int col,int rowTo,int colTo){
        writeComboBox(comboBoxData,null,row,col,rowTo,colTo);
    }
    /**
     * å†™å…¥ä¸‹æ‹‰åˆ—表的值
     * @param comboBoxData ä¸‹æ‹‰èœå•的值
     * @param errorMsg é”™è¯¯çš„æç¤ºä¿¡æ¯
     * @param row  è¡Œå·
     * @param col åˆ—号
     * @param rowTo  ç»“束行号
     * @param colTo ç»“束列号
     */
    public void writeComboBox( List<String> comboBoxData,String errorMsg,int row,int col,int rowTo,int colTo){
        this.validationDataList = comboBoxData;
        this.validation= true;
        this.validationErrorMsg = errorMsg;
        this.row = row;
        this.col = col;
        this.rowTo = rowTo;
        this.colTo = colTo;
    }
    /**
     * æœ‰æ•ˆæ€§åºåˆ—引用其他的
     * @param referFormula å¼•用的公式
     * @param row  è¡Œå·
     * @param col åˆ—号
     * @param rowTo  ç»“束行号
     * @param colTo ç»“束列号
     */
    public void writeUseRefer(String referFormula,int row,int col,int rowTo,int colTo){
        writeUseRefer(referFormula,null,row,col,rowTo,colTo);
    }
    /**
     * æœ‰æ•ˆæ€§åºåˆ—引用其他的
     * @param referFormula å¼•用的公式
     * @param errorMsg é”™è¯¯çš„æç¤ºä¿¡æ¯
     * @param row  è¡Œå·
     * @param col åˆ—号
     * @param rowTo  ç»“束行号
     * @param colTo ç»“束列号
     */
    public void writeUseRefer(String referFormula,String errorMsg,int row,int col,int rowTo,int colTo){
        this.validation= true;
        this.obj = referFormula;
        this.validationErrorMsg = errorMsg;
        this.row = row;
        this.col = col;
        this.rowTo = rowTo;
        this.colTo = colTo;
    }
    public boolean isReadOnly() {
        return readOnly;
    }
    public void setReadOnly(boolean readOnly) {
        this.readOnly = readOnly;
    }
    public int getRow() {
        return row;
    }
    public void setRow(int row) {
        this.row = row;
    }
    public int getCol() {
        return col;
    }
    public void setCol(int col) {
        this.col = col;
    }
    public Object getObj() {
        return obj;
    }
    public void setObj(Object obj) {
        this.obj = obj;
    }
    public boolean isMerged() {
        return merged;
    }
    public void setMerged(boolean merged) {
        this.merged = merged;
    }
    public int getRowTo() {
        return rowTo;
    }
    public void setRowTo(int rowTo) {
        this.rowTo = rowTo;
    }
    public int getColTo() {
        return colTo;
    }
    public void setColTo(int colTo) {
        this.colTo = colTo;
    }
    public boolean isCopyStyle() {
        return copyStyle;
    }
    public void setCopyStyle(boolean copyStyle) {
        this.copyStyle = copyStyle;
    }
    public int getCopyStyleRow() {
        return copyStyleRow;
    }
    public void setCopyStyleRow(int copyStyleRow) {
        this.copyStyleRow = copyStyleRow;
    }
    public int getCopyStyleCol() {
        return copyStyleCol;
    }
    public void setCopyStyleCol(int copyStyleCol) {
        this.copyStyleCol = copyStyleCol;
    }
    public boolean isCenter() {
        return center;
    }
    public void setCenter(boolean center) {
        this.center = center;
    }
    public boolean isFormula() {
        return formula;
    }
    public void setFormula(boolean formula) {
        this.formula = formula;
    }
    public boolean isNameRefer() {
        return nameRefer;
    }
    public void setNameRefer(boolean nameRefer) {
        this.nameRefer = nameRefer;
    }
    public boolean isValidation() {
        return validation;
    }
    public void setValidation(boolean validation) {
        this.validation = validation;
    }
    public String getValidationErrorMsg() {
        return validationErrorMsg;
    }
    public void setValidationErrorMsg(String validationErrorMsg) {
        this.validationErrorMsg = validationErrorMsg;
    }
    public String getDateFormat() {
        return dateFormat;
    }
    public void setDateFormat(String dateFormat) {
        this.dateFormat = dateFormat;
    }
    public Integer getWidth() {
        return width;
    }
    public void setWidth(Integer width) {
        this.width = width;
    }
    @Override
    public String toString() {
        return "WriteExcelData{" +
                "row=" + row +
                ", col=" + col +
                ", obj=" + obj +
                ", merged=" + merged +
                ", rowTo=" + rowTo +
                ", colTo=" + colTo +
                ", copyStyle=" + copyStyle +
                ", copyStyleRow=" + copyStyleRow +
                ", copyStyleCol=" + copyStyleCol +
                ", center=" + center +
                ", formula=" + formula +
                ", nameRefer=" + nameRefer +
                ", validation=" + validation +
                ", validationDataList=" + validationDataList +
                ", validationErrorMsg='" + validationErrorMsg + '\'' +
                ", fontColor='" + fontColor + '\'' +
                ", dateFormat='" + dateFormat + '\'' +
                ", readOnly=" + readOnly +
                '}';
    }
}
Source/plt-web/plt-web-parent/plt-poi/src/main/java/com/vci/starter/poi/bo/WriteExcelOption.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,154 @@
package com.vci.starter.poi.bo;
import org.apache.commons.collections4.map.LinkedMap;
import java.util.*;
/**
 * å†™å…¥æ•°æ®åˆ°excel的配置信息
 * @author weidy
 * @date 2020/5/29
 */
public class WriteExcelOption {
    /**
     * è¦å†™å…¥çš„æ•°æ®
     */
    private LinkedMap<String/**工作表的名称**/, LinkedList<WriteExcelData> /**要写入的数据**/> writeDataMap ;
    /**
     * è¦éšè—çš„工作表名称
     */
    private List<String> hideSheetList;
    /**
     * æ˜¯å¦ä¸ºè¿½åŠ çš„å†…å®¹ï¼Œå³å·¥ä½œè¡¨å·²ç»å­˜åœ¨
     */
    private boolean append = false;
    /**
     * æ˜¯å¦07的版本
     */
    private boolean revision07 = false;
    /**
     * æ‰©å±•属性的映射配置,po对象上属性是map的形式时使用,key与excelColumn注解的value()相同,值是对应的标题
     */
    private LinkedMap<String,List<ExcelColumnMap>> extendAttrMap ;
    /**
     * é»˜è®¤æž„造方法
     */
    public WriteExcelOption(){
    }
    /**
     * åŒ…含一个工作表的内容
     * @param excelDataList è¦å†™å…¥çš„工作表内容,工作表的名称默认为Sheet1
     */
    public  WriteExcelOption(List<WriteExcelData> excelDataList){
        writeDataMap = new LinkedMap<>();
        LinkedList newList=new LinkedList();
        newList.addAll(excelDataList);
        writeDataMap.put("Sheet1",newList);
    }
    /**
     * åŒ…含一个工作表的内容
     * @param excelDataList è¦å†™å…¥çš„工作表内容,工作表的名称默认为Sheet1
     */
    public  WriteExcelOption(LinkedList<WriteExcelData> excelDataList){
        writeDataMap = new LinkedMap<>();
        writeDataMap.put("Sheet1",excelDataList);
    }
    /**
     * æ·»åŠ å·¥ä½œè¡¨çš„æ•°æ®å¯¹è±¡
     * @param sheetName å·¥ä½œè¡¨åç§°
     * @param excelDataList å·¥ä½œè¡¨çš„æ•°æ®åˆ—表
     */
    public  void addSheetDataList(String sheetName,LinkedList<WriteExcelData> excelDataList){
        if(writeDataMap == null){
            writeDataMap = new LinkedMap<>();
        }
        writeDataMap.put(sheetName,excelDataList);
    }
    /**
     * æ·»åŠ å·¥ä½œè¡¨çš„æ•°æ®å¯¹è±¡
     * @param sheetName å·¥ä½œè¡¨åç§°
     * @param excelDataList å·¥ä½œè¡¨çš„æ•°æ®åˆ—表
     */
    public  void addSheetDataList(String sheetName,List<WriteExcelData> excelDataList){
        if(writeDataMap == null){
            writeDataMap = new LinkedMap<>();
        }
        LinkedList newList=new LinkedList();
        newList.addAll(excelDataList);
        writeDataMap.put(sheetName,newList);
    }
    /**
     * æ·»åŠ éœ€è¦å½±å“çš„å·¥ä½œè¡¨åç§°
     * @param sheetName å·¥ä½œè¡¨åç§°
     */
    public void  addHideSheet(String sheetName){
        if(hideSheetList == null){
            hideSheetList = new ArrayList<>();
        }
        hideSheetList.add(sheetName);
    }
    public Map<String, LinkedList<WriteExcelData>> getWriteDataMap() {
        return writeDataMap;
    }
    public void setWriteDataMap(LinkedMap<String, LinkedList<WriteExcelData>> writeDataMap) {
        this.writeDataMap = writeDataMap;
    }
    public List<String> getHideSheetList() {
        return hideSheetList;
    }
    public void setHideSheetList(List<String> hideSheetList) {
        this.hideSheetList = hideSheetList;
    }
    public boolean isAppend() {
        return append;
    }
    public void setAppend(boolean append) {
        this.append = append;
    }
    public boolean isRevision07() {
        return revision07;
    }
    public void setRevision07(boolean revision07) {
        this.revision07 = revision07;
    }
    public LinkedMap<String, List<ExcelColumnMap>> getExtendAttrMap() {
        return extendAttrMap;
    }
    public void setExtendAttrMap(LinkedMap<String, List<ExcelColumnMap>> extendAttrMap) {
        this.extendAttrMap = extendAttrMap;
    }
    @Override
    public String toString() {
        return "WriteExcelOption{" +
                "writeDataMap=" + writeDataMap +
                ", hideSheetList=" + hideSheetList +
                ", append=" + append +
                ", revision07=" + revision07 +
                ", extendAttrMap=" + extendAttrMap +
                '}';
    }
}
Source/plt-web/plt-web-parent/plt-poi/src/main/java/com/vci/starter/poi/constant/ExcelLangCodeConstant.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,68 @@
package com.vci.starter.poi.constant;
/**
 * excel相关操作的多语言的代码
 * @author weidy
 * @date 2020/5/5
 */
public class ExcelLangCodeConstant {
    /**
     * è¯»å–导入的文件出错
     */
    public static final String READ_IMPORT_FILE_FAIL = "readImportFileFail";
    /**
     * å¯¼å…¥çš„æ–‡ä»¶å†…容为空
     */
    public static final String IMPORT_CONTENT_NULL = "importContentNull";
    /**
     * æ–‡ä»¶ä¸å­˜åœ¨
     */
    public static final String FILE_NOT_FOUND = "fileNotFound";
    /**
     * æ–‡ä»¶å†™å…¥é”™è¯¯
     */
    public static final String FILE_IO_EXCEPTION = "fileIoException";
    /**
     * æ–‡ä»¶åˆ›å»ºå¼‚常
     */
    public static final String FILE_CREATE_EXCEPTION = "fileCreateException";
    /**
     * è¾“入流是空
     */
    public static final String INPUT_STREAM_IS_NULL = "inputStreamIsNull";
    /**
     * è¾“出流是空
     */
    public static final String OUTPUT_STREAM_IS_NULL = "outputStreamIsNull";
    /**
     * å·¥ä½œç°¿åˆå§‹åŒ–失败
     */
    public static final String WORKBOOK_INIT_FAIL = "workBookInitFail";
    /**
     * å•元格的值不能为空
     */
    public static final String CELL_VALUE_CAN_NOT_NULL = "cellValueCanNotNull";
    /**
     * å› ä¸ºè¦æ ¡éªŒæ­£åˆ™è¡¨è¾¾å¼ï¼Œæ‰€ä»¥å•元格的值不能为空
     */
    public static final String CELL_VALUE_CAN_NOT_NULL_FOR_REG = "cellValueCanNotNullForReg";
    /**
     * å•元格的值不符合正则表达式的要求
     */
    public static final String CELL_VALUE_NOT_EQUAL_REG = "cellValueNotEqualReg";
    /**
     * å•元格不是有效的时间格式
     */
    public static final String CELL_NOT_DATE_FORMATE = "cellNotDateFormate";
}
Source/plt-web/plt-web-parent/plt-poi/src/main/java/com/vci/starter/poi/util/ExcelUtil.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,1662 @@
package com.vci.starter.poi.util;
import com.vci.starter.poi.annotation.ExcelColumn;
import com.vci.starter.poi.annotation.ExcelTitle;
import com.vci.starter.poi.bo.*;
import com.vci.starter.web.annotation.VciFieldType;
import com.vci.starter.web.enumpck.BooleanEnum;
import com.vci.starter.web.enumpck.VciFieldTypeEnum;
import com.vci.starter.web.exception.VciBaseException;
import com.vci.starter.web.util.LangBaseUtil;
import com.vci.starter.web.util.LocalFileUtil;
import com.vci.starter.web.util.VciBaseUtil;
import com.vci.starter.web.util.VciDateUtil;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.CellRangeAddressList;
import org.apache.poi.xssf.usermodel.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.CollectionUtils;
import java.io.*;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.nio.channels.FileChannel;
import java.util.*;
import java.util.stream.Collectors;
import static com.vci.starter.poi.constant.ExcelLangCodeConstant.*;
/**
 * excel操作类
 * 2020/5/8,引入4.1版本的poi,全部的接口发生变化
 * @author weidy
 * @date 2020/2/19
 */
public  class ExcelUtil {
    /**
     * æ—¥å¿—
     */
    private static Logger logger = LoggerFactory.getLogger(ExcelUtil.class);
    /**
     * åœ¨è¯»å–文件的内容的时候,poi会自动判断文件是否为excel,所以不需要单独的方法,另外07还是03也不需要推断
     * æä¾›å†™å…¥åˆ°excel的方法,包括指明单元格和对象的两种方式
     * æä¾›è¯»å–excel的方法,包括返回对象和map数据的两种方式
     */
    /**
     * æ‹·è´æ–‡ä»¶
     *
     * @param source æºæ–‡ä»¶
     * @param target ç›®æ ‡æ–‡ä»¶
     * @throws VciBaseException æ‹·è´æ–‡ä»¶å‡ºçŽ°é”™è¯¯æˆ–è€…æ–‡ä»¶ä¸å­˜åœ¨çš„æ—¶å€™ä¼šæŠ¥é”™
     */
    public static void copyFile(File source, File target) throws VciBaseException {
        VciBaseUtil.alertNotNull(source, "来源文件", target, "目标文件");
        if (!source.exists()) {
            throw new VciBaseException(FILE_NOT_FOUND, new String[]{source.getName()});
        }
        if (!target.exists()) {
            File folder = target.getParentFile();
            folder.mkdirs();
            try {
                target.createNewFile();
            } catch (IOException e) {
                throw new VciBaseException(FILE_IO_EXCEPTION, new String[]{target.getName()});
            }
        }
        FileInputStream is = null;
        FileOutputStream os = null;
        try {
            is = new FileInputStream(source);
        } catch (FileNotFoundException e) {
            throw new VciBaseException(FILE_NOT_FOUND, new String[]{source.getName()});
        }
        try {
            os = new FileOutputStream(target);
        } catch (FileNotFoundException e) {
            IOUtils.closeQuietly(is);
            throw new VciBaseException(FILE_NOT_FOUND, new String[]{target.getName()});
        }
        try {
            copyFile(is, os);
        } catch (VciBaseException e) {
            throw e;
        } catch (Throwable e) {
            throw new VciBaseException(LangBaseUtil.getErrorMsg(e), new String[]{source.getName(), target.getName()}, e);
        } finally {
            //防止因为异常没有关闭
            IOUtils.closeQuietly(is);
            IOUtils.closeQuietly(os);
        }
    }
    /**
     * æ‹·è´æ–‡ä»¶
     *
     * @param in æ–‡ä»¶è¾“入流
     * @param os æ–‡ä»¶è¾“出流
     * @throws VciBaseException æ–‡ä»¶ä¸å­˜åœ¨æˆ–者写入错误的时候会抛出异常
     */
    public static void copyFile(FileInputStream in, FileOutputStream os) throws VciBaseException {
        try {
            FileChannel sourceChannel = in.getChannel();
            FileChannel targetChannel = os.getChannel();
            int i = 0;
            int length = 2097152;
            while (true) {
                if (sourceChannel.position() == sourceChannel.size()) {
                    sourceChannel.close();
                    targetChannel.close();
                    break;
                }
                if ((sourceChannel.size() - sourceChannel.position()) < 20971520) {
                    length = (int) (sourceChannel.size() - sourceChannel.position());
                } else {
                    length = 20971520;
                }
                sourceChannel.transferTo(sourceChannel.position(), length, targetChannel);
                sourceChannel.position(sourceChannel.position() + length);
                i++;
            }
        } catch (IOException e) {
            if (logger.isErrorEnabled()) {
                logger.error("拷贝源文件到目标文件出现了错误", e);
            }
            throw new VciBaseException(LangBaseUtil.getErrorMsg(e), new String[]{}, e);
        } catch (Throwable e) {
            if (logger.isErrorEnabled()) {
                logger.error("拷贝源文件到目标文件出现了错误", e);
            }
            throw new VciBaseException(LangBaseUtil.getErrorMsg(e), new String[]{}, e);
        } finally {
            IOUtils.closeQuietly(in);
            IOUtils.closeQuietly(os);
        }
    }
    /**
     * å°†jar中的文件拷贝到目标文件
     *
     * @param filePathInJar åœ¨jar中的相对路径
     * @param targetFile    ç›®æ ‡æ–‡ä»¶
     * @throws VciBaseException æ‹·è´å‡ºé”™çš„æ—¶å€™ä¼šæŠ›å‡ºå¼‚常
     */
    public static void copyFileFromJar(String filePathInJar, File targetFile) throws VciBaseException {
        VciBaseUtil.alertNotNull(filePathInJar, "来源文件", targetFile, "目标文件");
        if (!targetFile.exists()) {
            File folder = targetFile.getParentFile();
            folder.mkdirs();
            try {
                targetFile.createNewFile();
            } catch (IOException e) {
                throw new VciBaseException(FILE_IO_EXCEPTION, new String[]{targetFile.getName()});
            }
        }
        FileOutputStream os = null;
        InputStream ins = null;
        try {
            os = new FileOutputStream(targetFile);
        } catch (FileNotFoundException e) {
            throw new VciBaseException(FILE_NOT_FOUND, new String[]{targetFile.getName()});
        }
        try {
            ins = ExcelUtil.class.getResourceAsStream(filePathInJar);
            IOUtils.copy(ins, os);
        } catch (IOException e) {
            if (logger.isErrorEnabled()) {
                logger.error("拷贝源文件到目标文件出现了错误", e);
            }
            throw new VciBaseException(LangBaseUtil.getErrorMsg(e), new String[]{}, e);
        } catch (Throwable e) {
            if (logger.isErrorEnabled()) {
                logger.error("拷贝源文件到目标文件出现了错误", e);
            }
            throw new VciBaseException(LangBaseUtil.getErrorMsg(e), new String[]{}, e);
        } finally {
            IOUtils.closeQuietly(ins);
            IOUtils.closeQuietly(os);
        }
    }
    /**
     * å†™å…¥æ•°æ®åˆ°excel文件中
     *
     * @param fileName      æ–‡ä»¶çš„名称,不能是jar中的文件,要包括绝对路径
     * @param writeExcelOption è¦å†™å…¥çš„æ•°æ®å’Œé…ç½®
     * @throws VciBaseException æ–‡ä»¶æœªæ‰¾åˆ°,写入数据出现了错误
     */
    public static void writeDataToFile(String fileName, WriteExcelOption writeExcelOption) throws VciBaseException {
        writeDataToFile(new File(fileName),  writeExcelOption);
    }
    /**
     * å†™å…¥æ•°æ®åˆ°excel文件中
     *
     * @param file          æ–‡ä»¶å¯¹è±¡
     * @param writeExcelOption è¦å†™å…¥çš„æ•°æ®å’Œé…ç½®
     * @param writeExcelOption è¦å†™å…¥çš„æ•°æ®å’Œé…ç½®
     * @throws VciBaseException æ–‡ä»¶æœªæ‰¾åˆ°,写入数据出现了错误
     */
    public static void writeDataToFile(File file, WriteExcelOption writeExcelOption) throws VciBaseException {
        if (file == null) {
            throw new VciBaseException("文件为空,无法找到文件");
        }
        if (!file.exists()) {
            File folder = file.getParentFile();
            if (!folder.exists()) {
                folder.mkdirs();
            }
            try {
                file.createNewFile();
            } catch (IOException e) {
                throw new VciBaseException(FILE_NOT_FOUND, new String[]{file.getName()});
            }
        }
        Workbook workbook = null;
        if(writeExcelOption!=null && writeExcelOption.isAppend()){
            try {
                if (file.length() == 0) {
                    workbook = createWorkbook(false);
                }else {
                    workbook = getWorkbookByInputStream(new FileInputStream(file));
                }
            } catch (FileNotFoundException e) {
                throw new VciBaseException("fileNotExist",new String[]{file.getName()},e);
            }
        }
        OutputStream os = null;
        try {
            os = new FileOutputStream(file);
        } catch (FileNotFoundException e) {
            throw new VciBaseException(FILE_NOT_FOUND, new String[]{e.getMessage()}, e);
        }
        try {
            writeDataToFile(os, writeExcelOption,workbook);
        } catch (VciBaseException e) {
            if (logger.isErrorEnabled()) {
                logger.error("写入数据到excel出错", e);
            }
            throw e;
        } catch (Throwable e) {
            if (logger.isErrorEnabled()) {
                logger.error("写入数据到excel出错", e);
            }
            throw new VciBaseException(LangBaseUtil.getErrorMsg(e), new String[]{}, e);
        } finally {
            //防止之前因为异常没有关闭
            IOUtils.closeQuietly(os);
        }
    }
    /**
     * å†™å…¥æ•°æ®åˆ°excel文件中
     *
     * @param os            æ–‡ä»¶è¾“出流,必须是excel文件的输出流
     * @param writeExcelOption è¦å†™å…¥çš„æ•°æ®å’Œé…ç½®
     * @throws VciBaseException æ–‡ä»¶æœªæ‰¾åˆ°,写入数据出现了错误
     */
    public static void writeDataToFile(OutputStream os, WriteExcelOption writeExcelOption) throws VciBaseException {
        writeDataToFile(os,writeExcelOption,null);
    }
    /**
     * å†™å…¥æ•°æ®åˆ°excel文件中
     *
     * @param os            æ–‡ä»¶è¾“出流,必须是excel文件的输出流
     * @param writeExcelOption è¦å†™å…¥çš„æ•°æ®å’Œé…ç½®
     * @param workbook å·¥ä½œç°¿å¯¹è±¡ï¼Œæ˜¯è¿½åŠ æ•°æ®çš„æ—¶å€™å…ˆèŽ·å–workbook
     * @throws VciBaseException æ–‡ä»¶æœªæ‰¾åˆ°,写入数据出现了错误
     */
    public static void writeDataToFile(OutputStream os, WriteExcelOption writeExcelOption,Workbook workbook) throws VciBaseException {
        if (os == null) {
            throw new VciBaseException(OUTPUT_STREAM_IS_NULL);
        }
        if (writeExcelOption == null ) {
            IOUtils.closeQuietly(os);
        } else {
            //有数据才执行写入
            Workbook wb = null;
            if(writeExcelOption.isAppend() && workbook !=null){
                wb = workbook;
            }else{
                wb = createWorkbook(writeExcelOption.isRevision07());
            }
            Workbook finalWb = wb;
            writeExcelOption.getWriteDataMap().forEach((sheetName, excelDataList) ->{
                Sheet sheet = getSheetByWorkbook(finalWb, sheetName);
                try {
                    writeDataToCell(sheet, excelDataList);
                } catch (VciBaseException e) {
                    IOUtils.closeQuietly(os);
                    throw e;
                } catch (Throwable e) {
                    if (logger.isErrorEnabled()) {
                        logger.error("写入数据到工作簿出错", e);
                    }
                    IOUtils.closeQuietly(os);
                    throw new VciBaseException(LangBaseUtil.getErrorMsg(e), new String[]{}, e);
                }
            });
            //是否有隐藏工作表
            if(!CollectionUtils.isEmpty(writeExcelOption.getHideSheetList())){
                writeExcelOption.getHideSheetList().stream().forEach(sheetName ->{
                    Sheet sheet = getSheetByWorkbook(finalWb, sheetName);
                    finalWb.setSheetHidden(finalWb.getSheetIndex(sheet),true);
                });
            }
            //到这里说明已经写到工作簿
            try {
                wb.write(os);
            } catch (IOException e) {
                if (logger.isErrorEnabled()) {
                    logger.error("把工作簿上的数据写入到文件出错", e);
                }
                throw new VciBaseException(LangBaseUtil.getErrorMsg(e), new String[]{}, e);
            } finally {
                IOUtils.closeQuietly(os);
                try {
                    wb.close();
                } catch (Throwable e) {
                    if (logger.isErrorEnabled()) {
                        logger.error("关闭工作簿", e);
                    }
                }
            }
        }
    }
    /**
     * èŽ·å–excel某个属性所在的列索引
     * @param excelFileName excel文件的名称
     * @param poClass poi导入导出对象所属的类
     * @param poFieldName è¦æŸ¥è¯¢çš„属性的名称
     * @param sheetName å·¥ä½œè¡¨çš„名称
     * @return åˆ—的索引,不存在的时候返回-1
     */
    public static int getCellIndexForPoField(String excelFileName,String sheetName,Class<?> poClass,String poFieldName) throws VciBaseException{
        return getCellIndexForPoField(new File(excelFileName),sheetName,poClass,poFieldName);
    }
    /**
     * èŽ·å–excel某个属性所在的列索引
     * @param excelFile excel文件的名称
     * @param poClass poi导入导出对象所属的类
     * @param poFieldName è¦æŸ¥è¯¢çš„属性的名称
     * @param sheetName å·¥ä½œè¡¨çš„名称
     * @return åˆ—的索引,不存在的时候返回-1
     */
    public static int getCellIndexForPoField(File excelFile,String sheetName,Class<?> poClass,String poFieldName) throws VciBaseException{
        VciBaseUtil.alertNotNull(excelFile,"excel的文件",poClass,"poi导入导出对象所属的类",poFieldName,"属性的名称");
        if(!excelFile.exists()){
            throw new VciBaseException("fileNotExist",new String[]{excelFile.getAbsolutePath()});
        }
        if(StringUtils.isBlank(sheetName)){
            sheetName = "Sheet1";
        }
        Field field = VciBaseUtil.getFieldForObject(poFieldName, poClass);
        if(field == null){
            throw new VciBaseException("对象中不存在此属性,{0},{1}",new String[]{poFieldName,poClass.getName()});
        }
        if(field.isAnnotationPresent(ExcelColumn.class)){
            ExcelColumn ec = getExcelColumnAnnotation(field);
            String columnName = ec.value();
            Workbook workbook = null;
            try {
                workbook = getWorkbookByInputStream(new FileInputStream(excelFile));
            } catch (FileNotFoundException e) {
                throw new VciBaseException("fileNotExist",new String[]{excelFile.getAbsolutePath()});
            }
            if(workbook!=null){
                Sheet sheet = workbook.getSheet(sheetName);
                if(sheet!=null){
                    Row row = sheet.getRow(getRowIndexForTitle(poClass));
                    if(row!=null){
                        short lastCellNum = row.getLastCellNum();
                        for(short i = 0;i<lastCellNum; i ++){
                            Cell cell = row.getCell(i);
                            if(columnName.equals(cell.getStringCellValue())){
                                try {
                                    workbook.close();
                                } catch (IOException e) {
                                    logger.error("关闭工作表出现错误",e);
                                }
                                return  i;
                            }
                        }
                    }
                }
            }
        }
        return -1;
    }
    /**
     * è¯»å–po对象里的各个属性的所在列的位置
     * @param excelFile excel文件
     * @param sheetName åˆ—的名称
     * @param poClass å¯¼å…¥å¯¼å‡ºçš„对象
     * @return key是属性名称,value是列所在的位置
     * @throws VciBaseException æ–‡ä»¶ä¸å­˜åœ¨ï¼Œè¯»å–出错的时候会抛出异常
     */
    public static Map<String,Integer> listCellIndexForPO(File excelFile,String sheetName,Class<?> poClass) throws VciBaseException{
        VciBaseUtil.alertNotNull(excelFile,"excel的文件",poClass,"poi导入导出对象所属的类");
        if(!excelFile.exists()){
            throw new VciBaseException("fileNotExist",new String[]{excelFile.getAbsolutePath()});
        }
        if(StringUtils.isBlank(sheetName)){
            sheetName = "Sheet1";
        }
        List<Field> fields = VciBaseUtil.getAllFieldForObj(poClass);
        //列索引映射,key是属性的名称,value是列索引
        Map<String,Integer> cellIndexMap = new HashMap<>();
        if(!CollectionUtils.isEmpty(fields)){
            Workbook workbook = null;
            try {
                workbook = getWorkbookByInputStream(new FileInputStream(excelFile));
            } catch (FileNotFoundException e) {
                throw new VciBaseException("fileNotExist",new String[]{excelFile.getAbsolutePath()});
            }
            if(workbook!=null) {
                Sheet sheet = workbook.getSheet(sheetName);
                if (sheet != null) {
                    Row row = sheet.getRow(getRowIndexForTitle(poClass));
                    if (row != null) {
                        Map<String,String> columnNamesMap = new HashMap<>();
                        fields.stream().forEach(field -> {
                            if(field.isAnnotationPresent(ExcelColumn.class)) {
                                ExcelColumn ec = getExcelColumnAnnotation(field);
                                String columnName = ec.value();
                                columnNamesMap.put(columnName,field.getName());
                            }
                        });
                        short lastCellNum = row.getLastCellNum();
                        for(short i = 0;i<lastCellNum; i ++){
                            Cell cell = row.getCell(i);
                            String cellName = cell.getStringCellValue();
                            if(columnNamesMap.containsKey(cellName)){
                                cellIndexMap.put(columnNamesMap.get(cellName),Integer.valueOf(i));
                            }
                        }
                    }
                }
                try {
                    workbook.close();
                } catch (IOException e) {
                    logger.error("关闭工作表出现错误",e);
                }
            }
        }
        return cellIndexMap;
    }
    /**
     * èŽ·å–æ ‡é¢˜æ‰€åœ¨çš„è¡Œ
     * @param poClass poi导出导入对象
     * @return è¡Œç´¢å¼•
     */
    public static int getRowIndexForTitle(Class<?> poClass){
        if(poClass.isAnnotationPresent(ExcelTitle.class)){
            ExcelTitle ec = poClass.getAnnotation(ExcelTitle.class);
            if (ec == null) {
                ec = poClass.getDeclaredAnnotation(ExcelTitle.class);
            }
            if(ec !=null){
                return ec.rowIndexForTitle();
            }
        }
        return 0;
    }
    /**
     * æ ¹æ®åˆ—序号获取列的名称
     * @param colIndex åˆ—序号
     * @return åˆ—的名称
     */
    public static String getCellNameByIndex(int colIndex){
        //A~Z
        //AA~AZ
        //BA~BZ
        if(colIndex<26){
            return String.valueOf((char)('A' + colIndex));
        }else{
            //
            //大于等于26,取倍数和余数
            int balance = colIndex%26;
            int multiple = (colIndex-balance)/26;
            String prefix = String.valueOf((char)('A'  + (multiple-1)));
            String suffix = String.valueOf((char)('A'  + balance));
            return prefix+suffix;
        }
    }
    /**
     * åˆ›å»ºå·¥ä½œç°¿ï¼Œæ³¨æ„éƒ½æ˜¯03版本的,为了兼容
     *
     * @return å·¥ä½œç°¿å¯¹è±¡
     */
    public static Workbook createWorkbook(boolean is07) {
        Workbook wb = null;
        if(is07){
            wb = new XSSFWorkbook();
        }else{
            wb = new HSSFWorkbook();
        }
        //导出都是些2003版本的,用于兼容
        return wb;
    }
    /**
     * èŽ·å–å·¥ä½œç°¿å¯¹è±¡
     *
     * @param ins æ–‡ä»¶è¾“入流
     * @return å·¥ä½œç°¿ï¼Œpoi3.15以上版本不区分03还07
     * @throws VciBaseException å¦‚果不是excel文件,会直接报错
     */
    public static Workbook getWorkbookByInputStream(InputStream ins) throws VciBaseException {
        Workbook wb = null;
        try {
            wb = WorkbookFactory.create(ins);
        } catch (IOException e) {
            IOUtils.closeQuietly(ins);
            throw new VciBaseException(WORKBOOK_INIT_FAIL, new String[]{LangBaseUtil.getErrorMsg(e)});
        }
        return wb;
    }
    /**
     * èŽ·å–å·¥ä½œè¡¨ï¼Œå¦‚æžœå·¥ä½œè¡¨åç§°ä¸å­˜åœ¨ï¼Œåˆ™ä¼šåˆ›å»ºä¸€ä¸ª
     *
     * @param wb        å·¥ä½œç°¿
     * @param sheetName å·¥ä½œè¡¨çš„名称
     * @return å·¥ä½œè¡¨å¯¹è±¡
     */
    private static Sheet getSheetByWorkbook(Workbook wb, String sheetName) {
        if (StringUtils.isBlank(sheetName)) {
            sheetName = "Sheet1";
        }
        Sheet sheet = wb.getSheet(sheetName);
        if (sheet == null) {
            sheet = wb.createSheet(sheetName);
        }
        return sheet;
    }
    /**
     * èŽ·å–è¡Œçš„å¯¹è±¡
     *
     * @param sheet    å·¥ä½œè¡¨å¯¹è±¡
     * @param rowIndex è¡Œå·ï¼Œä»Ž0开始
     * @return è¡Œçš„对象,不存在会创建一行
     */
    private static Row getRowBySheet(Sheet sheet, int rowIndex) {
        Row row = sheet.getRow(rowIndex);
        if (row == null) {
            //说明这个时候还没有创建这行--即没有值
            row = sheet.createRow(rowIndex);
        }
        return row;
    }
    /**
     * æ ¹æ®è¡ŒèŽ·å–å•å…ƒæ ¼å¯¹è±¡
     *
     * @param row       è¡Œå¯¹è±¡
     * @param cellIndex åˆ—序号,从0开始
     * @return å•元格的对象,不存在会创建
     */
    private static Cell getCellByRow(Row row, int cellIndex) {
        Cell cell = row.getCell(cellIndex);
        if (cell == null) {
            //说明还没有创建这个单元格
            cell = row.createCell(cellIndex);
        }
        return cell;
    }
    /**
     * å†™å…¥æ•°æ®
     *
     * @param sheet         è¡¨æ ¼å¯¹è±¡
     * @param excelDataList è¦å†™å…¥çš„æ•°æ®å¯¹è±¡
     */
    private static void writeDataToCell(Sheet sheet, List<WriteExcelData> excelDataList) throws VciBaseException {
        if (sheet != null && !CollectionUtils.isEmpty(excelDataList)) {
            List<WriteExcelData> mergedDataList = new ArrayList<>();
            excelDataList.stream().forEach(ed -> {
                Row row = getRowBySheet(sheet, ed.getRow());
                Cell cell = getCellByRow(row, ed.getCol());
                //合并单元格
                if (ed.isMerged() && (ed.getRowTo() > ed.getRow() || ed.getColTo() > ed.getCol())) {
                    mergedDataList.add(ed);
                }
                copyStyle(sheet, cell, ed);
                if(ed.isReadOnly() && ed.getObj() !=null && !(ed.getObj() instanceof RichTextString) && CollectionUtils.isEmpty(ed.getValidationDataList())){
                    //ed.setValidation(true);
                    List<String> list = new ArrayList<>();
                    list.add(ed.getObj().toString());
                    ed.setValidationDataList(list );
                    setValidation(sheet,ed);
                }
                centerCell(cell, ed);
                Object value = ed.getObj();
                if(StringUtils.isNotBlank(ed.getFontColor())){
                    String rtsValue = value ==null?"":value.toString();
                    RichTextString ts = (cell instanceof HSSFCell)?new HSSFRichTextString(rtsValue):new XSSFRichTextString(rtsValue);
                    Font font = sheet.getWorkbook().createFont();
                    font.setColor(VciBaseUtil.getShort(ed.getFontColor()));
                    ts.applyFont(font);
                    value = ts;
                }
                if(ed.isFormula()){
                    //设置公式,如果即有值,还要设置公式则设置为两个对象
                    setFormula(cell,ed);
                }else if(ed.isNameRefer()){
                    //设置名称管理器,一般和有效性配合使用
                    setNameRefer(sheet,ed);
                }else if(ed.isValidation()){
                    //说明是直接写有效性的值
                    setValidation(sheet,ed);
                }else{
                    //写值
                    setCellValue(cell, value);
                }
                if(ed.getWidth()!=null && ed.getWidth()>0){
                    sheet.setColumnWidth(cell.getColumnIndex(),(int)(ed.getWidth() + 0.72)*256);
                }
            });
            mergedRegion(sheet, mergedDataList);
        }
    }
    /**
     * ä¸ºå•元格设置公式
     * @param cell å•元格的对象
     * @param ed æ•°æ®å¯¹è±¡
     */
    private static void setFormula(Cell cell ,WriteExcelData ed){
        if (ed.getObj() != null) {
            cell.setCellFormula(ed.getObj().toString());
        }
    }
    /**
     * è®¾ç½®åç§°ç®¡ç†å™¨
     * @param sheet å·¥ä½œè¡¨
     * @param ed æ•°æ®å¯¹è±¡
     */
    private static void setNameRefer(Sheet sheet,WriteExcelData ed){
        if(ed.getObj() !=null){
            Name name = sheet.getWorkbook().createName();
            name.setNameName(ed.getObj().toString());
            name.setRefersToFormula(sheet.getSheetName() + "!"+getRange(ed));
        }
    }
    /**
     * è®¾ç½®æ•°æ®æœ‰æ•ˆæ€§
     * @param sheet å·¥ä½œè¡¨
     * @param ed æ•°æ®å¯¹è±¡
     */
    private static void setValidation(Sheet sheet,WriteExcelData ed){
        if(ed.getRowTo()<ed.getRow()){
            ed.setRowTo(ed.getRow());
        }
        if(ed.getColTo()<ed.getCol()){
            ed.setColTo(ed.getCol());
        }
        CellRangeAddressList regions=new CellRangeAddressList(ed.getRow(),ed.getRowTo(),ed.getCol(),ed.getColTo());
        DataValidation validation = null;
        if (sheet instanceof XSSFSheet) {
            XSSFDataValidationHelper dvHelper = new XSSFDataValidationHelper((XSSFSheet)sheet);
            XSSFDataValidationConstraint dvConstraint = null;
            if(!CollectionUtils.isEmpty(ed.getValidationDataList())){
                //说明是直接写内容的
                dvConstraint = (XSSFDataValidationConstraint)dvHelper.createExplicitListConstraint(ed.getValidationDataList().toArray(new String[0]));
            }else{
                VciBaseUtil.alertNotNull(ed.getObj(),"写入有效性的时候,没有设置有效性的公式表达式");
                dvConstraint = (XSSFDataValidationConstraint) dvHelper.createFormulaListConstraint(ed.getObj().toString());
            }
            validation = (XSSFDataValidation) dvHelper.createValidation(dvConstraint, regions);
        }else{
            HSSFDataValidationHelper dvHelper = new HSSFDataValidationHelper((HSSFSheet)sheet);
            DataValidationConstraint dvConstraint = null;
            if(!CollectionUtils.isEmpty(ed.getValidationDataList())){
                //说明是直接写内容的
                dvConstraint = dvHelper.createExplicitListConstraint(ed.getValidationDataList().toArray(new String[0]));
            }else{
                VciBaseUtil.alertNotNull(ed.getObj(),"写入有效性的时候,没有设置有效性的公式表达式");
                dvConstraint = dvHelper.createFormulaListConstraint(ed.getObj().toString());
            }
            validation = (HSSFDataValidation)(new HSSFDataValidation(regions,dvConstraint));
        }
        if(validation instanceof XSSFDataValidation) {
            validation.setSuppressDropDownArrow(true);
            validation.setShowErrorBox(true);
        }else {
            validation.setSuppressDropDownArrow(false);
        }
        if(StringUtils.isNotBlank(ed.getValidationErrorMsg())){
            validation.createErrorBox("error",ed.getValidationErrorMsg());
        }
        sheet.addValidationData(validation);
    }
    /**
     * èŽ·å–èŒƒå›´çš„è¡¨è¾¾å¼
     * @param excelData æ•°æ®å¯¹è±¡
     * @return èŒƒå›´çš„表达式
     */
    private static String getRange(WriteExcelData excelData){
        //列是从A开始的
        char start = (char)('A' + excelData.getCol());
        int rowId = excelData.getRow() + 1;
        int endRowId = excelData.getRowTo() +1;
        if (excelData.getColTo() <= 25) {
            char end = (char)('A' +excelData.getColTo());
            return "$" + start + "$" + rowId + ":$" + end + "$" + endRowId;
        } else {
            char endPrefix = 'A';
            char endSuffix = 'A';
            if ((excelData.getColTo() - 25) / 26 == 0 || excelData.getColTo() == 51) {// 26-51之间,包括边界(仅两次字母表计算)
                if ((excelData.getColTo() - 25) % 26 == 0) {// è¾¹ç•Œå€¼
                    endSuffix = (char)('A' + 25);
                } else {
                    endSuffix = (char)('A' + (excelData.getColTo() - 25) % 26 - 1);
                }
            } else {// 51以上
                if ((excelData.getColTo() - 25) % 26 == 0) {
                    endSuffix = (char)('A' + 25);
                    endPrefix = (char)(endPrefix + (excelData.getColTo() - 25) / 26 - 1);
                } else {
                    endSuffix = (char)('A' + (excelData.getColTo() - 25) % 26 - 1);
                    endPrefix = (char)(endPrefix + (excelData.getColTo() - 25) / 26);
                }
            }
            return "$" + start + "$" + rowId + ":$" + endPrefix + endSuffix + "$" + endRowId;
        }
    }
    /**
     * å¾€å•元格里写入值
     *
     * @param cell  å•元格对象
     * @param value è¦å†™å…¥çš„值
     */
    private static void setCellValue(Cell cell, Object value) {
        if (value != null) {
            if (value instanceof Date) {
                cell.setCellValue((Date) value);
            } else if (value instanceof String) {
                cell.setCellValue(value.toString());
            } else if (value instanceof Boolean) {
                cell.setCellValue((Boolean)value);
            } else if (value instanceof Integer) {
                cell.setCellValue((Integer) value);
            } else if (value instanceof Long) {
                cell.setCellValue((Long) value);
            } else if (value instanceof BigDecimal) {
                cell.setCellValue(((BigDecimal) value).doubleValue());
            } else if (value instanceof Double) {
                cell.setCellValue((Double) value);
            } else if (value instanceof RichTextString) {
                cell.setCellValue((RichTextString) value);
            } else {
                cell.setCellValue(value.toString());
            }
        }
    }
    /**
     * æ‹·è´æ ·å¼
     *
     * @param sheet     å·¥ä½œè¡¨
     * @param cell      å•元格
     * @param excelData è¦æ‹·è´çš„信息
     */
    private static void copyStyle(Sheet sheet, Cell cell, WriteExcelData excelData) {
        if (excelData.isCopyStyle()) {
            //拷贝样式
            Row copyStyleRow = sheet.getRow(excelData.getCopyStyleRow());
            if (copyStyleRow != null) {
                Cell copyStyleCell = copyStyleRow.getCell(excelData.getCopyStyleCol());
                copyStyleForCell(copyStyleCell,cell);
                if(StringUtils.isNotBlank(excelData.getDateFormat())){
                    HSSFDataFormat format= (HSSFDataFormat) sheet.getWorkbook().createDataFormat();
                    cell.getCellStyle().setDataFormat(format.getFormat(excelData.getDateFormat()));
                }
            }
        }
    }
    /**
     * æ‹·è´å•元格的样式
     * @param fromCell æ¥æºç«¯å•元格
     * @param toCell ç›®æ ‡ç«¯å•元格
     */
    private static void copyStyleForCell(Cell fromCell,Cell toCell){
        // æ ·å¼
        CellStyle cellStyle = toCell.getCellStyle();
        CellStyle fromStyle = fromCell.getCellStyle();
        cellStyle.cloneStyleFrom(fromStyle);
        cellStyle.setAlignment(fromStyle.getAlignment());
        cellStyle.setBorderBottom(fromStyle.getBorderBottom());
        cellStyle.setBorderLeft(fromStyle.getBorderLeft());
        cellStyle.setBorderRight(fromStyle.getBorderRight());
        cellStyle.setBorderTop(fromStyle.getBorderTop());
        cellStyle.setDataFormat(fromStyle.getDataFormat());
        cellStyle.setFillBackgroundColor(fromStyle.getFillBackgroundColor());
        cellStyle.setFillForegroundColor(fromStyle.getFillForegroundColor());
        cellStyle.setFillPattern(fromStyle.getFillPattern());
        cellStyle.setVerticalAlignment(fromStyle.getVerticalAlignment());
        cellStyle.setWrapText(fromStyle.getWrapText());
        cellStyle.setLocked(fromStyle.getLocked());
        cellStyle.setBottomBorderColor(fromStyle.getBottomBorderColor());
        cellStyle.setLeftBorderColor(fromStyle.getLeftBorderColor());
        cellStyle.setTopBorderColor(fromStyle.getTopBorderColor());
        cellStyle.setRightBorderColor(fromStyle.getRightBorderColor());
    }
    /**
     * å±…中数据
     *
     * @param cell      å•元格
     * @param excelData è¦å±…中的内容
     */
    private static void centerCell(Cell cell, WriteExcelData excelData) {
        if (excelData.isCenter()) {
            CellStyle cellStyle = cell.getCellStyle();
            cellStyle.setAlignment(HorizontalAlignment.CENTER);//水平居中
            cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);//垂直居中
        }
    }
    /**
     * åˆå¹¶å•元格
     *
     * @param sheet          å·¥ä½œè¡¨
     * @param mergedDataList è¦åˆå¹¶çš„æ•°æ®ä¿¡æ¯
     */
    private static void mergedRegion(Sheet sheet, Collection<WriteExcelData> mergedDataList) {
        if (!CollectionUtils.isEmpty(mergedDataList)) {
            mergedDataList.stream().forEach(ed -> {
                if (ed.getRowTo() < ed.getRow()) {
                    ed.setRowTo(ed.getRow());
                }
                if (ed.getColTo() < ed.getCol()) {
                    ed.setColTo(ed.getCol());
                }
                sheet.addMergedRegion(new CellRangeAddress(ed.getRow(), ed.getRowTo(), ed.getCol(), ed.getColTo()));
            });
        }
    }
    /**
     * ä»Žexcel上读取数据
     *
     * @param file æ–‡ä»¶
     * @return æ•°æ®åˆ—表
     * @throws VciBaseException æ‰§è¡Œå‡ºé”™çš„æ—¶å€™ä¼šæŠ›å‡ºå¼‚常
     */
    public static  List<SheetDataSet> readDataObjectFromExcel(File file) throws VciBaseException {
        return readDataObjectFromExcel(file, SheetDataSet.class);
    }
    /**
     * ä»Žexcel上读取数据
     *
     * @param file        æ–‡ä»¶
     * @param doClass æ•°æ®å¯¹è±¡çš„类型
     * @param <T>         æ•°æ®å¯¹è±¡çš„类型
     * @return æ•°æ®åˆ—表
     * @throws VciBaseException æ‰§è¡Œå‡ºé”™çš„æ—¶å€™ä¼šæŠ›å‡ºå¼‚常
     */
    public static <T> List<T> readDataObjectFromExcel(File file, Class<T> doClass) throws VciBaseException {
        return readDataObjectFromExcel(file, doClass, null);
    }
    /**
     * ä»Žexcel上读取数据
     *
     * @param file        æ–‡ä»¶
     * @param excelOption è¯»å–的类型,包括数据的首行,
     * @param doClass     æ•°æ®å¯¹è±¡çš„ç±»
     * @param <T>         æ•°æ®å¯¹è±¡çš„类型
     * @return æ•°æ®åˆ—表
     * @throws VciBaseException æ‰§è¡Œå‡ºé”™çš„æ—¶å€™ä¼šæŠ›å‡ºå¼‚常
     */
    public static <T> List<T> readDataObjectFromExcel(File file, Class<T> doClass, ReadExcelOption excelOption) throws VciBaseException {
        return readDataObjectFromExcel(file, doClass,excelOption, null);
    }
    /**
     * ä»Žexcel上读取数据
     *
     * @param file        æ–‡ä»¶
     * @param excelOption è¯»å–的类型,包括数据的首行,
     * @param doClass     æ•°æ®å¯¹è±¡çš„ç±»
     * @param <T>         æ•°æ®å¯¹è±¡çš„类型
     * @param processer   è½¬æ¢å™¨
     * @return æ•°æ®åˆ—表
     * @throws VciBaseException æ‰§è¡Œå‡ºé”™çš„æ—¶å€™ä¼šæŠ›å‡ºå¼‚常
     */
    public static <T> List<T> readDataObjectFromExcel(File file, Class<T> doClass,ReadExcelOption excelOption,  PoiImportProcesser<T> processer) throws VciBaseException {
        InputStream ins = null;
        try {
            ins = new FileInputStream(file);
        } catch (Throwable e) {
            String msg = READ_IMPORT_FILE_FAIL;
            if (logger.isErrorEnabled()) {
                logger.error(msg, e);
            }
            throw new VciBaseException(msg + LangBaseUtil.getErrorMsg(e), new String[]{}, e);
        }
        try {
            return readDataObjectFromExcel(ins, doClass, excelOption,processer);
        } catch (VciBaseException e) {
            throw e;
        } catch (Throwable e) {
            throw new VciBaseException(LangBaseUtil.getErrorMsg(e), new String[]{}, e);
        } finally {
            IOUtils.closeQuietly(ins);
        }
    }
    /**
     * ä»Žexcel上读取数据
     *
     * @param ins         æ–‡ä»¶æµ
     * @param excelOption è¯»å–的类型,包括数据的首行(默认1),工作表(默认0)和是否全部工作表(默认否)
     * @param doClass     æ•°æ®çš„对象
     * @param <T>         æ•°æ®å¯¹è±¡æ‰€å±žçš„类型
     * @param processer   è½¬æ¢å™¨
     * @return æ•°æ®åˆ—表
     * @throws VciBaseException æ‰§è¡Œå‡ºé”™çš„æ—¶å€™ä¼šæŠ›å‡ºå¼‚常
     */
    public static <T> List<T> readDataObjectFromExcel(InputStream ins, Class<T> doClass,ReadExcelOption excelOption,  PoiImportProcesser<T> processer) throws VciBaseException {
        if (ins == null) {
            throw new VciBaseException(INPUT_STREAM_IS_NULL);
        }
        if (doClass == null) {
            doClass = (Class<T>) SheetDataSet.class;
        }
        boolean isDataSet = false;
        if (doClass.equals(SheetDataSet.class)) {
            isDataSet = true;
        }
        //获取对象上的列的名称
        Map<Field, ExcelColumn> excelColumnSet = getExcelColumnAnnotations(doClass);
        Map<String/**标题**/, ExcelColumn> excelTitleMap = Optional.of(excelColumnSet).get().values().stream().collect(Collectors.toMap(s -> s.value(), t -> t));
        Map<String/**标题**/,Field> excelTitleFieldMap = new HashMap<>();
        Map<String/**标题**/,ExcelColumnMap> extendAttrTitleMap = new HashMap<>();
        final Field[] rowIndexFields = {null};
        ReadExcelOption finalExcelOption = excelOption;
        excelColumnSet.forEach(((field, excelColumn) -> {
            excelTitleFieldMap.put(excelColumn.value(),field);
            if (excelColumn.rowIndexColumn()) {
                rowIndexFields[0] = field;
            }
            field.setAccessible(true);
            if((field.getType().equals(Map.class) || field.getType().getSuperclass().equals(Map.class))
                    && !CollectionUtils.isEmpty(finalExcelOption.getExtendAttrMap())
                    &&  finalExcelOption.getExtendAttrMap().containsKey(excelColumn.value())){
                //说明是map类型,这种一般是扩展属性,将一堆属性转换为map里的值
                List<ExcelColumnMap> excelColumnMaps = finalExcelOption.getExtendAttrMap().get(excelColumn.value());
                if(!CollectionUtils.isEmpty(excelColumnMaps)){
                    excelColumnMaps.stream().forEach(ss->{
                        excelTitleFieldMap.put(ss.getTitle(),field);
                        extendAttrTitleMap.put(ss.getTitle(),ss);
                    });
                }
            }
        }));
        Field rowIndexField = null;
        if (rowIndexFields[0] != null) {
            rowIndexField = rowIndexFields[0];
        }
        Workbook workbook = getWorkbookByInputStream(ins);
        if (excelOption == null) {
            excelOption = new ReadExcelOption();
        }
        FormulaEvaluator evaluator = workbook.getCreationHelper().createFormulaEvaluator();
        List<T> dataSet = new ArrayList<>();
        try {
            for (int sheetIndex = 0; sheetIndex < workbook.getNumberOfSheets(); sheetIndex++) {
                Sheet sheet = workbook.getSheetAt(sheetIndex);
                if(StringUtils.isNotBlank(excelOption.getSheetName())){
                    if(!sheet.getSheetName().equalsIgnoreCase(excelOption.getSheetName())){
                        continue;
                    }
                }else {
                    if (!excelOption.isReadAllSheet() && sheetIndex != excelOption.getSheetIndex()) {
                        continue;
                    }
                }
                SheetDataSet sheetDataSet = new SheetDataSet();
                sheetDataSet.setSheetName(sheet.getSheetName());
                if (isDataSet) {
                    dataSet.add((T) sheetDataSet);
                }
                //处理标题
                Map<Integer, String> colsNameIndexMap = new HashMap<>();
                if (excelOption.getFristRow() > 0) {
                    //等于0表示没有总标题
                    try {
                        Row titleRow = sheet.getRow(excelOption.getFristRow()-1);
                        int colsCount = titleRow.getLastCellNum();
                        List<String> titleList = new LinkedList<>();
                        for (int i = 0; i < colsCount; i++) {
                            String title = VciBaseUtil.getStringValueFromObject(getCellValue(titleRow.getCell(i),evaluator));
                            if (StringUtils.isNotBlank(title)) {
                                title= title.replace("*","").replace("☆","");
                                colsNameIndexMap.put(i, title);
                                titleList.add(title);
                            }
                        }
                        if (isDataSet) {
                            sheetDataSet.setColName(titleList);
                        }
                    } catch (Exception e) {
                        if (logger.isErrorEnabled()) {
                            logger.error("读取excel文件中的标题信息出现了错误", e);
                        }
                        throw e;
                    }
                }
                //读取值
                List<SheetRowData> rowDataList = new LinkedList<SheetRowData>();
                if (sheet.getLastRowNum() > 0) {
                    for (int rowIndex = excelOption.getFristRow(); rowIndex <= sheet.getLastRowNum(); rowIndex++) {
                        Row rowDataSet = sheet.getRow(rowIndex);
                        if (rowDataSet == null) {
                            continue;
                        }
                        boolean notValue = false;
                        for (int i = 0; i < rowDataSet.getLastCellNum(); i++) {
                            Cell cellTemp = rowDataSet.getCell(i);
                            Object valueTemp = getCellValue(cellTemp, evaluator);
                            if((valueTemp != null && !(valueTemp instanceof String) )
                                    || (valueTemp instanceof String && valueTemp !=null && StringUtils.isNotBlank(valueTemp.toString())) ){
                                notValue = true;
                                break;
                            }
                        }
                        if(!notValue){
                            //整行都是空,直接跳过
                            continue;
                        }
                        //实例化数据对象
                        SheetRowData rd = (isDataSet ? new SheetRowData() : null);
                        T obj = null;
                        if (!isDataSet) {
                            try {
                                obj = doClass.newInstance();
                            } catch (Throwable e) {
                                if (logger.isErrorEnabled()) {
                                    logger.error("实例化数据对象", e);
                                }
                                throw new VciBaseException("实例化数据对象," + LangBaseUtil.getErrorMsg(e));
                            }
                        }
                        //处理行号
                        if (isDataSet) {
                            rd.setRowIndex(String.valueOf(rowIndex));
                        }
                        if (!isDataSet && rowIndexField != null) {
                            VciBaseUtil.setValueForField(rowIndexField, obj, String.valueOf(rowIndex));
                        }
                        //每行的数据
                        Map<Integer, String> rowDataMap = new HashMap<>();
                        //遍历这行的每一个单元格的数据
                        for (int columnIndex = 0; columnIndex < rowDataSet.getLastCellNum(); columnIndex++) {
                            Cell cell = rowDataSet.getCell(columnIndex);
                            Object value = getCellValue(cell, evaluator);
                            //说明是对象
                            String title = colsNameIndexMap.containsKey(columnIndex)?colsNameIndexMap.get(columnIndex):"";
                            //属性是否为map形式
                            boolean isMapField = false;
                            Field thisField = null;
                            if (StringUtils.isNotBlank(title) && excelTitleFieldMap.containsKey(title)) {
                                thisField = excelTitleFieldMap.get(title);
                            }
                            if(thisField!=null){
                                thisField.setAccessible(true);
                                if(thisField.getType().equals(Map.class) || thisField.getType().getSuperclass().equals(Map.class)){
                                    isMapField = true;
                                }
                            }
                            ExcelColumn excelColumn = null;
                            if (StringUtils.isNotBlank(title) && excelTitleMap.containsKey(title)) {
                                excelColumn = excelTitleMap.get(title);
                            }
                            ExcelColumnMap columnMap = null;
                            if(isMapField){
                                columnMap = extendAttrTitleMap.get(title);
                            }
                            boolean isNull = false;
                            if(value == null || (value instanceof String && StringUtils.isBlank(value.toString()))){
                                isNull = true;
                            }
                            if (!isNull) {
                                if (!isDataSet) {
                                    if (thisField != null && (excelColumn != null || columnMap!=null)) {
                                        if(!isMapField) {
                                            if (value.getClass().equals(thisField.getType())) {
                                                try {
                                                    thisField.set(obj, value);
                                                } catch (IllegalAccessException e) {
                                                    if (logger.isErrorEnabled()) {
                                                        logger.error("读取excel的单元格的值后,为对象赋值出现了错误", e);
                                                    }
                                                }
                                            } else {
                                                VciBaseUtil.setValueForField(thisField, obj, VciBaseUtil.getStringValueFromObject(value));
                                            }
                                            if (thisField.getType().equals(Date.class) && thisField.get(obj) == null) {
                                                throw new VciBaseException(CELL_NOT_DATE_FORMATE, new String[]{title, (rowIndex + 1) + ""});
                                            }
                                            if (StringUtils.isNotBlank(excelColumn.regExg()) && !VciBaseUtil.getStringValueFromObject(value).matches(excelColumn.regExg())) {
                                                throw new VciBaseException(CELL_VALUE_NOT_EQUAL_REG, new String[]{title, (rowIndex + 1) + "", excelColumn.regExgTitle()});
                                            }
                                        }else{
                                            //说明是map
                                            Object fieldValue = thisField.get(obj);
                                            Map<String,String> data ;
                                            if(fieldValue==null){
                                                data = new HashMap<>();
                                            }else{
                                                data = (Map<String,String>)fieldValue;
                                            }
                                            data.put(columnMap.getColumnName(),value==null?"":value.toString());
                                            try {
                                                thisField.set(obj, data);
                                            } catch (IllegalAccessException e) {
                                                if (logger.isErrorEnabled()) {
                                                    logger.error("设置map类型的数据时候出现了错误", e);
                                                }
                                            }
                                        }
                                    }
                                    if (processer != null && thisField != null) {
                                        processer.process(value, obj, thisField);
                                    }
                                } else {
                                    //说明只是读取数据
                                    rowDataMap.put(columnIndex, VciBaseUtil.getStringValueFromObject(value));
                                }
                            }else{
                                //需要判断一下,是不是整行都是空的
                                if (!isDataSet && thisField != null && excelColumn != null ) {
                                    if(!excelColumn.nullable() ) {
                                        throw new VciBaseException(CELL_VALUE_CAN_NOT_NULL, new String[]{title, (rowIndex + 1) + ""});
                                    }
                                    if(StringUtils.isNotBlank(excelColumn.regExg())){
                                        throw new VciBaseException(CELL_VALUE_CAN_NOT_NULL_FOR_REG, new String[]{title, (rowIndex + 1) + ""});
                                    }
                                }
                            }
                        }
                        if (isDataSet) {
                            rd.setData(rowDataMap);
                            rowDataList.add(rd);
                        } else {
                            dataSet.add(obj);
                        }
                    }
                }
                if(isDataSet){
                    sheetDataSet.setRowData(rowDataList);
                }
            }
        }catch (Throwable e){
            throw new VciBaseException(LangBaseUtil.getErrorMsg(e),new String[0],e);
        }finally {
            IOUtils.closeQuietly(ins);
            try {
                workbook.close();
            } catch (IOException e) {
                if(logger.isErrorEnabled()){
                    logger.error("关闭工作簿出现了错误",e);
                }
            }
        }
        return  dataSet;
    }
    /**
     * ä»Žcell单元格上获取值
     * @param cell å•元格对象
     * @param evaluator å…¬å¼è½¬æ¢
     * @return å•元格的值,没有转换为字符串
     */
    private static Object getCellValue(Cell cell,FormulaEvaluator evaluator){
        if(cell !=null ){
            Object cellValue = null;
            CellType cellTypeEnum = cell.getCellType();
            switch (cellTypeEnum){
                case STRING:
                    String thisCellValue = cell.getStringCellValue();
                    cellValue = StringUtils.isEmpty(thisCellValue)?"":thisCellValue.trim();
                    break;
                case BOOLEAN:
                    boolean boolValue = cell.getBooleanCellValue();
                    cellValue = boolValue;
                    break;
                case FORMULA:
                    cellValue = getCellValue(evaluator.evaluate(cell));
                    break;
                case NUMERIC:
                    if(DateUtil.isCellDateFormatted(cell)){
                        cellValue = cell.getDateCellValue();
                    }else{
                        cellValue = cell.getNumericCellValue();
                    }
                    break;
                default:
                    cellValue = "";
                    break;
            }
            return cellValue;
        }else{
            return null;
        }
    }
    /**
     * é’ˆå¯¹å…¬å¼çš„计算值
     * @param cell å…¬å¼è½¬æ¢åŽçš„单元格对象
     * @return å…¬å¼çš„实际值
     */
    private static Object getCellValue(CellValue cell) {
        Object cellValue = null;
        switch (cell.getCellTypeEnum()) {
            case STRING:
                String thisCellValue = cell.getStringValue();
                cellValue = StringUtils.isEmpty(thisCellValue)?"":thisCellValue.trim();
                break;
            case NUMERIC:
                //公式计算不会有日期型
                cellValue=cell.getNumberValue();
                break;
            default:
                break;
        }
        return cellValue;
    }
    /**
     * èŽ·å–ç”µå­è¡¨æ ¼ç›¸å…³çš„æ³¨è§£
     *
     * @param doClass è¿”回的类
     * @return ä¸æ˜¯SheetDataSet的时候需要返回所有包含了excelcolumn注解的属性
     */
    public static <T> Map<Field, ExcelColumn> getExcelColumnAnnotations(Class<T> doClass) {
        Map<Field, ExcelColumn> excelColumnMap = new HashMap();
        if (!doClass.equals(SheetDataSet.class)) {
            List<Field> allFields = VciBaseUtil.getAllFieldForObj(doClass);
            List<Field> hasExcelColumnFields = allFields.stream().filter(field -> field.isAnnotationPresent(ExcelColumn.class)).collect(Collectors.toList());
            if (!CollectionUtils.isEmpty(hasExcelColumnFields)) {
                hasExcelColumnFields.stream().forEach(field -> {
                    ExcelColumn ec = getExcelColumnAnnotation(field);
                    excelColumnMap.put(field, ec);
                });
            }
        }
        return excelColumnMap;
    }
    /**
     * èŽ·å–å±žæ€§ä¸Šçš„excelColumn的注解
     * @param field å±žæ€§å¯¹è±¡
     * @return excelColumn
     */
    public static ExcelColumn getExcelColumnAnnotation(Field field){
        ExcelColumn ec = field.getAnnotation(ExcelColumn.class);
        if (ec == null) {
            ec = field.getDeclaredAnnotation(ExcelColumn.class);
        }
        return ec;
    }
    /**
     * æ ¹æ®PO对象,导出模板
     * @param doClass å¯¼å‡ºçš„对象
     * @param downloadTempOption ä¸‹è½½çš„选项
     * @param processer è°ƒç”¨å‡½æ•°ï¼ŒèŽ·å–æžšä¸¾çš„å€¼
     * @param <T> ç±»åž‹
     * @return æ–‡ä»¶çš„路径
     */
    public static <T> String downloadImportTempByClass(Class<T> doClass,DownloadTempOption downloadTempOption,PoiTemplateProcesser<T> processer){
        if(downloadTempOption == null){
            downloadTempOption = new DownloadTempOption("");
        }
        //ok,写excel
        String excelName = LocalFileUtil.getDefaultTempFolder() + File.separator + (StringUtils.isNotBlank(downloadTempOption.getExcelName())?downloadTempOption.getExcelName():"导入模板.xls");
        try {
            new File(excelName).createNewFile();
        } catch (Throwable e) {
            throw new VciBaseException(LangBaseUtil.getErrorMsg(e), new String[]{excelName}, e);
        }
        List<WriteExcelData> excelDataList = new ArrayList<>();
        //先处理标题
        Map<Field, ExcelColumn> fieldExcelColumnMap = getExcelColumnAnnotations(doClass);
        Map<String,ExcelColumn> fieldNameExcelColumnMap = new HashMap<>();
        fieldExcelColumnMap.forEach((field,ec)->{
            field.setAccessible(true);
            fieldNameExcelColumnMap.put(field.getName(),ec);
        });
        //todo åŽé¢å¤„理标题的内容
        //获取顺序,如果是继承上级的,就放后面随意处理
        Field fields[] = doClass.getDeclaredFields();
        Set<String> finedFields = new HashSet<>();
        Workbook workbook = new HSSFWorkbook();
        int index = 0;
        for (int i = 0; i < fields.length; i++) {
            //TODO, ç»§æ‰¿çš„还没处理
            Field field = fields[i];
            field.setAccessible(true);
            String fieldName = field.getName();
            if(fieldNameExcelColumnMap.containsKey(fieldName)){
                finedFields.add(fieldName);
                ExcelColumn column = fieldNameExcelColumnMap.get(fieldName);
                if(column.rowIndexColumn()){
                    continue;
                }
                WriteExcelData excelData = new WriteExcelData(0,index,StringUtils.isNotBlank(column.value())?column.value():fieldName);
                if(!column.nullable()){
                    excelData.setFontColor(String.valueOf(HSSFColor.HSSFColorPredefined.RED.getIndex()));
                    excelData.setObj(excelData.getObj() +"*");
                }
                //标题都不让改
                excelData.setReadOnly(true);
                excelData.setCenter(true);
                if(column.width()>0){
                    excelData.setWidth(column.width());
                }
                /**
                 * ä¸‹é¢çš„内容,时间格式,下拉菜单,是否开关
                 */
                List<WriteExcelData> thisRowNextDatas = new ArrayList<>();
                if(downloadTempOption.getDefaultRowSize() ==null || downloadTempOption.getDefaultRowSize()<0){
                    downloadTempOption.setDefaultRowSize(1);
                }
                Integer defaultRowSize = downloadTempOption.getDefaultRowSize();
                for (int j = 0; j < defaultRowSize; j++) {
                    thisRowNextDatas.add(new WriteExcelData(1+j,index,""));
                }
                //看看是否有枚举
                if(StringUtils.isNotBlank(column.enumId()) && processer!=null){
                    Map<String, String> enumMap = processer.wrapperEnumMap(column.enumId(), doClass, field);
                    if(!CollectionUtils.isEmpty(enumMap)){
                        WriteExcelData thisRowNext = thisRowNextDatas.get(0);
                        thisRowNext.setValidation(true);
                        thisRowNext.setRowTo(defaultRowSize);
                        thisRowNext.setColTo(thisRowNext.getCol());
                        thisRowNext.setValidationDataList(enumMap.values().stream().collect(Collectors.toList()));
                    }
                }
                if(field.isAnnotationPresent(VciFieldType.class)){
                    VciFieldType fieldType = field.getDeclaredAnnotation(VciFieldType.class);
                    if(fieldType ==null){
                        fieldType = field.getAnnotation(VciFieldType.class);
                    }
                    if(fieldType!=null){
                        String dateFormat = "";
                        if(VciFieldTypeEnum.VTDateTime.equals(fieldType.value())){
                            dateFormat = VciDateUtil.DateTimeFormat;
                        }else if(VciFieldTypeEnum.VTDate.equals(fieldType.value())){
                            dateFormat = VciDateUtil.DateFormat;
                        }else if(VciFieldTypeEnum.VTTime.equals(fieldType.value())){
                            dateFormat = VciDateUtil.TimeFormat;
                        }
                        if(StringUtils.isNotBlank(dateFormat)){
                            String finalDateFormat = dateFormat;
                            thisRowNextDatas.stream().forEach(thisRowNext->{
                                thisRowNext.setDateFormat(finalDateFormat);
                            });
                        }
                        //boolean类型
                        if(VciFieldTypeEnum.VTBoolean.equals(fieldType.value())){
                            List<String> trueFlase = new ArrayList<>();
                            trueFlase.add("是");
                            trueFlase.add("否");
                            WriteExcelData thisRowNext = thisRowNextDatas.get(0);
                            thisRowNext.setValidation(true);
                            thisRowNext.setRowTo(defaultRowSize);
                            thisRowNext.setColTo(thisRowNext.getCol());
                            thisRowNext.setValidationDataList(trueFlase);
                        }
                        //枚举因为是固定的,所以可以逐个去处理,参照导出的时候,不能把数据导出
                    }
                }
                excelDataList.addAll(thisRowNextDatas);
                excelDataList.add(excelData);
                index++;
            }
        }
        WriteExcelOption excelOption = new WriteExcelOption();
        excelOption.addSheetDataList(StringUtils.isNotBlank(downloadTempOption.getSheetName())?downloadTempOption.getSheetName():"Sheet1",excelDataList);
        writeDataToFile(excelName, excelOption);
        return excelName;
    }
    /**
     * * åˆå¹¶å¤šä¸ªExcelSheet
     * https://blog.csdn.net/lingerlan510/article/details/121943788
     * @param files æ–‡ä»¶å­—符串(file.toString)集合,按顺序进行合并,合并的Excel中Sheet名称不可重复
     * @param excelName åˆå¹¶åŽExcel名称(包含后缀和路径)
     * @Date: 2020/9/18 15:31
     */
    public static void mergeExcel(List<String> files, String excelName) {
        Workbook newExcelCreat = excelName.toLowerCase(Locale.ROOT).endsWith(".xlsx")? new XSSFWorkbook():new HSSFWorkbook();
        // éåŽ†æ¯ä¸ªæºexcel文件,TmpList为源文件的名称集合
        for (int i = 0 ; i < files.size(); i ++) {
            String fromExcelName = files.get(i);
            try (InputStream in = new FileInputStream(fromExcelName)) {
                Workbook fromExcel = null;
                if(fromExcelName.toLowerCase(Locale.ROOT).endsWith(".xlsx")){
                    fromExcel = new XSSFWorkbook(in);
                }else{
                    fromExcel = new HSSFWorkbook(in);
                }
                int length = fromExcel.getNumberOfSheets();
                if (length <= 1) {       //长度为1时
                    Sheet oldSheet = fromExcel.getSheetAt(0);
                    Sheet existSheet = newExcelCreat.getSheet(oldSheet.getSheetName());
                    String newSheetName = oldSheet.getSheetName();
                    if(existSheet!=null){
                        newSheetName += "_" +i;
                    }
                    Sheet newSheet = newExcelCreat.createSheet(newSheetName);
                    copySheet(newExcelCreat, oldSheet, newSheet);
                } else {
                    for (int j = 0; j < length; j++) {// éåŽ†æ¯ä¸ªsheet
                        Sheet oldSheet = fromExcel.getSheetAt(j);
                        Sheet existSheet = newExcelCreat.getSheet(oldSheet.getSheetName());
                        String newSheetName = oldSheet.getSheetName();
                        if(existSheet!=null){
                            newSheetName += "_" +i + "_" + j;
                        }
                        Sheet newSheet = newExcelCreat.createSheet(newSheetName);
                        copySheet(newExcelCreat, oldSheet, newSheet);
                    }
                }
                //名称管理器
                List<? extends Name> allNames = fromExcel.getAllNames();
                if(!CollectionUtils.isEmpty(allNames)){
                    allNames.stream().forEach(name->{
                        Name name1 = newExcelCreat.createName();
                        name1.setNameName(name.getNameName());
                        name1.setRefersToFormula(name.getRefersToFormula());
                    });
                }
            } catch (IOException e) {
                throw new VciBaseException("合并excel出错的了",new String[]{},e);
            }
        }
        // å®šä¹‰æ–°ç”Ÿæˆçš„xlxs表格文件
        String allFileName = excelName;
        try (FileOutputStream fileOut = new FileOutputStream(allFileName)) {
            newExcelCreat.write(fileOut);
            fileOut.flush();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                newExcelCreat.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    /**
     * åˆå¹¶å•元格
     *
     * @param fromSheet æ¥æº
     * @param toSheet ç›®æ ‡
     */
    private static void mergeSheetAllRegion(Sheet fromSheet, Sheet toSheet) {
        int num = fromSheet.getNumMergedRegions();
        CellRangeAddress cellR = null;
        for (int i = 0; i < num; i++) {
            cellR = fromSheet.getMergedRegion(i);
            toSheet.addMergedRegion(cellR);
        }
    }
    /**
     * å¤åˆ¶å•元格
     *
     * @param fromCell æ¥æº
     * @param toCell ç›®æ ‡
     */
    private static void copyCell(Cell fromCell, Cell toCell) {
        copyStyleForCell(fromCell,toCell);
        if (fromCell.getCellComment() != null) {
            toCell.setCellComment(fromCell.getCellComment());
        }
        // ä¸åŒæ•°æ®ç±»åž‹å¤„理
        CellType fromCellType = fromCell.getCellType();
        toCell.setCellType(fromCellType);
        if (fromCellType == CellType.NUMERIC) {
            if (DateUtil.isCellDateFormatted(fromCell)) {
                toCell.setCellValue(fromCell.getDateCellValue());
            } else {
                toCell.setCellValue(fromCell.getNumericCellValue());
            }
        } else if (fromCellType == CellType.STRING) {
            RichTextString value = fromCell.getRichStringCellValue();
            if(value !=null && StringUtils.isNotBlank(value.toString())){
                Font fontAt = fromCell.getSheet().getWorkbook().getFontAt(fromCell.getCellStyle().getFontIndexAsInt());
                value.applyFont(fontAt);
            }
            toCell.setCellValue(value);
        } else if (fromCellType == CellType.BLANK) {
            // nothing21
        } else if (fromCellType == CellType.BOOLEAN) {
            toCell.setCellValue(fromCell.getBooleanCellValue());
        } else if (fromCellType == CellType.ERROR) {
            toCell.setCellErrorValue(fromCell.getErrorCellValue());
        } else if (fromCellType == CellType.FORMULA) {
            toCell.setCellFormula(fromCell.getCellFormula());
        } else {
            // nothing29
        }
    }
    /**
     * è¡Œå¤åˆ¶åŠŸèƒ½
     *
     * @param wb å·¥ä½œè¡¨
     * @param oldRow æ¥æº
     * @param toRow ç›®æ ‡
     */
    private static void copyRow(Workbook wb, Row oldRow, Row toRow) {
        toRow.setHeight(oldRow.getHeight());
        for (Iterator cellIt = oldRow.cellIterator(); cellIt.hasNext(); ) {
            Cell tmpCell = (Cell)cellIt.next();
            Cell newCell = toRow.createCell(tmpCell.getColumnIndex());
            copyCell(tmpCell, newCell);
        }
    }
    /**
     * Sheet复制
     *
     * @param wb å·¥ä½œè¡¨
     * @param fromSheet æ¥æº
     * @param toSheet ç›®æ ‡
     */
    private static void copySheet(Workbook wb, Sheet fromSheet, Sheet toSheet) {
        mergeSheetAllRegion(fromSheet, toSheet);
        // è®¾ç½®åˆ—宽
        int length = fromSheet.getRow(fromSheet.getFirstRowNum()).getLastCellNum();
        for (int i = 0; i <= length; i++) {
            toSheet.setColumnWidth(i, fromSheet.getColumnWidth(i));
        }
        for (Iterator rowIt = fromSheet.rowIterator(); rowIt.hasNext(); ) {
            Row oldRow = (Row) rowIt.next();
            Row newRow = toSheet.createRow(oldRow.getRowNum());
            copyRow(wb, oldRow, newRow);
        }
        //下拉框
        List<? extends DataValidation> dataValidations = fromSheet.getDataValidations();
        if(!CollectionUtils.isEmpty(dataValidations)){
            dataValidations.stream().forEach(dv->{
                toSheet.addValidationData(dv);
            });
        }
    }
    /**
     * å…³é”®å±žæ€§
     */
    public static final String KEY_ATTR_CHAR = "☆";
    /**
     * å¿…输
     */
    public static final String REQUIRED_CHAR = "*";
    /**
     * è¿½åŠ æ•°æ®åˆ°excel中,
     * @param data æ•°æ®ï¼Œå¿…须是po对象
     * @param excelName ç›®æ ‡çš„æ–‡ä»¶åç§°
     * @param excelOption å†™å…¥çš„相关配置
     * @param <T> å¯¹è±¡ç±»åž‹
     */
    public static <T> void appendDataToExcel(Collection<T> data,String excelName,AppendDataExcelOption excelOption){
        if(!CollectionUtils.isEmpty(data)){
            T t1 = data.stream().findFirst().get();
            //获取对象上的列的名称
            Map<Field, ExcelColumn> excelColumnSet = getExcelColumnAnnotations(t1.getClass());
            Map<String/**标题**/,String> excelTitleFieldNameMap =new HashMap<>();
            Set<String> readOnlyFields = new HashSet<>();
            excelColumnSet.forEach((field,excelColumn)->{
                excelTitleFieldNameMap.put(excelColumn.value(),field.getName());
                if(excelColumn.readOnly()){
                    readOnlyFields.add(field.getName());
                }
            });
            //读取内容
            ReadExcelOption readExcelOption = new ReadExcelOption();
            readExcelOption.setSheetName(excelOption.getSheetName());
            readExcelOption.setFristRow(excelOption.getTitleRowIndex()+1);
            List<SheetDataSet> sheetDataSets = ExcelUtil.readDataObjectFromExcel(new File(excelName),SheetDataSet.class,readExcelOption);
            if(!CollectionUtils.isEmpty(sheetDataSets)) {
                SheetDataSet sheetDataSet = sheetDataSets.get(0);
                Map<String/**字段**/, Integer> fieldColumnMap = new HashMap<>();
                List<String> colName = sheetDataSet.getColName();
                if (!CollectionUtils.isEmpty(colName)) {
                    for (int i = 0; i < colName.size(); i++) {
                        String col= colName.get(i).replace(REQUIRED_CHAR,"").replace(KEY_ATTR_CHAR,"");
                        if(excelTitleFieldNameMap.containsKey(col)){
                            fieldColumnMap.put(excelTitleFieldNameMap.get(col),i);
                        }
                    }
                    //我们封装数据
                    List<WriteExcelData> writeExcelDataList = new ArrayList<>();
                    final Integer[] index = {excelOption.getTitleRowIndex()+1};
                    data.stream().forEach(d->{
                        Map<String, String> dataMap = VciBaseUtil.objectToMapString(d);
                        fieldColumnMap.forEach((field,col)->{
                            if(CollectionUtils.isEmpty(excelOption.getWriteFields()) || excelOption.getWriteFields().contains(field)) {
                                WriteExcelData excelData = new WriteExcelData(index[0], col, dataMap.getOrDefault(field, ""));
                                excelData.setReadOnly((excelOption.isReadOnlyFromField() && readOnlyFields.contains(field))
                                || (!CollectionUtils.isEmpty(excelOption.getReadOnlyFields()) && excelOption.getReadOnlyFields().contains(field)));
                                writeExcelDataList.add(excelData);
                            }
                        });
                        index[0]++;
                    });
                    WriteExcelOption writeExcelOption = new WriteExcelOption();
                    writeExcelOption.addSheetDataList(excelOption.getSheetName(),writeExcelDataList);
                    writeExcelOption.setAppend(true);
                    writeDataToFile(excelName,writeExcelOption);
                }
            }
        }
    }
}
Source/plt-web/plt-web-parent/plt-poi/src/main/java/com/vci/starter/poi/util/PoiImportProcesser.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,21 @@
package com.vci.starter.poi.util;
import java.lang.reflect.Field;
/**
 * ä»Žexcel导入的时候,属性的转换器
 * @author weidy
 * @date 2020/5/5
 */
@FunctionalInterface
public interface PoiImportProcesser<T> {
    /***
     * å¯¹ç‰¹æ®Šçš„的类型进行处理.
     * @param value è¯¥å±žæ€§å¯¹åº”的值
     * @param obj  javaBean对象.
     * @param field å±žæ€§å­—段.
     * @return è¿”回javaBean对象.
     */
     void process(Object value, T obj, Field field);
}
Source/plt-web/plt-web-parent/plt-poi/src/main/java/com/vci/starter/poi/util/PoiTemplateProcesser.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,22 @@
package com.vci.starter.poi.util;
import java.lang.reflect.Field;
import java.util.Map;
/**
 * ç”Ÿæˆexcel项目的模板的时候,获取枚举的内容
 * @author weidy
 * @date 2022/09/28
 */
@FunctionalInterface
public interface PoiTemplateProcesser<T> {
    /***
     * èŽ·å–æžšä¸¾çš„å†…å®¹
     * @param enumId æžšä¸¾çš„编号
     * @param tClass  javaBean对象.
     * @param field å±žæ€§å­—段.
     * @return æžšä¸¾çš„内容
     */
    Map<String,String> wrapperEnumMap(String enumId, Class<T> tClass, Field field);
}
Source/plt-web/plt-web-parent/plt-poi/src/main/java/com/vci/starter/word/bo/WordMergeListDataSource.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,181 @@
package com.vci.starter.word.bo;
import com.aspose.words.IMailMergeDataSource;
import com.aspose.words.ref.Ref;
import com.vci.starter.web.util.VciBaseUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.CollectionUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
 * ç”¨äºŽmergeField的表格形式的数据写入对象,因为aspose.word不支持HashMap
 * @author weidy,dangsn
 */
public class WordMergeListDataSource implements IMailMergeDataSource {
    /**
     * æ•°æ®å¯¹è±¡
     */
    private List<Map<String, Object>> dataList;
    /**
     * ç´¢å¼•
     */
    private int index;
    /**
     * è¡¨æ ¼åç§°
     */
    private String tableName;
    /**
     * å­è¡¨æ ¼çš„名称
     */
    private String childTableName;
    /**
     * @param dataList æ•°æ®é›† ï¼Œæ•°æ®é›†ä¸­Map的key,需要跟TableStart,TableEnd包含的名称对应
     * @param tableName ä¸Žæ¨¡æ¿ä¸­çš„TableStart,TableEnd对应
     */
    public WordMergeListDataSource(List<Map<String, Object>> dataList, String tableName) {
        this.dataList = dataList;
        this.tableName = tableName;
        index = -1;
        this.setChildTableName(listChildTableNameFromData(this.dataList));
    }
    /**
     * @param data å•个数据集
     * @param tableName ä¸Žæ¨¡æ¿ä¸­çš„Name对应
     */
    public WordMergeListDataSource(Map<String, Object> data, String tableName) {
        if(this.dataList == null) {
            this.dataList = new ArrayList<Map<String,Object>>();
            this.dataList.add(data);
        }
        this.tableName = tableName;
        index = -1;
        this.setChildTableName(listChildTableNameFromData(this.dataList));
    }
    /**
     * èŽ·å–å­è¡¨åç§°
     * @return å­è¡¨åç§°ï¼Œå¤šä¸ªä¼šä»¥é€—号分隔
     */
    public String getChildTableName() {
        return childTableName;
    }
    /**
     * è®¾ç½®å­è¡¨åç§°
     * @param childTableName å­è¡¨åç§°ï¼Œå¤šä¸ªä»¥é€—号分隔
     */
    public void setChildTableName(String childTableName) {
        this.childTableName = childTableName;
    }
    /**
     * èŽ·å–ç»“æžœé›†æ€»æ•°
     * @return ä¸ªæ•°
     */
    public int getCount() {
        return this.dataList.size();
    }
    /**
     * èŽ·å–æ•°æ®åˆ—è¡¨
     * @return æ•°æ®åˆ—表
     */
    public List<Map<String, Object>> getDataList(){
        return this.dataList;
    }
    /**
     * èŽ·å–è¡¨æ ¼åç§°
     * @return è¡¨æ ¼çš„名称
     */
    public String getTableName() {
        return this.tableName;
    }
    /**
     * èŽ·å–å…·ä½“çš„å€¼ï¼ŒæŽ¥å£æ‰€éœ€è¦çš„
     * @param key å­—段名称
     * @param ref å€¼
     * @return æ˜¯å¦æœ‰å€¼
     * @throws Exception èŽ·å–çš„æ—¶å€™èƒ½å‡ºé”™
     */
    @Override
    public boolean getValue(String key, Ref<Object> ref) throws Exception {
        if(index < 0 || index >= this.getCount()){
            return false;
        }
        if(ref != null){
            ref.set(this.dataList.get(index).get(key));
            return true;
        }else{
            return false;
        }
    }
    /**
     * ä»Žæ•°æ®ä¸­æ‰¾åˆ°list的作为子表的对象
     * @param dataList æ•°æ®åˆ—表
     * @return åŒ…含子表的名称的连接字符串
     */
    private String listChildTableNameFromData(List<Map<String,Object>> dataList ){
        List<String> nextChildNameList = new ArrayList<>();
        if(!CollectionUtils.isEmpty(dataList)){
            dataList.get(0).forEach((k,v) ->{
                if(v != null && v instanceof List){
                    nextChildNameList.add(k);
                }
            });
        }
        return nextChildNameList.stream().collect(Collectors.joining(","));
    }
    /**
     * å®žçŽ°çš„æŽ¥å£
     * @param tableName å­è¡¨çš„名称
     * @return å­è¡¨å¯¹è±¡ï¼Œä¸ç¬¦åˆçš„会返回null
     * @throws Exception èŽ·å–å‡ºé”™çš„æ—¶å€™ä¼šæŠ›å‡ºå¼‚å¸¸
     */
    @Override
    public IMailMergeDataSource getChildDataSource(String tableName) throws Exception {
        if(StringUtils.isNotBlank(getChildTableName())){
            List<String> childrenTableName = VciBaseUtil.str2List(getChildTableName());
            if(childrenTableName.contains(tableName)){
                Object childData = this.dataList.get(index).get(tableName);
                if(childData != null && childData instanceof List) {
                    List<Map<String,Object>> childDataList = (List<Map<String,Object>>)childData;
                    if(!CollectionUtils.isEmpty(childDataList)) {
                        WordMergeListDataSource childDataSource = new WordMergeListDataSource(childDataList, tableName);
                        childDataSource.setChildTableName(listChildTableNameFromData(childDataList));
                        return childDataSource;
                    }
                }
            }
        }
        return null;
    }
    /**
     * å®žçŽ°æŽ¥å£
     * åˆ¤æ–­æ˜¯å¦è¿˜æœ‰ä¸‹ä¸€æ¡è®°å½•
     * @return true移动到下一条
     */
    @Override
    public boolean moveNext() {
        index += 1;
        if(index >= this.getCount()) {
            return false;
        }
        return true;
    }
}
Source/plt-web/plt-web-parent/plt-poi/src/main/java/com/vci/starter/word/bo/WordMergeStartTableDataBO.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,88 @@
package com.vci.starter.word.bo;
import java.util.List;
import java.util.Map;
/**
 * ä½¿ç”¨åŸŸä»£ç çš„æ–¹å¼å¾€word的表格 é‡Œå†™å…¥æ•°æ®ï¼Œéœ€è¦<TableStart:xxx><aa><bb><TableEnd:xxx>这样的方式
 * @author weidy
 * @date 2019/8/13 15:47
 */
public class WordMergeStartTableDataBO implements java.io.Serializable {
    /**
     * ç¦æ­¢ä¿®æ”¹è¿™ä¸ªå€¼
     */
    private static final long serialVersionUID = -5247054966349871652L;
    /**
     * è¡¨åï¼Œéœ€è¦å’Œword的域代码中相对应,比如<TableStart:xxx><aa><bb><TableEnd:xxx> ,表名为xxx
     */
    private String tableName;
    /**
     * åˆ—表数据,其中每一行的数据中的Map的key是域字段名称,一定要注意,如果有子表,子表的那个值不能为null,否则无法判断
     */
    private List<Map<String,Object>> tableDataList;
    /**
     * è¦åˆå¹¶å•元格的列序号,从1开始
     */
    private String mergeColumn ;
    /**
     * èŽ·å–è¡¨æ ¼åç§°
     * @return è¡¨æ ¼åç§°
     */
    public String getTableName() {
        return tableName;
    }
    /**
     * è®¾ç½®è¡¨æ ¼åç§°
     * @param tableName è¡¨æ ¼åç§°
     */
    public void setTableName(String tableName) {
        this.tableName = tableName;
    }
    /**
     * èŽ·å–è¡¨æ ¼çš„æ•°æ®
     * @return èŽ·å–è¡¨æ ¼çš„åç§°
     */
    public List<Map<String, Object>> getTableDataList() {
        return tableDataList;
    }
    /**
     * è®¾ç½®è¡¨æ ¼çš„æ•°æ®
     * @param tableDataList è¡¨æ ¼æ•°æ®
     */
    public void setTableDataList(List<Map<String, Object>> tableDataList) {
        this.tableDataList = tableDataList;
    }
    /**
     * éœ€è¦åˆå¹¶å•元格的列
     * @return åˆ—名称,多个以逗号分隔
     */
    public String getMergeColumn() {
        return mergeColumn;
    }
    /**
     * è®¾ç½®è¦åˆå¹¶çš„单元格
     * @param mergeColumn å•元格列号,从0开始,多个以逗号分隔
     */
    public void setMergeColumn(String mergeColumn) {
        this.mergeColumn = mergeColumn;
    }
    @Override
    public String toString() {
        return "WordSignMergeTableData{" +
                "tableName='" + tableName + '\'' +
                ", tableDataList=" + tableDataList +
                ", mergeColumn='" + mergeColumn + '\'' +
                '}';
    }
}
Source/plt-web/plt-web-parent/plt-poi/src/main/java/com/vci/starter/word/util/WordUtil.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,429 @@
package com.vci.starter.word.util;
import com.aspose.words.*;
import com.vci.starter.web.exception.VciBaseException;
import com.vci.starter.word.bo.WordMergeListDataSource;
import com.vci.starter.word.bo.WordMergeStartTableDataBO;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.CollectionUtils;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.List;
import java.util.*;
/**
 * word操作类
 * @author weidy
 * @date 2020/2/19
 */
public class WordUtil {
    /**
     * æ—¥å¿—
     */
    private static Logger logger = LoggerFactory.getLogger(WordUtil.class);
    /**
     * æç¤ºå‚数为空
     * @param s ç›¸å…³çš„参数,两两组合,第一个为参数的对象,第二个为显示的名称
     * @throws VciBaseException å¦‚果参数为空的时候会抛出异常
     */
    public static void alertNotNull(Object... s) throws VciBaseException {
        if(s!=null && s.length>0){
            for(int i = 0 ; i < s.length ; i ++){
                Object obj = s[i];
                if(obj==null || StringUtils.isBlank(obj.toString())){
                    String param = "";
                    try{
                        i++;
                        param = s[i].toString();
                    }catch(Exception e){
                    }
                    throw new VciBaseException("参数[{0}]不能为空",new String[]{param});
                }
            }
        }
    }
    /**
     * å¸¦é€—号的字符串转为list
     * @param s å­—符串
     * @return å­—符串列表
     */
    public static List<String> str2List(String s){
        if (isNull(s)) {
            return null;
        } else {
            List<String> l = new ArrayList<String>();
            Collections.addAll(l,removeComma(s).split(","));
            return l;
        }
    }
    /**
     * åŽ»é™¤æœ€å‰é¢çš„é€—å·ï¼ŒåŽ»é™¤åŽé¢çš„é€—å·
     * @param s å­—符串
     * @return åŽ»é™¤æœ«å°¾é€—å·
     */
    public static String removeComma(String s){
        if(s == null || s.trim().length() == 0) {
            return s;
        }
        else{
            if(s.startsWith(",")) {
                s = s.substring(1, s.length());
            }
            if(s.endsWith(",")) {
                s = s.substring(0, s.length() - 1);
            }
            return s;
        }
    }
    /**
     * åˆ¤æ–­å­—符串是不是空,不判断trim
     * @param o å­—符串
     * @return true表示空
     */
    public static boolean isNull(String o){
        return StringUtils.isEmpty(o);
    }
    /**
     * å¾€word写入表格数据,这种是使用startTable的方式,不会自动拷贝格式
     * @param fileName æ–‡ä»¶åï¼Œå¿…须是word文件
     * @param tableDataBOList è¦å†™å…¥åˆ°æ–‡ä»¶çš„信息
     * @throws FileNotFoundException æ–‡ä»¶ä¸å­˜åœ¨çš„æ—¶å€™ä¼šæŠ›å‡ºå¼‚常
     * @throws VciBaseException å†™å…¥æ•°æ®å‡ºé”™æ—¶ä¼šæŠ›å‡ºå¼‚常
     */
    public static void setTableDataToWord(String fileName, List<WordMergeStartTableDataBO> tableDataBOList) throws FileNotFoundException, VciBaseException{
        alertNotNull(fileName,"word的文件名称");
        setTableDataToWord(new File(fileName),tableDataBOList);
    }
    /**
     * å¾€word写入表格数据,这种是使用startTable的方式,不会自动拷贝格式
     * @param file æ–‡ä»¶,必须是word文件
     * @param tableDataBOList è¦å†™å…¥åˆ°æ–‡ä»¶çš„信息
     * @throws FileNotFoundException æ–‡ä»¶ä¸å­˜åœ¨çš„æ—¶å€™ä¼šæŠ›å‡ºå¼‚常
     * @throws VciBaseException å†™å…¥æ•°æ®å‡ºé”™æ—¶ä¼šæŠ›å‡ºå¼‚常
     */
    public static void setTableDataToWord(File file, List<WordMergeStartTableDataBO> tableDataBOList) throws FileNotFoundException, VciBaseException{
        alertNotNull(file,"word文件");
        if(!file.exists()){
            throw new FileNotFoundException(file.getName());
        }
        InputStream in = null;
        Document document = null;
        try{
            in = new FileInputStream(file);
            document = new Document(in);
        }catch (Exception e){
            IOUtils.closeQuietly(in);
            //不能在finally里关闭,因为后面还需要用
            throw new VciBaseException("初始化word文档对象的时候出现了错误,{0}",new String[]{file.getAbsolutePath()},e);
        }
        try {
            setTableDataToWord(document, tableDataBOList);
        }catch (VciBaseException e){
            throw e;
        }catch (Throwable e){
            throw new VciBaseException("向word里写入tableStart类型的域字段的时候出错,{0}",new String[]{file.getAbsolutePath()},e);
        }finally {
            IOUtils.closeQuietly(in);
        }
        try{
            document.save(file.getAbsolutePath());
        }catch (Exception e) {
            throw new VciBaseException("将word的内容返填到文件中出现了错误,{0}",new String[]{file.getAbsolutePath()},e);
        }
    }
    /**
     * æŠŠä¿¡æ¯å†™å…¥word中的域字段中,域字段会保留(但是目前打印会依然显示域代码)
     * @param fileName æ–‡ä»¶å
     * @param dataMap è¦å†™å…¥çš„æ•°æ®
     * @throws FileNotFoundException æ–‡ä»¶ä¸å­˜åœ¨æ—¶æŠ›å‡ºå¼‚常
     * @throws VciBaseException å†™å…¥å‡ºé”™çš„æ—¶å€™æŠ›å‡ºæ­¤å¼‚常
     */
    public static void setFieldDataToWord(String fileName,Map<String,String> dataMap) throws FileNotFoundException, VciBaseException{
        alertNotNull(fileName,"word的文件名称");
        setFieldDataToWord(new File(fileName), dataMap,true);
    }
    /**
     * æŠŠä¿¡æ¯å†™å…¥word中的域字段中,域字段会保留(但是目前打印会依然显示域代码)
     * @param file æ–‡ä»¶
     * @param dataMap è¦å†™å…¥çš„æ•°æ®
     * @throws FileNotFoundException æ–‡ä»¶ä¸å­˜åœ¨æ—¶æŠ›å‡ºå¼‚常
     * @throws VciBaseException å†™å…¥å‡ºé”™çš„æ—¶å€™æŠ›å‡ºæ­¤å¼‚常
     */
    public static void setFieldDataToWord(File file,Map<String,String> dataMap) throws FileNotFoundException, VciBaseException{
        setFieldDataToWord(file, dataMap,true);
    }
    /**
     * æŠŠä¿¡æ¯å†™å…¥word中的域字段中,域字段会保留(但是目前打印会依然显示域代码)
     * @param file æ–‡ä»¶
     * @param dataMap è¦å†™å…¥çš„æ•°æ®
     * @param retainFieldCode true会保留域字段(但是目前打印会依然显示域代码),false不会保留域字段,打印无问题
     * @throws FileNotFoundException æ–‡ä»¶ä¸å­˜åœ¨æ—¶æŠ›å‡ºå¼‚常
     * @throws VciBaseException å†™å…¥å‡ºé”™çš„æ—¶å€™æŠ›å‡ºæ­¤å¼‚常
     */
    public static void setFieldDataToWord(File file,Map<String,String> dataMap,boolean retainFieldCode ) throws FileNotFoundException, VciBaseException{
        alertNotNull(file,"word文件");
        if(!file.exists()){
            throw new FileNotFoundException(file.getName());
        }
        InputStream in = null;
        Document document = null;
        try{
            in = new FileInputStream(file);
            document = new Document(in);
        }catch (Exception e){
            IOUtils.closeQuietly(in);
            //不能在finally里关闭,因为后面还需要用
            throw new VciBaseException("初始化word文档对象的时候出现了错误,{0}",new String[]{file.getAbsolutePath()},e);
        }
        try {
            if(retainFieldCode) {
                mergeMapForField(document, dataMap);
            }else{
                mergeMapForFieldUnFormate(document, dataMap);
            }
        }catch (VciBaseException e){
            throw e;
        }catch (Throwable e){
            throw new VciBaseException("向word里的域字段写入信息的时候出错,{0}",new String[]{file.getAbsolutePath()},e);
        }finally {
            IOUtils.closeQuietly(in);
        }
        try{
            document.save(file.getAbsolutePath());
        }catch (Exception e) {
            throw new VciBaseException("将word的内容返填到文件中出现了错误,{0}",new String[]{file.getAbsolutePath()},e);
        }
    }
    /**
     * å¾€word写入表格数据,这种是使用startTable的方式,不会自动拷贝格式
     * @param document word文档对象
     * @param tableDataBOList è¦å†™å…¥åˆ°æ–‡ä»¶çš„信息
     * @throws FileNotFoundException æ–‡ä»¶ä¸å­˜åœ¨çš„æ—¶å€™ä¼šæŠ›å‡ºå¼‚常
     * @throws VciBaseException å†™å…¥æ•°æ®å‡ºé”™æ—¶ä¼šæŠ›å‡ºå¼‚常
     */
    public static void setTableDataToWord(Document document, List<WordMergeStartTableDataBO> tableDataBOList) throws  VciBaseException{
        alertNotNull(document,"word文档对象");
        if(!CollectionUtils.isEmpty(tableDataBOList)){
            try {
                mergeBeanListUnFormate(document,tableDataBOList);
            } catch (Exception e) {
                logger.error("向word里写入tableStart类型的域字段的时候出错",e);
                throw new VciBaseException("向word里写入tableStart类型的域字段的时候出错,{0}" ,new String[]{e.getLocalizedMessage()},e);
            }
        }
    }
    /**
     * å†™å…¥è¡¨æ ¼æ•°æ®ï¼Œæ–°çš„æ•°æ®è¡Œçš„æ ¼å¼ä¸ä¼šè‡ªåŠ¨ç»§æ‰¿
     * @param doc word文档
     * @param wordSignMergeTableDataList è¦å†™å…¥çš„æ•°æ®
     * @throws Exception å†™å…¥å¤±è´¥æˆ–者表格不存在的时候会抛出异常
     */
    public static  void mergeBeanListUnFormate(Document doc, List<WordMergeStartTableDataBO> wordSignMergeTableDataList) throws Exception {
        if(!CollectionUtils.isEmpty(wordSignMergeTableDataList)) {
            for (WordMergeStartTableDataBO tableData : wordSignMergeTableDataList) {
                boolean needMergeColumn = false;
                String tableName = tableData.getTableName();
                Table thisTable = null;
                boolean finedField = false;
                int startRowIndex = -1;
                Map<String,Integer> mergeColumnNameIndexMap = new HashMap<String, Integer>();
                List<String> mergeColumnList = str2List(tableData.getMergeColumn());
                if (StringUtils.isNotBlank(tableData.getMergeColumn()) && tableData.getTableDataList().size()> 1){
                    needMergeColumn = true;
                    //找到所有的表格中的单元格,看是否有这个表格的tableStart标记
                    NodeCollection tableNodes = doc.getChildNodes(NodeType.TABLE, true);
                    Iterator tableIt = tableNodes.iterator();
                    while (tableIt.hasNext()) {
                        Table table = (Table) tableIt.next();
                        int rowCount = table.getRows().getCount();
                        if (rowCount > 0) {
                            //说明这个表格有行
                            RowCollection rowCollection = table.getRows();
                            for (int i = 0; i < rowCount; i++) {
                                Row row = rowCollection.get(i);
                                CellCollection cellCollection = row.getCells();
                                if (cellCollection != null) {
                                    for (int z = 0; z < cellCollection.getCount(); z++) {
                                        Cell cell = cellCollection.get(z);
                                        NodeCollection mergeCollection = cell.getChildNodes(NodeType.FIELD_START, true);
                                        Iterator fieldNodes = mergeCollection.iterator();
                                        if (mergeCollection.getCount() > 0) {
                                            while (fieldNodes.hasNext()) {
                                                FieldStart fdStart = (FieldStart) fieldNodes.next();
                                                if (fdStart.getFieldType() == FieldType.FIELD_MERGE_FIELD) {
                                                    FieldMergeField fdMerge = (FieldMergeField) fdStart.getField();
                                                    String fieldName = fdMerge.getFieldName();
                                                    if (fieldName.equalsIgnoreCase("TableStart:" + tableName)) {
                                                        thisTable = table;
                                                        startRowIndex = i;
                                                    }
                                                    if(mergeColumnList.contains(fieldName)){
                                                        mergeColumnNameIndexMap.put(fieldName,z);
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                            if(thisTable != null){
                                finedField = true;
                                break;
                            }
                        }
                        if(finedField){
                            break;
                        }
                    }
                }
                WordMergeListDataSource dataSource = new WordMergeListDataSource(tableData.getTableDataList(),tableName);
                doc.getMailMerge().executeWithRegions(dataSource);
                //处理了完数据后,有可能需要将行合并单元格
                if (needMergeColumn && thisTable != null && mergeColumnNameIndexMap.size() > 0) {
                    List<Map<String, Object>> thisTableData = dataSource.getDataList();
                    for (String mergeColumnName : mergeColumnList) {
                        //找所有的数据,记录相同行的数据
                        if(mergeColumnNameIndexMap.containsKey(mergeColumnName)) {
                            int columnIndex = mergeColumnNameIndexMap.get(mergeColumnName) + 1;
                            Map<Integer, Integer> mergeRowMap = new HashMap<Integer, Integer>();
                            Object lastRowValue = "";
                            int lastRowIndex = 0;
                            for (int i = 0; i < thisTableData.size(); i++) {
                                Map<String, Object> thisRowData = thisTableData.get(i);
                                Object thisCellValue = thisRowData.get(mergeColumnName);
                                if (thisCellValue == null) {
                                    thisCellValue = "";
                                }
                                if (i == 0) {
                                    lastRowValue = thisCellValue;
                                    lastRowIndex = startRowIndex;
                                    //等于起始行,1
                                } else if (i != thisTableData.size() - 1) {
                                    if (!thisCellValue.toString().equalsIgnoreCase(lastRowValue.toString())) {
                                        //说明和上一行不一样了
                                        mergeRowMap.put(lastRowIndex, i+startRowIndex-1);
                                        lastRowValue = thisCellValue;
                                        lastRowIndex = startRowIndex + i;
                                    }
                                } else {
                                    if (!thisCellValue.toString().equalsIgnoreCase(lastRowValue.toString())) {
                                        //说明和上一行不一样了
                                        mergeRowMap.put(lastRowIndex, i+startRowIndex-1);
                                        lastRowValue = thisCellValue;
                                        lastRowIndex = startRowIndex + i;
                                        // mergeRowMap.put(startRowIndex +i, startRowIndex +i);
                                    }else{
                                        mergeRowMap.put(lastRowIndex, startRowIndex +i);
                                        lastRowValue = thisCellValue;
                                        lastRowIndex = startRowIndex + i;
                                    }
                                }
                            }
                            //找到了所有的相同的内容,肯定会有值
                            doMerge(thisTable,mergeRowMap,columnIndex);
                        }
                    }
                }
            }
        }
    }
    /**
     * æ‰§è¡Œåˆå¹¶å•元格
     * @param thisTable è¡¨æ ¼å¯¹è±¡
     * @param mergeRowMap è¦åˆå¹¶çš„行,key是其实行,value是结束行,从0开始
     * @param columnIndex åˆ—的需要,从0开始
     */
    private static void doMerge(Table thisTable, Map<Integer, Integer> mergeRowMap, int columnIndex){
        if (mergeRowMap.size() > 0) {
            for (Integer startRowIndex : mergeRowMap.keySet()) {
                Integer endRowIndex = mergeRowMap.get(startRowIndex);
                for (int x = startRowIndex; x <= endRowIndex; x++) {
                    //开始的行设置为FIRST,其他的行设置为PREVIOUS
                    if (x == startRowIndex) {
                        Cell cell = thisTable.getRows().get(x).getCells().get(columnIndex - 1);
                        cell.getCellFormat().setVerticalMerge(CellMerge.FIRST);
                    } else {
                        Cell cell = thisTable.getRows().get(x).getCells().get(columnIndex - 1);
                        cell.getCellFormat().setVerticalMerge(CellMerge.PREVIOUS);
                    }
                }
            }
        }
    }
    /**
     * è®¾ç½®åŸŸå­—段的值,这个域字段修改后域代码还在,不能切换域代码,否则数据丢失(注意,目前发现打印的时候还是显示域代码)
     * @param doc word文档
     * @param dataMap æ•°æ®æ˜ å°„
     * @throws VciBaseException å†™å…¥å¤±è´¥æ—¶ä¼šæŠ›å‡ºå¼‚常
     */
    public static void mergeMapForField(Document doc, Map<String, String> dataMap) throws VciBaseException{
        NodeCollection fieldStartNodes=doc.getChildNodes(NodeType.FIELD_START,true);
        Iterator fieldNodes=fieldStartNodes.iterator();
        while(fieldNodes.hasNext()) {
            FieldStart fdStart = (FieldStart) fieldNodes.next();
            if (fdStart.getFieldType() == FieldType.FIELD_MERGE_FIELD) {
                FieldMergeField fdMerge = (FieldMergeField)fdStart.getField();
                String fieldName = fdMerge.getFieldName();
                if (dataMap.containsKey(fieldName)) {
                    try {
                        fdMerge.setResult(dataMap.get(fieldName));
                    } catch (Exception e) {
                        throw new VciBaseException("写域字段的内容出错,{0}",new String[]{fieldName});
                    }
                }
            }
        }
    }
    /**
     * è®¾ç½®åŸŸå­—段的值,这个域字段修改后域代码不会再存在,也就是不能再次使用
     * @param doc word文档
     * @param dataMap æ•°æ®æ˜ å°„
     * @throws VciBaseException å†™å…¥å¤±è´¥æ—¶ä¼šæŠ›å‡ºå¼‚常
     */
    public static void mergeMapForFieldUnFormate(Document doc, Map<String, String> dataMap) throws VciBaseException{
        String[] fieldName = new String[dataMap.size()];
        Object[] values = new Object[dataMap.size()];
        int i = 0 ;
        for(String field:dataMap.keySet()){
            fieldName[i] = field;
            values[i] = dataMap.get(field);
            i++;
        }
        try {
            doc.getMailMerge().execute(fieldName,values);
        } catch (Exception e) {
            throw new VciBaseException("写域字段的内容出错",new String[]{},e);
        }
    }
}
Source/plt-web/plt-web-parent/plt-starter/pom.xml
@@ -136,20 +136,9 @@
            <version>${plt.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.1</version>
        </dependency>
        <!--操作xml需要-->
        <dependency>
            <groupId>dom4j</groupId>
            <artifactId>dom4j</artifactId>
            <version>1.6.1</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.83</version>
        </dependency>
        <dependency>
            <groupId>org.freemarker</groupId>
@@ -162,55 +151,10 @@
            <version>4.8</version>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-api</artifactId>
            <version>2.12.4</version>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-core</artifactId>
            <version>2.12.4</version>
        </dependency>
        <dependency>
            <groupId>javax.mail</groupId>
            <artifactId>mail</artifactId>
            <version>1.4</version>
        </dependency>
        <dependency>
            <groupId>org.jbpm</groupId>
            <artifactId>jbpm-core</artifactId>
            <version>4.3.2</version>
        </dependency>
        <!--commons的几个组件-->
        <dependency>
            <groupId>commons-net</groupId>
            <artifactId>commons-net</artifactId>
            <version>1.4.1</version>
        </dependency>
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.5</version>
        </dependency>
        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.3.1</version>
        </dependency>
        <!---zip压缩 æ›¿æ¢antzip-->
        <dependency>
            <groupId>net.lingala.zip4j</groupId>
            <artifactId>zip4j</artifactId>
            <version>1.3.2</version>
        </dependency>
        <!--zip压缩所需要的jar-->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-compress</artifactId>
            <version>1.9</version>
        </dependency>
    </dependencies>
</project>
Source/plt-web/plt-web-parent/plt-web-base/pom.xml
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,51 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.vci</groupId>
        <artifactId>plt-web-parent</artifactId>
        <version>2024.1-SNAPSHOT</version>
    </parent>
    <artifactId>plt-web-base</artifactId>
    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <!--单独使用feign-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <!--由于feign自带的Http客户端实现是HttpURLConnection,所有换成okHttp用于支持连接池 -->
        <!-- https://mvnrepository.com/artifact/io.github.openfeign/feign-okhttp -->
        <dependency>
            <groupId>io.github.openfeign</groupId>
            <artifactId>feign-okhttp</artifactId>
            <version>10.2.3</version>
        </dependency>
        <dependency>
            <groupId>org.freemarker</groupId>
            <artifactId>freemarker</artifactId>
            <version>2.3.23</version>
        </dependency>
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.4.3</version>
        </dependency>
    </dependencies>
</project>
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/common/log/VciComponentLogAspect.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,212 @@
package com.vci.starter.common.log;
import com.vci.starter.web.annotation.log.VciUnLog;
import com.vci.starter.common.log.autoconfigure.VciAutoLogConfigure;
import com.vci.starter.web.enumpck.LogLevelEnum;
import com.vci.starter.web.util.LangBaseUtil;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.DefaultParameterNameDiscoverer;
import org.springframework.core.ParameterNameDiscoverer;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Collection;
import java.util.Map;
/**
 * æ—¥å¿—记录切面
 * @author weidy
 * @date 2020/4/10
 */
@Aspect
@Component
public class VciComponentLogAspect {
    /**
     * å½“前类的日志输出
     */
    private Logger logger = LoggerFactory.getLogger(getClass());
    /**
     * æ—¥å¿—的配置
     */
    @Autowired
    private VciAutoLogConfigure logConfigure;
    /**
     * æ‰€æœ‰çš„controller,component,service都监控
     */
    @Pointcut("execution(public * com.vci..*.*(..)) && (@target(org.springframework.web.bind.annotation.RestController) " +
            "|| @target(org.springframework.stereotype.Controller) || @target(org.springframework.stereotype.Service)" +
            "|| @target(org.springframework.stereotype.Component)) && !(@target(com.vci.starter.web.annotation.log.VciUnLog)) ")
    public void vciComponentLog(){}
    /**
     * åœ¨åˆ‡å…¥ç‚¹çš„æ–¹æ³•执行之前,获取方法的参数
     * @param joinPoint åˆ‡å…¥ç‚¹
     */
    @Before("vciComponentLog()")
    public void enterMethodLog(JoinPoint joinPoint){
        Method method = getMethod(joinPoint);
        try {
            if (logConfigure.isShowLog() && !checkIsUnLog(method)) {
                //说明要记录日志
                Logger beforeLogger = LoggerFactory.getLogger(joinPoint.getTarget().getClass());
                //要把参数打印出来
                ParameterNameDiscoverer pnd = new DefaultParameterNameDiscoverer();
                if (method != null) {
                    String[] parameterNames = pnd.getParameterNames(method);
                    Object[] args = joinPoint.getArgs();
                    String logMsg = "调用了" + joinPoint.getSignature().getName() + "方法";
                    if (parameterNames != null && parameterNames.length > 0) {
                        logMsg += ",参数为空";
                    } else {
                        for (int i = 0; i < parameterNames.length; i++) {
                            logMsg += parameterNames[i] + "=" + getParamString(args[i]) + ";";
                        }
                    }
                    if (LogLevelEnum.INFO.name().equalsIgnoreCase(logConfigure.getVciLogLevel()) && beforeLogger.isInfoEnabled()) {
                        beforeLogger.info(logMsg);
                    }
                    if (LogLevelEnum.DEBUG.name().equalsIgnoreCase(logConfigure.getVciLogLevel()) && beforeLogger.isDebugEnabled()) {
                        beforeLogger.debug(logMsg);
                    }
                } else {
                    if (logger.isInfoEnabled()) {
                        logger.info(joinPoint.getTarget().getClass() + "." + joinPoint.getSignature().getName() + "这个方法没有找到Method对象,此处程序可能有问题");
                    }
                }
            }
        }catch (Throwable e1){
            //日志错误了不要影响别的
        }
    }
    /**
     * åœ¨æŠ›å‡ºå¼‚常时记录
     * @param joinPoint åˆ‡å…¥ç‚¹
     * @param e å¼‚常的变量
     */
    @AfterThrowing(pointcut = "vciComponentLog()",throwing = "e")
    public void exceptionMethodLog(JoinPoint joinPoint,Throwable e){
        Method method = getMethod(joinPoint);
        try {
            if (logConfigure.isShowLog() && !checkIsUnLog(method)) {
                //说明要记录日志
                Logger exceptionLogger = LoggerFactory.getLogger(joinPoint.getTarget().getClass());
                //要把异常打印出来
                if (exceptionLogger.isErrorEnabled()) {
                    exceptionLogger.error("调用了" + joinPoint.getSignature().getName() + "方法,出现了错误:" + LangBaseUtil.getErrorMsg(e), e);
                }
            }
        }catch (Throwable e1){
            //日志错误了不要影响别的
        }
    }
    /**
     * åœ¨è°ƒç”¨æˆåŠŸåŽæ—¶è®°å½•
     * @param joinPoint åˆ‡å…¥ç‚¹
     * @param returnVal è¿”回值
     */
    @AfterReturning(pointcut = "vciComponentLog()",returning = "returnVal")
    public void returnMethodLog(JoinPoint joinPoint,Object returnVal){
        Method method = getMethod(joinPoint);
        try {
            if (logConfigure.isShowLog() && !checkIsUnLog(method)) {
                //说明要记录日志
                Logger returnLogger = LoggerFactory.getLogger(joinPoint.getTarget().getClass());
                //把返回结果打印出来
                String logMsg = "调用" + joinPoint.getSignature().getName() + "方法成功," + getParamString(returnVal);
                if (LogLevelEnum.INFO.name().equalsIgnoreCase(logConfigure.getVciLogLevel()) && returnLogger.isInfoEnabled()) {
                    returnLogger.info(logMsg);
                }
                if (LogLevelEnum.DEBUG.name().equalsIgnoreCase(logConfigure.getVciLogLevel()) && returnLogger.isDebugEnabled()) {
                    returnLogger.debug(logMsg);
                }
            }
        }catch (Throwable e){
            //日志错误了不要影响别的
        }
    }
    /**
     * èŽ·å–è¢«è°ƒç”¨çš„æ–¹æ³•
     * @param joinPoint åˆ‡å…¥ç‚¹
     * @return è°ƒç”¨çš„æ–¹æ³•
     */
    public Method getMethod(JoinPoint joinPoint){
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        return method;
    }
    /**
     * èŽ·å–å‚æ•°çš„å†…å®¹å­—ç¬¦ä¸²
     * @param obj å‚数对象
     * @return å‚数转成字符串
     */
    public String getParamString(Object obj){
        if(obj == null){
            return "没有返回值";
        }else{
            //看看是否集合
            if(obj instanceof Collection){
                final String[] paStr = {"["};
                ((Collection)obj).stream().limit(10).forEach(s->{
                    if(s!=null) {
                        paStr[0] += s.toString() + ",";
                    }else{
                        paStr[0] += "null,";
                    }
                });
                return paStr[0]  + "]";
            }else if(obj instanceof Map){
                final String[] paStr = {"{"};
                ((Map)obj).forEach((k,v)->{
                    if(v!=null) {
                        paStr[0] += k + ":" + v.toString() + ",";
                    }else{
                        paStr[0] += k + ":null,";
                    }
                });
                return paStr[0]  + "}";
            }else if(obj.getClass().isArray()){
                //说明是数组
                final String[] paStr = {"["};
                Arrays.stream(((Object[]) obj)).limit(10).forEach( s->{
                    if(s instanceof String) {
                        if (s != null ) {
                            paStr[0] += s.toString() + ",";
                        } else {
                            paStr[0] += "null,";
                        }
                    }
                });
                return paStr[0]  + "]";
            }else {
                return obj.toString();
            }
        }
    }
    /**
     * èŽ·å–æ–¹æ³•æ˜¯å¦è®°å½•æ—¥å¿—
     * @param method è¢«è°ƒç”¨çš„æ–¹æ³•
     * @return true è¡¨ç¤ºä¸è®°å½•日志
     */
    private boolean checkIsUnLog(Method method){
        //如果整个类添加了vciUnLog注解时,不会进入到这个方法中
        if(method != null && method.isAnnotationPresent(VciUnLog.class)){
            return true;
        }
        return false;
    }
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/common/log/autoconfigure/VciAutoLogConfigure.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,48 @@
package com.vci.starter.common.log.autoconfigure;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
/**
 * æ—¥å¿—自动读取的配置
 * @author weidy
 * @date 2020/4/14
 */
@Configuration
@ConfigurationProperties(prefix = "logging")
public class VciAutoLogConfigure {
    /**
     * æ˜¯å¦è‡ªåŠ¨è®°å½•è°ƒç”¨æ—¥å¿—
     */
    private boolean showLog = false;
    /**
     * è‡ªåŠ¨è®°å½•çš„æ—¥å¿—çš„çº§åˆ«ï¼Œåªèƒ½æ˜¯Info或者debug
     */
    private String vciLogLevel = "info";
    public boolean isShowLog() {
        return showLog;
    }
    public void setShowLog(boolean showLog) {
        this.showLog = showLog;
    }
    public String getVciLogLevel() {
        return vciLogLevel;
    }
    public void setVciLogLevel(String vciLogLevel) {
        this.vciLogLevel = vciLogLevel;
    }
    @Override
    public String toString() {
        return "VciAutoLogConfigure{" +
                "showLog=" + showLog +
                ", vciLogLevel='" + vciLogLevel + '\'' +
                '}';
    }
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/revision/bo/TreeWrapperOptions.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,194 @@
package com.vci.starter.revision.bo;
import com.vci.starter.web.pagemodel.TreeQueryObject;
/**
 * è½¬æ¢ä¸ºæ ‘型数据时的配置信息
 * @author weidy
 * @date 2020/4/22
 */
public class TreeWrapperOptions implements java.io.Serializable{
    /**
     * è¯·å‹¿ä¿®æ”¹è¿™ä¸ªå€¼
     */
    private static final long serialVersionUID = 3183500138266494574L;
    /**
     * æ˜¾ç¤ºæ–‡æœ¬æ‰€ä½¿ç”¨çš„属性
     */
    private String textFieldName = "name";
    /**
     * å¤šä¸ªæ˜¾ç¤ºæ–‡æœ¬çš„属性时的分隔符(最终显示的值的分隔符)
     */
    private String textValueSep = " ";
    /**
     * ä¸Šçº§æ•°æ®çš„属性名称
     */
    private String parentFieldName;
    /**
     * ä¸»é”®çš„属性名称
     */
    private String oidFieldName = "oid";
    /**
     * å¤šä¸ªå€¼å±žæ€§æ—¶çš„分隔符
     */
    private String oidValueSep = ",";
    /**
     * æ˜¯å¦æŸ¥è¯¢æ‰€æœ‰çš„属性
     */
    private boolean allAttributes = true;
    /**
     * ä¸Šçº§çš„主键的值
     */
    private String parentOid;
    /**
     * æ˜¯å¦å¤šé€‰
     */
    private boolean multipleSelect = false;
    /**
     * æ˜¯å¦æ˜¾ç¤ºå¤é€‰æ¡†
     */
    private boolean showCheckBox = false;
    /**
     * æž„造函数
     */
    public TreeWrapperOptions(){
    }
    /**
     * å¸¸ç”¨çš„æž„造函数,只设置上级属性的名称
     * @param parentFieldName ä¸Šçº§å±žæ€§çš„名称
     */
    public TreeWrapperOptions(String parentFieldName){
        this.parentFieldName = parentFieldName;
    }
    /**
     * å¸¸ç”¨çš„æž„造函数,设置显示text和上级属性的名称
     * @param textFieldName æ˜¾ç¤ºæ–‡æœ¬å±žæ€§çš„名称
     * @param parentFieldName ä¸Šçº§å±žæ€§çš„名称
     */
    public TreeWrapperOptions(String textFieldName,String parentFieldName){
        this.textFieldName = textFieldName;
        this.parentFieldName = parentFieldName;
    }
    /**
     * å¸¸ç”¨çš„æž„造函数,设置显示text、上级属性的名称、
     * @param textFieldName æ˜¾ç¤ºæ–‡æœ¬å±žæ€§çš„名称
     * @param parentFieldName ä¸Šçº§å±žæ€§çš„名称
     * @param parentOid ä¸Šçº§ä¸»é”®
     */
    public TreeWrapperOptions(String textFieldName,String parentFieldName,String parentOid){
        this.textFieldName = textFieldName;
        this.parentFieldName = parentFieldName;
        this.parentOid = parentOid;
    }
    /**
     * ä»Žæ ‘形查询对象上拷贝
     * @param treeQueryObject æ ‘形查询对象
     */
    public void copyFromTreeQuery(TreeQueryObject treeQueryObject){
        if(treeQueryObject != null){
            this.parentOid = treeQueryObject.getParentOid();
            this.multipleSelect = treeQueryObject.isMultipleSelect();
            this.showCheckBox = treeQueryObject.isShowCheckBox();
        }
    }
    public String getTextFieldName() {
        return textFieldName;
    }
    public void setTextFieldName(String textFieldName) {
        this.textFieldName = textFieldName;
    }
    public String getParentFieldName() {
        return parentFieldName;
    }
    public void setParentFieldName(String parentFieldName) {
        this.parentFieldName = parentFieldName;
    }
    public String getOidFieldName() {
        return oidFieldName;
    }
    public void setOidFieldName(String oidFieldName) {
        this.oidFieldName = oidFieldName;
    }
    public boolean isAllAttributes() {
        return allAttributes;
    }
    public void setAllAttributes(boolean allAttributes) {
        this.allAttributes = allAttributes;
    }
    public String getParentOid() {
        return parentOid;
    }
    public void setParentOid(String parentOid) {
        this.parentOid = parentOid;
    }
    public boolean isMultipleSelect() {
        return multipleSelect;
    }
    public void setMultipleSelect(boolean multipleSelect) {
        this.multipleSelect = multipleSelect;
    }
    public boolean isShowCheckBox() {
        return showCheckBox;
    }
    public void setShowCheckBox(boolean showCheckBox) {
        this.showCheckBox = showCheckBox;
    }
    public String getTextValueSep() {
        return textValueSep;
    }
    public void setTextValueSep(String textValueSep) {
        this.textValueSep = textValueSep;
    }
    public String getOidValueSep() {
        return oidValueSep;
    }
    public void setOidValueSep(String oidValueSep) {
        this.oidValueSep = oidValueSep;
    }
    @Override
    public String toString() {
        return "TreeWrapperOptions{" +
                "textFieldName='" + textFieldName + '\'' +
                ", textValueSep='" + textValueSep + '\'' +
                ", parentFieldName='" + parentFieldName + '\'' +
                ", oidFieldName='" + oidFieldName + '\'' +
                ", oidValueSep='" + oidValueSep + '\'' +
                ", allAttributes=" + allAttributes +
                ", parentOid='" + parentOid + '\'' +
                ", multipleSelect=" + multipleSelect +
                ", showCheckBox=" + showCheckBox +
                '}';
    }
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/revision/model/ReleasedObjDO.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,76 @@
package com.vci.starter.revision.model;
/**
 * å·²å‘布的数据
 * ä»…在有版本管理的业务类型才存储
 * @author weidy
 * @date 2020/3/17
 */
public class ReleasedObjDO implements java.io.Serializable{
    /**
     * ç¦æ­¢ä¿®æ”¹è¿™ä¸ªå€¼
     */
    private static final long serialVersionUID = -7258896338253286905L;
    /**
     * ä¸»é”®
     */
    private String oid;
    /**
     * ç‰ˆæœ¬çš„主键
     */
    private String revisionOid;
    /**
     * å¯¹è±¡çš„主键
     */
    private String nameOid;
    /**
     * ä¸šåŠ¡ç±»åž‹
     */
    private String btmName;
    public String getOid() {
        return oid;
    }
    public void setOid(String oid) {
        this.oid = oid;
    }
    public String getRevisionOid() {
        return revisionOid;
    }
    public void setRevisionOid(String revisionOid) {
        this.revisionOid = revisionOid;
    }
    public String getNameOid() {
        return nameOid;
    }
    public void setNameOid(String nameOid) {
        this.nameOid = nameOid;
    }
    public String getBtmName() {
        return btmName;
    }
    public void setBtmName(String btmName) {
        this.btmName = btmName;
    }
    @Override
    public String toString() {
        return "ReleasedObjDO{" +
                "oid='" + oid + '\'' +
                ", revisionOid='" + revisionOid + '\'' +
                ", nameOid='" + nameOid + '\'' +
                ", btmName='" + btmName + '\'' +
                '}';
    }
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/revision/model/RevisionInfo.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,221 @@
package com.vci.starter.revision.model;
/**
 * ç‰ˆæœ¬çš„信息
 * @author weidy
 * @date 2020/4/15
 */
public class RevisionInfo implements java.io.Serializable {
    /**
     * ç¦æ­¢ä¿®æ”¹è¿™ä¸ªå€¼
     */
    private static final long serialVersionUID = 7167255550437885283L;
    /**
     * ä¸»é”®ï¼Œå¦‚果自己的对象,不是oid作为主键的话,需要用id这个注解
     */
    private String oid;
    /**
     * å¯¹è±¡çš„主键
     */
    private String nameOid;
    /**
     * ç‰ˆæœ¬çš„主键
     */
    private String revisionOid;
    /**
     * æ˜¯å¦æœ€åŽç‰ˆæ¬¡----在采用二级版本管理时才有版次,可以理解为小版本
     */
    private String lastR;
    /**
     * æ˜¯å¦æœ€åˆç‰ˆæ¬¡
     */
    private String firstR;
    /**
     * æ˜¯å¦æœ€æ–°ç‰ˆæœ¬
     */
    private String lastV;
    /**
     * æ˜¯å¦æœ€æ—©ç‰ˆæœ¬
     */
    private String firstV;
    /**
     * ç‰ˆæœ¬è§„则
     */
    private String revisionRule;
    /**
     * ç‰ˆæœ¬åºå·
     */
    private Integer revisionSeq;
    /**
     * ç‰ˆæœ¬å€¼
     */
    private String revisionValue;
    /**
     * ç‰ˆæ¬¡è§„则
     */
    private String versionRule;
    /**
     * ç‰ˆæ¬¡æŽ’序
     */
    private Integer versionSeq;
    /**
     * ç‰ˆæ¬¡å€¼
     */
    private String versionValue;
    /**
     * ä¸šåŠ¡ç±»åž‹çš„åç§°
     */
    private String btmname;
    public String getBtmname() {
        return btmname;
    }
    public void setBtmname(String btmname) {
        this.btmname = btmname;
    }
    public String getOid() {
        return oid;
    }
    public void setOid(String oid) {
        this.oid = oid;
    }
    public String getNameOid() {
        return nameOid;
    }
    public void setNameOid(String nameOid) {
        this.nameOid = nameOid;
    }
    public String getRevisionOid() {
        return revisionOid;
    }
    public void setRevisionOid(String revisionOid) {
        this.revisionOid = revisionOid;
    }
    public String getLastR() {
        return lastR;
    }
    public void setLastR(String lastR) {
        this.lastR = lastR;
    }
    public String getFirstR() {
        return firstR;
    }
    public void setFirstR(String firstR) {
        this.firstR = firstR;
    }
    public String getLastV() {
        return lastV;
    }
    public void setLastV(String lastV) {
        this.lastV = lastV;
    }
    public String getFirstV() {
        return firstV;
    }
    public void setFirstV(String firstV) {
        this.firstV = firstV;
    }
    public String getRevisionRule() {
        return revisionRule;
    }
    public void setRevisionRule(String revisionRule) {
        this.revisionRule = revisionRule;
    }
    public int getRevisionSeq() {
        return revisionSeq;
    }
    public void setRevisionSeq(Integer revisionSeq) {
        this.revisionSeq = revisionSeq;
    }
    public String getRevisionValue() {
        return revisionValue;
    }
    public void setRevisionValue(String revisionValue) {
        this.revisionValue = revisionValue;
    }
    public String getVersionRule() {
        return versionRule;
    }
    public void setVersionRule(String versionRule) {
        this.versionRule = versionRule;
    }
    public int getVersionSeq() {
        return versionSeq;
    }
    public void setVersionSeq(Integer versionSeq) {
        this.versionSeq = versionSeq;
    }
    public String getVersionValue() {
        return versionValue;
    }
    public void setVersionValue(String versionValue) {
        this.versionValue = versionValue;
    }
    @Override
    public String toString() {
        return "RevisionInfo{" +
                "oid='" + oid + '\'' +
                ", nameOid='" + nameOid + '\'' +
                ", revisionOid='" + revisionOid + '\'' +
                ", lastR='" + lastR + '\'' +
                ", firstR='" + firstR + '\'' +
                ", lastV='" + lastV + '\'' +
                ", firstV='" + firstV + '\'' +
                ", revisionRule='" + revisionRule + '\'' +
                ", revisionSeq=" + revisionSeq +
                ", revisionValue='" + revisionValue + '\'' +
                ", versionRule='" + versionRule + '\'' +
                ", versionSeq=" + versionSeq +
                ", versionValue='" + versionValue + '\'' +
                ", btmname='" + btmname + '\'' +
                '}';
    }
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/revision/provider/CommonAnnotationProvider.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,25 @@
package com.vci.starter.revision.provider;
import com.vci.starter.web.pagemodel.BaseQueryObject;
import com.vci.starter.web.pagemodel.BaseResult;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
import java.util.Map;
/**
 * æ³¨é‡Šçš„调用器
 * @author weidy
 * @date 2020/4/17
 */
@FeignClient(name="commonAnnotationProvider",url="${vciPlatform.objectServiceUrl}",path = "annotationController")
public interface CommonAnnotationProvider {
    /**
     * æ‰¹é‡èŽ·å–ç±»ä¸‹é¢çš„æ³¨é‡Š
     * @param queryObject æŸ¥è¯¢æ¡ä»¶ï¼Œå…¶ä¸­å¦‚果指定类的名称时,使用classname参数,值用逗号分隔;如果指定包名时,使用packagename参数,值用逗号分隔
     * @return åˆ¤æ–­success后获取data属性,其中属性的内容为Map<类全路径,Map<属性英文名称小写,属性中文名称>>格式
     */
    @PostMapping("/batchListFieldNameAnnotation")
    BaseResult<Map<String,Map<String,String>>> batchListFieldNameAnnotation(BaseQueryObject queryObject);
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/revision/provider/CommonLifeCycleProvider.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,32 @@
package com.vci.starter.revision.provider;
import com.vci.starter.web.pagemodel.BaseResult;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
/**
 * é€šç”¨çš„生命周期的调用
 * @author weidy
 * @date 2020/4/15
 */
@FeignClient(name="commonLifeCycleProvider",url="${vciPlatform.objectServiceUrl}",path = "lifeCycleController")
public interface CommonLifeCycleProvider {
    /**
     * èŽ·å–ç”Ÿå‘½å‘¨æœŸçš„èµ·å§‹çŠ¶æ€çš„å€¼
     * @param lifeCycleId ç”Ÿå‘½å‘¨æœŸçš„英文名称,不区分大小写
     * @return å…ˆåˆ¤æ–­success,然后取obj的值
     */
    @GetMapping("/getStartStatus")
    BaseResult getStartStatus(@RequestParam("lifeCycleId")String lifeCycleId);
    /**
     * æŸ¥è¯¢çŠ¶æ€çš„æ–‡æœ¬
     * @param lcStatus çŠ¶æ€çš„å€¼
     * @param btmTypeId ä¸šåŠ¡ç±»åž‹çš„ç¼–å·
     * @return çŠ¶æ€çš„æ˜¾ç¤ºæ–‡æœ¬
     */
    @GetMapping("/getStatusText")
    BaseResult getStatusText(@RequestParam("lcStatus")String lcStatus,@RequestParam("btmTypeId")String btmTypeId);
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/revision/provider/CommonRevisionRuleProvider.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,25 @@
package com.vci.starter.revision.provider;
import com.vci.starter.web.pagemodel.BaseResult;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
/**
 * ç‰ˆæœ¬çš„调用器
 * @author weidy
 * @date 2020/4/15
 */
@FeignClient(name="commonRevisionRuleProvider",url="${vciPlatform.objectServiceUrl}",path = "revisionRuleController")
public interface CommonRevisionRuleProvider {
    /**
     * æ ¹æ®è§„则获取下一个版本号
     * @param ruleId ç‰ˆæœ¬è§„则的英文名称
     * @param currentRevisionValue å½“前的值
     * @return å…ˆåˆ¤æ–­success,再取obj属性
     */
    @GetMapping("/getNextRevisionValue")
    BaseResult getNextRevisionValue(@RequestParam("ruleId") String ruleId, @RequestParam("currentRevisionValue") String currentRevisionValue);
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/revision/service/RevisionModelUtil.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,1616 @@
package com.vci.starter.revision.service;
import com.sun.org.apache.xpath.internal.operations.Bool;
import com.vci.starter.revision.bo.TreeWrapperOptions;
import com.vci.starter.revision.model.*;
import com.vci.starter.revision.provider.*;
import com.vci.starter.web.annotation.Column;
import com.vci.starter.web.annotation.VciBtmType;
import com.vci.starter.web.annotation.VciColumnDefinition;
import com.vci.starter.web.constant.RevisionConstant;
import com.vci.starter.web.constant.RegExpConstant;
import com.vci.starter.web.enumpck.DataSecretEnum;
import com.vci.starter.web.enumpck.UserSecretEnum;
import com.vci.starter.web.exception.VciBaseException;
import com.vci.starter.web.model.BaseLinkModel;
import com.vci.starter.web.model.BaseModel;
import com.vci.starter.web.pagemodel.BaseResult;
import com.vci.starter.web.pagemodel.PageHelper;
import com.vci.starter.web.pagemodel.Tree;
import com.vci.starter.web.pagemodel.TreeQueryObject;
import com.vci.starter.web.service.VciSecretServiceI;
import com.vci.starter.web.util.BeanUtil;
import com.vci.starter.web.util.BeanUtilForVCI;
import com.vci.starter.web.util.VciBaseUtil;
import com.vci.starter.web.util.VciDateUtil;
import com.vci.starter.web.wrapper.VciQueryWrapperForDO;
import com.vci.starter.web.wrapper.VciQueryWrapperOption;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import java.lang.reflect.Field;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
/**
 * ç‰ˆæœ¬å’Œå¯¹è±¡æ¨¡åž‹çš„工具类
 * @author weidy
 * @date 2020/4/15
 */
@Component
public class RevisionModelUtil implements VciSecretServiceI {
    /**
     * æ—¥å¿—对象
     */
    private Logger logger = LoggerFactory.getLogger(getClass());
    /**
     * å­˜å‚¨å¯¹è±¡ç±»çš„属性的注释
     */
    public volatile static Map<String, Map<String,String>> modelColumnAnnotationMap = new ConcurrentHashMap<>();
    /**
     * å®žä½“类和注解的映射,在springboot热加载的时候一定要清除
     */
    public volatile static Map<String,VciBtmType> modelAnnotationMap = new ConcurrentHashMap<>();
    /**
     * åˆ¤æ–­å¹‚等性,使用redis
     */
    public static boolean CHECK_IDEMPOTENCE = false;
    /**
     * ç‰ˆæœ¬çš„æ•°æ®æ“ä½œå±‚
     */
    @Autowired(required = false)
    private VciRevisionServiceI revisionMapper;
    /**
     * ç‰ˆæœ¬çš„调用器
     */
    @Autowired(required = false)
    private CommonRevisionRuleProvider revisionRuleProvider;
    /**
     * ç”Ÿå‘½å‘¨æœŸçš„调用器
     */
    @Autowired(required = false)
    private CommonLifeCycleProvider lifeCycleProvider;
    /**
     * æ³¨é‡Šçš„调用接口
     */
    @Autowired(required = false)
    private CommonAnnotationProvider annotationProvider;
    /**
     * æ˜¯æœ€æ–°ç‰ˆæœ¬çš„值
     */
    public static final String LAST_REV_VALUE = "1";
    /**
     * ä¸æ˜¯æœ€æ–°ç‰ˆæœ¬çš„值
     */
    public static final String UN_LAST_REV_VALUE = "0";
    /**
     * åœ¨æ•°æ®æ–°å¢žçš„æ—¶å€™å°è£…属性(包括创建者和生命周期等),并且校验必输项,唯一项(其中唯一项对于时间无法判断),密级
     * @param baseModel åŸºç¡€æ•°æ®å¯¹è±¡
     */
    public void wrapperForAdd(BaseModel baseModel){
        wrapperForAddOrUpVersion(baseModel,false,false);
    }
    /**
     * æ‰¹é‡æ·»åŠ æ•°æ®
     * @param baseModelCollection æ•°æ®å¯¹è±¡é›†åˆ
     */
    public  void wrapperForBatchAdd(Collection<? extends BaseModel> baseModelCollection ){
        VciBaseUtil.alertCollectionNotNull("要新增的数据对象",baseModelCollection);
        BaseModel fristModel = baseModelCollection.iterator().next();
        VciBtmType vciBtmType = getBtmTypeAnnotation(fristModel);
        if(vciBtmType == null){
            throw new VciBaseException("实体对象上没有添加VciBtmType注解");
        }
        //有column注解的属性,有这个注解才需要校验必输项和唯一项
        List<Field> hasColumnAnnoFields =  filterHasColumnAnnoFields(VciBaseUtil.getAllFieldForObj(fristModel.getClass()));
        //必输项
        List<Field> checkNullFields = filterCheckNullFields(hasColumnAnnoFields);
        //唯一项的,包含不区分大小写和区分大小写的
        Map<Field/**要校验唯一项的属性**/, Boolean/**是否不区分大小写**/> checkUniqueFieldsMap = filterCheckUniqueFieldsHasUnCase(fristModel.getClass());
        //唯一的属性的值
        Map<String/**属性的名称**/,Set<Object>> unqiueFieldValueMap = new HashMap<>();
        String creator = VciBaseUtil.getCurrentUserId();
        Date currentDate= new Date();
        String btmName = vciBtmType.name();
        //获取默认的版本号,生命周期,密级
        wrapperFristRevision(fristModel);
        wrapperLifeCycle(fristModel);
        boolean manageRevision = isManageRevision(vciBtmType);
        boolean manageLifeCycle = isManageLifeCycle(vciBtmType);
        boolean checkSecret = isCheckSecret(vciBtmType);
        //遍历,实际也是每一个处理一次,只是版本和生命周期等不重复获取
        baseModelCollection.stream().forEach(s -> {
            VciBaseUtil.alertNotNull(s,"要添加的数据对象");
            setBaseFieldValue(s,creator,currentDate,btmName);
            //校验必输项
            checkFieldsRequired(checkNullFields,s);
            //先判断当前集合中唯一项是否有重复
            if(!CollectionUtils.isEmpty(checkUniqueFieldsMap)){
                checkUniqueFieldsMap.forEach( (field,unCase) ->{
                    checkUniqueValues(field,unCase,s,unqiueFieldValueMap,false);
                });
            }
            //因为新增都一定是第一个版本和版次,所以如果没有设置的时候,全部用初始版本号
            if(manageRevision){
                if(StringUtils.isBlank(s.getNameOid())){
                    s.setNameOid(VciBaseUtil.getPk());
                }
                if(StringUtils.isBlank(s.getRevisionOid())){
                    s.setRevisionOid(VciBaseUtil.getPk());
                }
                s.setRevisionRule(fristModel.getRevisionRule());
                s.setRevisionValue(fristModel.getRevisionValue());
                s.setRevisionSeq(1);
                s.setFirstR("1");
                s.setLastR("1");
                s.setVersionRule(fristModel.getVersionRule());
                s.setVersionValue(fristModel.getVersionValue());
                s.setVersionSeq(1);
                s.setLastV("1");
                s.setFirstV("1");
            }
            if(manageLifeCycle && StringUtils.isBlank(s.getLcStatus())){
                s.setLcStatus(fristModel.getLcStatus());
            }
            if(checkSecret){
                checkDataSecret(s);
            }
        });
    }
    /**
     * åœ¨æ•°æ®ä¿®æ”¹çš„æ—¶å€™å°è£…属性
     * @param baseModel åŸºç¡€æ•°æ®å¯¹è±¡
     */
    public void wrapperForEdit(BaseModel baseModel){
        VciBaseUtil.alertNotNull(baseModel,"要修改的数据对象",baseModel.getOid(),"数据的主键");
        Date currentDate = new Date();
        baseModel.setTs(currentDate);
        baseModel.setLastModifier(VciBaseUtil.getCurrentUserId());
        baseModel.setLastModifyTime(currentDate);
        //
        VciBtmType vciBtmType = getBtmTypeAnnotation(baseModel);
        if(StringUtils.isBlank(baseModel.getBtmname()) && vciBtmType!=null){
            baseModel.setBtmname(vciBtmType.name());
        }
        //获取包含了column注解的属性,因为不包含这个注解的时候是默认nullable为true,unique为false
        List<Field> hasColumnAnnoFields = filterHasColumnAnnoFields(baseModel);
        //判断是否有空的属性
        checkFieldsRequired(filterCheckNullFields(hasColumnAnnoFields),baseModel);
        Map<Field,Boolean> checkUniqueFields = filterCheckUniqueFieldsHasUnCase(hasColumnAnnoFields);
        if(!CollectionUtils.isEmpty(checkUniqueFields)){
            checkUniqueFields.forEach((field,unCase) ->{
                checkUniqueValues(field,unCase,baseModel,new HashMap<>(),true);
            });
        }
        //校验密级
        checkDataSecret(baseModel);
        //修改的时候版本号和生命周期不应该变化
    }
    /**
     * æ‰¹é‡ä¿®æ”¹æ•°æ®å¯¹è±¡æ—¶å°è£…属性,包括唯一项,必输项和基本属性设置
     * @param baseModelCollection æ•°æ®å¯¹è±¡é›†åˆ
     */
    public void wrapperForBatchEdit(List<? extends BaseModel> baseModelCollection){
        VciBaseUtil.alertCollectionNotNull("要修改的数据对象",baseModelCollection);
        BaseModel fristModel = baseModelCollection.iterator().next();
        VciBtmType vciBtmType = getBtmTypeAnnotation(fristModel);
        if(vciBtmType == null){
            throw new VciBaseException("实体对象上没有添加VciBtmType注解");
        }
        //有column注解的属性,有这个注解才需要校验必输项和唯一项
        List<Field> hasColumnAnnoFields =  filterHasColumnAnnoFields(VciBaseUtil.getAllFieldForObj(fristModel.getClass()));
        //必输项
        List<Field> checkNullFields = filterCheckNullFields(hasColumnAnnoFields);
        //唯一项的,包含不区分大小写和区分大小写的
        Map<Field/**要校验唯一项的属性**/, Boolean/**是否不区分大小写**/> checkUniqueFieldsMap = filterCheckUniqueFieldsHasUnCase(fristModel.getClass());
        //唯一的属性的值
        Map<String/**属性的名称**/,Set<Object>> unqiueFieldValueMap = new HashMap<>();
        String creator = VciBaseUtil.getCurrentUserId();
        Date currentDate= new Date();
        String btmName = vciBtmType.name();
        boolean checkSecret = isCheckSecret(vciBtmType);
        //遍历,实际也是每一个处理一次,只是版本和生命周期等不重复获取
        baseModelCollection.stream().forEach(s -> {
            VciBaseUtil.alertNotNull(s,"要添加的数据对象");
            setBaseFieldValueEdit(s,creator,currentDate);
            //校验必输项
            checkFieldsRequired(checkNullFields,s);
            //先判断当前集合中唯一项是否有重复
            if(!CollectionUtils.isEmpty(checkUniqueFieldsMap)){
                checkUniqueFieldsMap.forEach( (field,unCase) ->{
                    checkUniqueValues(field,unCase,s,unqiueFieldValueMap,true);
                });
            }
            //修改的时候,版本和生命周期都不能修改,密级需要修改,所以需要再次校验
            if(checkSecret){
                checkDataSecret(s);
            }
        });
    }
    /**
     * å‡ç‰ˆæœ¬å·
     * @param baseModel æ•°æ®å¯¹è±¡
     */
    public void wrapperForUpRevision(BaseModel baseModel){
        wrapperForAddOrUpVersion(baseModel,true,false);
    }
    /**
     * å‡ç‰ˆæ¬¡
     * @param baseModel æ•°æ®å¯¹è±¡
     */
    public void wrapperForUpVersion(BaseModel baseModel){
        wrapperForAddOrUpVersion(baseModel,true,true);
    }
    /**
     * åœ¨ä¿®æ”¹çš„æ—¶å€™æ‹·è´ï¼Œé˜²æ­¢å‰ç«¯æ²¡æœ‰ä¼ é€’默认的属性
     * @param dto æ•°æ®ä¼ è¾“对象
     * @param baseModel æ•°æ®åº“中的数据对象
     */
    public void copyFromDTO(Object dto,BaseModel baseModel){
        VciBaseUtil.alertNotNull(dto,"数据传输对象",baseModel,"数据库中的数据对象");
        //前端可能不会把默认的所有属性传递过来,所以先从数据库中的数据对象拷贝到临时的对象上
        BaseModel tempModel = new BaseModel();
        BeanUtil.convert(baseModel,tempModel);
        BeanUtil.convert(dto,baseModel);
        //BeanUtil.convert(tempModel,baseModel);
        //不知道为啥,突然BeanUtil.convert(tempModel,baseModel);不好使了
        BeanUtilForVCI.copyPropertiesIgnoreCase(tempModel,baseModel);
        //为了防止前端没有传递默认的属性,所以得先拷贝到baseModel中,然后dto拷贝一次后,再把数据库中拷贝回来。
        //但是因为id,name,description极大概率前端会传递,所以这里也设置一下
        baseModel.setId(VciBaseUtil.getStringValueFromObject(VciBaseUtil.getValueFromField("id",dto)));
        baseModel.setName(VciBaseUtil.getStringValueFromObject(VciBaseUtil.getValueFromField("name",dto)));
        baseModel.setDescription(VciBaseUtil.getStringValueFromObject(VciBaseUtil.getValueFromField("description",dto)));
        tempModel = null;
    }
    /**
     * ä»ŽDTO上拷贝,忽略属性大小写
     * @param dto DTO对象
     * @param baseModel ç›®æ ‡å¯¹è±¡
     */
    public void copyFromDTOIgnore(Object dto,BaseModel baseModel){
        VciBaseUtil.alertNotNull(dto,"数据传输对象",baseModel,"数据库中的数据对象");
        //前端可能不会把默认的所有属性传递过来,所以先从数据库中的数据对象拷贝到临时的对象上
        BaseModel tempModel = new BaseModel();
        BeanUtilForVCI.copyPropertiesIgnoreCase(baseModel,tempModel);
        BeanUtilForVCI.copyPropertiesIgnoreCase(dto,baseModel);
        BeanUtilForVCI.copyPropertiesIgnoreCase(tempModel,baseModel);
        //为了防止前端没有传递默认的属性,所以得先拷贝到baseModel中,然后dto拷贝一次后,再把数据库中拷贝回来。
        //但是因为id,name,description极大概率前端会传递,所以这里也设置一下
        baseModel.setId(VciBaseUtil.getStringValueFromObject(VciBaseUtil.getValueFromField("id",dto)));
        baseModel.setName(VciBaseUtil.getStringValueFromObject(VciBaseUtil.getValueFromField("name",dto)));
        baseModel.setDescription(VciBaseUtil.getStringValueFromObject(VciBaseUtil.getValueFromField("description",dto)));
        tempModel = null;
    }
    /**
     * åœ¨æ•°æ®æ–°å¢žçš„æ—¶å€™ä¸ºé“¾æŽ¥ç±»åž‹å°è£…属性
     * @param linkModel é“¾æŽ¥ç±»åž‹æ•°æ®å¯¹è±¡
     */
    public void wrapperForAddLink(BaseLinkModel linkModel){
        VciBaseUtil.alertNotNull(linkModel,"要新增的链接类型数据对象");
        if(StringUtils.isBlank(linkModel.getOid())){
            linkModel.setOid(VciBaseUtil.getPk());
        }
        linkModel.setCreator(VciBaseUtil.getCurrentUserId());
        Date currentDate = new Date();
        linkModel.setCreateTime(currentDate);
        linkModel.setTs(currentDate);
        linkModel.setLastModifier(linkModel.getCreator());
        linkModel.setLastModifytime(currentDate);
    }
    /**
     * åœ¨æ–°å¢žæ•°æ®çš„æ—¶å€™ä¸ºé“¾æŽ¥ç±»åž‹å°è£…属性
     * @param linkModel é“¾æŽ¥ç±»åž‹å¯¹è±¡
     * @param fromModel from端业务数据
     * @param toModel to端业务数据
     */
    public void wrapperForAddLink(BaseLinkModel linkModel,BaseModel fromModel,BaseModel toModel){
        wrapperForAddLink(linkModel);
        VciBaseUtil.alertNotNull(fromModel,"链接类型from端",toModel,"链接类型to端");
        linkModel.setFoid(fromModel.getOid());
        linkModel.setFbtmname(fromModel.getBtmname());
        linkModel.setFnameoid(fromModel.getNameOid());
        linkModel.setToid(toModel.getOid());
        linkModel.setTbtmname(toModel.getBtmname());
        linkModel.setTnameoid(toModel.getNameOid());
        linkModel.setTrevisionoid(toModel.getRevisionOid());
    }
    /**
     * åœ¨æ•°æ®ä¿®æ”¹çš„æ—¶å€™ä¸ºé“¾æŽ¥ç±»åž‹å°è£…属性
     * @param linkModel åŸºç¡€æ•°æ®å¯¹è±¡
     */
    public void wrapperForEditLink(BaseLinkModel linkModel){
        VciBaseUtil.alertNotNull(linkModel,"要修改的链接类型数据对象");
        Date currentDate = new Date();
        linkModel.setTs(currentDate);
        linkModel.setLastModifier(VciBaseUtil.getCurrentUserId());
        linkModel.setLastModifytime(currentDate);
    }
    /**
     * åˆ¤æ–­æ—¶é—´æˆ³æ˜¯å¦ç›¸åŒ
     * @param dtoTs æ•°æ®ä¼ è¾“对象上的ts
     * @param doTs æ•°æ®å¯¹è±¡ä¸Šçš„ts
     * @return true表示相同
     */
    public boolean checkTs(Date dtoTs,Date doTs){
        if(dtoTs!=null && doTs!=null){
            if(dtoTs.getTime() == doTs.getTime()){
                return true;
            }
            String dtoTsString = VciDateUtil.date2Str(dtoTs,VciDateUtil.DateTimeMillFormat);
            String doTsString = VciDateUtil.date2Str(doTs,VciDateUtil.DateTimeMillFormat);
            if(dtoTsString.equalsIgnoreCase(doTsString)){
                return true;
            }else{
                throw new VciBaseException("tsNotEqual");
            }
        }
        return false;
    }
    /**
     * åˆ¤æ–­å¯†çº§æ˜¯å¦ç¬¦åˆè¦æ±‚
     * @param baseModel æ•°æ®å¯¹è±¡
     * @return true è¡¨ç¤ºç¬¦åˆè¦æ±‚
     * @throws VciBaseException ä¸ç¬¦åˆè¦æ±‚时会抛出异常
     */
    public boolean checkDataSecret(BaseModel baseModel) throws VciBaseException{
        VciBaseUtil.alertNotNull(baseModel,"要校验密级的数据对象");
        if(isCheckSecret(baseModel) && VciBaseUtil.getCurrentUserSecret()>0) {
            if (baseModel.getSecretGrade() == null ) {
                baseModel.setSecretGrade(DataSecretEnum.NONE.getValue());
            }
            Integer userSecret = VciBaseUtil.getCurrentUserSecret();
            if (!checkUserSecret(baseModel.getSecretGrade())) {
                throw new VciBaseException("当前用户的密级低于数据的密级,用户密级为" + UserSecretEnum.getSecretText(userSecret) + ",数据密级为" + DataSecretEnum.getSecretText(baseModel.getSecretGrade()));
            }
        }
        return true;
    }
    /**
     * å‘布当前版本
     * @param baseModel è¦å‘布的数据对象
     */
    public void saveRelease(BaseModel baseModel){
        VciBaseUtil.alertNotNull(baseModel,"数据对象");
        VciBtmType btmType = getBtmTypeAnnotation(baseModel);
        if(isManageRevision(btmType)) {
            //必须管理版本才会执行发布
            VciBaseUtil.alertNotNull( baseModel.getOid(), "数据对象的主键", baseModel.getNameOid(), "对象的主键",baseModel.getRevisionOid(),"版本的主键");
            ReleasedObjDO releasedObjDO = new ReleasedObjDO();
            BeanUtil.convert(baseModel,releasedObjDO);
            if(StringUtils.isBlank(releasedObjDO.getBtmName())){
                releasedObjDO.setBtmName(btmType.name());
            }
            revisionMapper.saveReleased(releasedObjDO);
        }
    }
    /**
     * æ•°æ®æ–°å¢žçš„æ—¶å€™å°è£…属性,可以升版本,可以升版次
     * @param baseModel æ•°æ®å¯¹è±¡
     * @param upRevsion å‡ç‰ˆå·
     * @param upVersion å‡ç‰ˆæ¬¡
     */
    private void wrapperForAddOrUpVersion(BaseModel baseModel,boolean upRevsion,boolean upVersion){
        VciBaseUtil.alertNotNull(baseModel,"数据对象");
        //封装基本属性
        setBaseFieldValue(baseModel);
        //校验必输项和唯一项
        List<Field> fields = VciBaseUtil.getAllFieldForObj(baseModel.getClass());
        if(!CollectionUtils.isEmpty(fields)){
            //获取包含了column注解的属性,因为不包含的默认nullable为true,unique为false
            List<Field> hasColumnAnnoFields = fields.stream().filter(s->s.isAnnotationPresent(Column.class)).distinct().collect(Collectors.toList());
            if(!CollectionUtils.isEmpty(hasColumnAnnoFields)){
                //分离出需要判断是否为空的字段
                List<Field> notNullFields = filterCheckNullFields(hasColumnAnnoFields);
                //判断是否有空的属性
                checkFieldsRequired(notNullFields,baseModel);
                Map<Field,Boolean> checkUniqueFields = filterCheckUniqueFieldsHasUnCase(hasColumnAnnoFields);
                if(!CollectionUtils.isEmpty(checkUniqueFields)){
                    checkUniqueFields.forEach((field,unCase) ->{
                        checkUniqueValues(field,unCase,baseModel,new HashMap<>(),false);
                    });
                }
            }
        }
        //校验密级
        checkDataSecret(baseModel);
        //处理生命周期
        wrapperLifeCycle(baseModel);
        //如果控制版本,会创建第一个版本
        if(isManageRevision(baseModel)) {
            if(!upVersion) {
                if (StringUtils.isBlank(baseModel.getCopyFromVersion()) && !upRevsion) {
                    //说明是新增
                    wrapperFristRevision(baseModel);
                } else {
                    //说明是升版号
                    wrapperRevisionModel(baseModel);
                }
            }else {
                wrapperVersionModel(baseModel);
            }
        }
    }
    /**
     *处理基本属性
     * @param baseModel æ•°æ®å¯¹è±¡
     */
    public void setBaseFieldValue(BaseModel baseModel){
        VciBaseUtil.alertNotNull(baseModel,"数据对象");
        setBaseFieldValue(baseModel,null,null,null);
    }
    /**
     * å¤„理基本属性
     * @param currentUserId å½“前用户
     * @param currentDate å½“前时间
     * @param btmName ä¸šåŠ¡ç±»åž‹åç§°
     * @param baseModel æ•°æ®å¯¹è±¡
     */
    public void setBaseFieldValue(BaseModel baseModel,String currentUserId,Date currentDate,String btmName){
        if(StringUtils.isBlank(currentUserId)){
            currentUserId = VciBaseUtil.getCurrentUserId();
        }
        if(currentDate == null){
            currentDate = new Date();
        }
        if(StringUtils.isBlank(btmName)){
            btmName = VciBaseUtil.getBtmTypeNameFromDO(baseModel.getClass());
        }
        //处理基本属性
        if(StringUtils.isBlank(baseModel.getOid())){
            baseModel.setOid(VciBaseUtil.getPk());
        }
        if(StringUtils.isBlank(baseModel.getCreator())) {
            baseModel.setCreator(currentUserId);
        }
        baseModel.setCreateTime(currentDate);
        baseModel.setTs(currentDate);
        if(StringUtils.isBlank(baseModel.getLastModifier())) {
            baseModel.setLastModifier(currentUserId);
        }
        baseModel.setLastModifyTime(currentDate);
        if(StringUtils.isBlank(baseModel.getOwner())) {
            baseModel.setOwner(baseModel.getCreator());
        }
        baseModel.setBtmname(btmName);
    }
    /**
     * ç¼–辑的时候处理基本属性
     * @param baseModel æ•°æ®å¯¹è±¡
     * @param currentUserId å½“前用户
     * @param currentDate å½“前时间
     */
    public void setBaseFieldValueEdit(BaseModel baseModel,String currentUserId,Date currentDate){
        if(StringUtils.isBlank(currentUserId)){
            currentUserId = VciBaseUtil.getCurrentUserId();
        }
        if(currentDate == null){
            currentDate = new Date();
        }
        baseModel.setTs(currentDate);
        baseModel.setLastModifier(currentUserId);
        baseModel.setLastModifyTime(currentDate);
    }
    /**
     * æ‰¹é‡æ‰§è¡Œçš„æ—¶å€™,校验唯一项
     * @param field å±žæ€§
     * @param unCase æ˜¯å¦ä¸åŒºåˆ†å¤§å°å†™
     * @param baseModel æ•°æ®å¯¹è±¡
     * @param unqiueFieldValueMap å­˜åœ¨çš„æ•°æ®é›†åˆ
     * @param edit æ˜¯å¦ä¸ºä¿®æ”¹
     */
    private void checkUniqueValues(Field field,Boolean unCase,BaseModel baseModel, Map<String/**属性的名称**/,Set<Object>> unqiueFieldValueMap ,boolean edit){
        field.setAccessible(true);
        String fieldName = field.getName();
        Set<Object> fieldValueList ;
        if(unqiueFieldValueMap.containsKey(fieldName)){
            fieldValueList = unqiueFieldValueMap.get(fieldName);
        }else{
            fieldValueList = new HashSet<>();
        }
        Object fieldValue = null;
        try {
            fieldValue = field.get(baseModel);
        } catch (IllegalAccessException e) {
            if(logger.isDebugEnabled()){
                logger.debug("获取属性的值出现了错误,{}",fieldName);
            }
        }
        if(fieldValue!=null){
            if(unCase !=null && unCase){
                fieldValue = fieldValue.toString().toLowerCase();
            }
            if(fieldValueList.contains(fieldValue) || (unCase?checkFieldNotUniqueUnCase(field,baseModel,edit):checkFieldNotUnique(field,baseModel,edit))){
                throw new VciBaseException("dataRepeat",new String[]{getColumnChineseText(field),fieldValue.toString()});
            }else{
                fieldValueList.add(fieldValue);
            }
        }
        unqiueFieldValueMap.put(fieldName,fieldValueList);
    }
    /**
     * å°è£…新的版本信息,会自动处理老的版本和最新版本的问题
     * @param newModel æ–°ç‰ˆæœ¬çš„æ•°æ®å¯¹è±¡
     * @throws VciBaseException å‚数错误,无注解,服务配置不正确的时候会抛出异常
     */
    public void wrapperRevisionModel(BaseModel newModel) throws VciBaseException{
        setBtmName(newModel);
        VciBaseUtil.alertNotNull(newModel.getCopyFromVersion(),"引用老版本的主键");
        if (revisionMapper != null) {
            RevisionInfo oldRevision = revisionMapper.selectByOid(newModel.getCopyFromVersion(),VciBaseUtil.getTableName(newModel.getBtmname()));
            if(oldRevision == null || StringUtils.isBlank(oldRevision.getOid()) ){
                throw new VciBaseException("老版本在数据库中不存在");
            }
            BaseModel oldModel = new BaseModel();
            BeanUtil.convert(oldRevision,oldModel);
            wrapperRevisionModel(oldModel,newModel);
        }else{
            throw new VciBaseException("没有初始化版本规则的数据操作层,请开发人员检查Maven是否引用");
        }
    }
    /**
     * å°è£…新的版次信息,会自动处理老的版次和最新版次问题
     * @param newModel æ–°ç‰ˆæ¬¡çš„æ•°æ®å¯¹è±¡
     * @throws VciBaseException å‚数错误,缺少注解,配置错误都会抛出这个异常
     */
    public void wrapperVersionModel(BaseModel newModel) throws VciBaseException{
        VciBaseUtil.alertNotNull(newModel,"新版次的数据对象",newModel.getCopyFromVersion(),"引用老版次的主键");
        if (revisionMapper != null) {
            RevisionInfo oldRevision = revisionMapper.selectByOid(newModel.getCopyFromVersion(),VciBaseUtil.getTableName(newModel.getBtmname()));
            if(oldRevision == null || StringUtils.isBlank(oldRevision.getOid()) ){
                throw new VciBaseException("老版次数据在数据库中不存在");
            }
            BaseModel oldModel = new BaseModel();
            BeanUtil.convert(oldRevision,oldModel);
            wrapperVersionModel(oldModel,newModel);
        }else{
            throw new VciBaseException("没有初始化版本规则的数据操作层,请开发人员检查Maven是否引用");
        }
    }
    /**
     * èŽ·å–æ•°æ®å¯¹è±¡ä¸­æ‰€æœ‰åŒ…å«äº†column列的属性
     * @param baseModel æ•°æ®å¯¹è±¡
     * @return æ²¡æœ‰æ—¶ä¼šè¿”回Null
     */
    public List<Field> filterHasColumnAnnoFields(BaseModel baseModel){
        List<Field> fields = VciBaseUtil.getAllFieldForObj(baseModel.getClass());
        return filterHasColumnAnnoFields(fields);
    }
    /**
     * è¿‡æ»¤åŒ…含了column的属性
     * @param fields æ‰€æœ‰çš„属性
     * @return ç¬¦åˆæ¡ä»¶çš„属性,不存在的时候会返回null
     */
    public List<Field> filterHasColumnAnnoFields( List<Field> fields){
        if(!CollectionUtils.isEmpty(fields)) {
            return  fields.stream().filter(s -> s.isAnnotationPresent(Column.class)).distinct().collect(Collectors.toList());
        }else{
            return null;
        }
    }
    /**
     * è¿‡æ»¤éœ€è¦æ ¡éªŒæ˜¯å¦è¾“入的属性
     * @param fields åŒ…含有column注解的属性
     * @return ç¬¦åˆæ¡ä»¶çš„属性,不存在的时候会返回null
     */
    public List<Field> filterCheckNullFields(List<Field> fields){
        if(!CollectionUtils.isEmpty(fields)){
            return  fields.stream().filter(s -> {
                Column column = getColumnAnnotation(s);
                //指定了不能为空,或者需要校验唯一的一定不能为空
                return ((column != null && column.nullable()) == false) || ((column != null && column.unique()) == true);
            }).collect(Collectors.toList());
        }
        return null;
    }
    /**
     * èŽ·å–æ ¡éªŒå”¯ä¸€é¡¹ï¼ŒåŒ…å« åŒºåˆ†å¤§å°å†™å”¯ä¸€é¡¹çš„属性
     * @param doClass æ•°æ®å¯¹è±¡æ‰€å±žçš„ç±»
     * @return å±žæ€§æ˜ å°„,key是属性对象,value的值为true表示不区分大小写的方式校验唯一项
     */
    public Map<Field/**要校验唯一项的属性**/, Boolean/**是否不区分大小写**/> filterCheckUniqueFieldsHasUnCase(Class<?> doClass){
        List<Field> hasColumnAnnoFields =  filterHasColumnAnnoFields(VciBaseUtil.getAllFieldForObj(doClass));
        return filterCheckUniqueFieldsHasUnCase(hasColumnAnnoFields);
    }
    /**
     * èŽ·å–æ ¡éªŒå”¯ä¸€é¡¹ï¼ŒåŒ…å« åŒºåˆ†å¤§å°å†™å”¯ä¸€é¡¹çš„属性
     * @param hasColumnAnnoFields æ•°æ®å¯¹è±¡æ‰€å±žçš„ç±»
     * @return å±žæ€§æ˜ å°„,key是属性对象,value的值为true表示不区分大小写的方式校验唯一项
     */
    public Map<Field/**要校验唯一项的属性**/, Boolean/**是否不区分大小写**/> filterCheckUniqueFieldsHasUnCase(List<Field> hasColumnAnnoFields){
        //唯一项的,包含不区分大小写和区分大小写的
        Map<Field/**要校验唯一项的属性**/, Boolean/**是否不区分大小写**/> checkUniqueFieldsMap = new HashMap<>();
        List<Field> checkUniqueFields = filterCheckUniqueFields(hasColumnAnnoFields);
        if(!CollectionUtils.isEmpty(checkUniqueFields)){
            checkUniqueFields.stream().forEach(s -> {
                checkUniqueFieldsMap.put(s,false);
            });
        }
        List<Field> checkUniqueUnCaseFields = filterCheckUniqueUnCaseFields(hasColumnAnnoFields);
        if(!CollectionUtils.isEmpty(checkUniqueUnCaseFields)){
            checkUniqueUnCaseFields.stream().forEach(s -> {
                //这个是不区分大小写
                checkUniqueFieldsMap.put(s,true);
            });
        }
        return checkUniqueFieldsMap;
    }
    /**
     * èŽ·å–éœ€è¦æ ¡éªŒå”¯ä¸€çš„å±žæ€§
     * @param fields åŒ…含有column注解的属性
     * @return ç¬¦åˆæ¡ä»¶çš„属性,不存在的时候会返回null
     */
    public List<Field> filterCheckUniqueFields(List<Field> fields){
        if(!CollectionUtils.isEmpty(fields)){
            return fields.stream().filter(s -> {
                Column column = getColumnAnnotation(s);
                return (column != null && column.unique()) == true;
            }).collect(Collectors.toList());
        }
        return null;
    }
    /**
     * èŽ·å–éœ€è¦æ ¡éªŒå”¯ä¸€çš„å±žæ€§
     * @param fields åŒ…含有column注解的属性
     * @return ç¬¦åˆæ¡ä»¶çš„属性,不存在的时候会返回null
     */
    public List<Field> filterCheckUniqueUnCaseFields(List<Field> fields){
        if(!CollectionUtils.isEmpty(fields)){
            return fields.stream().filter(s -> {
                Column column = getColumnAnnotation(s);
                return (column != null && column.unique() && column.unUniqueCase()) == true;
            }).collect(Collectors.toList());
        }
        return null;
    }
    /**
     * æ ¡éªŒå±žæ€§çš„值是否唯一
     * @param uniqueFields  éœ€è¦æ ¡éªŒå”¯ä¸€çš„属性值
     * @param baseModel æ•°æ®å¯¹è±¡
     * @param editFlag æ˜¯å¦ä¸ºä¿®æ”¹æ•°æ®ï¼Œä¿®æ”¹çš„æ—¶å€™éœ€è¦æŽ’除当前数据
     */
    public void checkFieldsUnique(List<Field> uniqueFields, BaseModel baseModel, boolean editFlag) {
        if(!CollectionUtils.isEmpty(uniqueFields)){
            List<Field> notUniqueFields = uniqueFields.stream().filter( s -> checkFieldNotUnique(s,baseModel,editFlag)).collect(Collectors.toList());
            if(!CollectionUtils.isEmpty(notUniqueFields)){
                //找对应的中文名称
                List<String> notUniqueFieldChineseNames = new ArrayList<>();
                notUniqueFields.stream().forEach( s -> {
                    //先从注释中上获取,但是怕的是之前没有注释,所以可能得从注解上获取
                    notUniqueFieldChineseNames.add(getColumnChineseText(s));
                });
                //按理说这个错误信息不应该出现的,所以不做多语
                throw new VciBaseException("属性[" + notUniqueFieldChineseNames.stream().collect(Collectors.joining(",")) + "]对应的数据在系统中已经存在",notUniqueFieldChineseNames.toArray());
            }
        }
    }
    /**
     * æ ¡éªŒå±žæ€§çš„值是否唯一,不区分属性值的大小写
     * @param uniqueFields  éœ€è¦æ ¡éªŒå”¯ä¸€çš„属性值
     * @param baseModel æ•°æ®å¯¹è±¡
     * @param editFlag æ˜¯å¦ä¸ºä¿®æ”¹æ•°æ®ï¼Œä¿®æ”¹çš„æ—¶å€™éœ€è¦æŽ’除当前数据
     */
    public void checkFieldsUnUniqueCase(List<Field> uniqueFields, BaseModel baseModel, boolean editFlag){
        if(!CollectionUtils.isEmpty(uniqueFields)){
            List<Field> notUniqueFields = uniqueFields.stream().filter( s -> checkFieldNotUniqueUnCase(s,baseModel,editFlag)).collect(Collectors.toList());
            if(!CollectionUtils.isEmpty(notUniqueFields)){
                //找对应的中文名称
                List<String> notUniqueFieldChineseNames = new ArrayList<>();
                notUniqueFields.stream().forEach( s -> {
                    //先从注释中上获取,但是怕的是之前没有注释,所以可能得从注解上获取
                    notUniqueFieldChineseNames.add(getColumnChineseText(s));
                });
                //按理说这个错误信息不应该出现的,所以不做多语
                throw new VciBaseException("属性[" + notUniqueFieldChineseNames.stream().collect(Collectors.joining(",")) + "]对应的数据在系统中已经存在",notUniqueFieldChineseNames.toArray());
            }
        }
    }
    /**
     * æ£€æŸ¥å±žæ€§æ˜¯å¦å”¯ä¸€
     * @param field éœ€è¦æ ¡éªŒçš„属性对象
     * @param baseModel æ•°æ®å¯¹è±¡
     * @param editFlag æ˜¯å¦ä¸ºä¿®æ”¹æ•°æ®ï¼Œä¿®æ”¹çš„æ—¶å€™éœ€è¦æŽ’除当前数据
     * @return true表示不唯一,false唯一
     */
    public boolean checkFieldNotUnique(Field field,BaseModel baseModel,boolean editFlag){
        return checkFieldNotUnique(field,baseModel,editFlag,false);
    }
    /**
     * æ£€æŸ¥å±žæ€§æ˜¯å¦å”¯ä¸€,并且不区分大小写
     * @param field éœ€è¦æ ¡éªŒçš„属性对象
     * @param baseModel æ•°æ®å¯¹è±¡
     * @param editFlag æ˜¯å¦ä¸ºä¿®æ”¹æ•°æ®ï¼Œä¿®æ”¹çš„æ—¶å€™éœ€è¦æŽ’除当前数据
     * @return true表示不唯一,false唯一
     */
    public boolean checkFieldNotUniqueUnCase(Field field,BaseModel baseModel,boolean editFlag){
        return checkFieldNotUnique(field,baseModel,editFlag,true);
    }
    /**
     * æ£€æŸ¥å±žæ€§æ˜¯å¦å”¯ä¸€,可以设置不区分大小写
     * @param field éœ€è¦æ ¡éªŒçš„属性对象
     * @param baseModel æ•°æ®å¯¹è±¡
     * @param editFlag æ˜¯å¦ä¸ºä¿®æ”¹æ•°æ®ï¼Œä¿®æ”¹çš„æ—¶å€™éœ€è¦æŽ’除当前数据
     * @param unCase ä¸åŒºåˆ†å¤§å°å†™
     * @return true表示不唯一,false唯一
     */
    private boolean checkFieldNotUnique(Field field,BaseModel baseModel,boolean editFlag,boolean unCase){
        String btmType = VciBaseUtil.getBtmTypeNameFromDO(baseModel.getClass());
        String className = baseModel.getClass().getName();
        String columnName =VciBaseUtil.getCboAttrNameFromField(field,baseModel.getClass());
        String tableName = VciBaseUtil.getTableName(btmType);
        Object columnValue = null;
        String oid = "";
        if(editFlag){
            oid = baseModel.getOid();
        }
        field.setAccessible(true);
        try {
            columnValue = field.get(baseModel);
        } catch (IllegalAccessException e) {
            String msg = "判断某个对象的属性是否重复时出现了错误";
            if(logger.isErrorEnabled()) {
                logger.error(msg + ",{}.{}", className, field.getName(), e);
            }
            throw new VciBaseException(msg + "{0},{1}",new String[]{className,field.getName()},e);
        }
        if(unCase && columnValue instanceof String){
            //只有字符串才有大小写,日期和数字这些不支持
            columnName = "lower(" + columnName + ")";
            columnValue = columnValue.toString().toLowerCase();
        }
        int count;
        if(editFlag){
            count=  revisionMapper.countByPropertiesNotIncludeSelf(columnName, columnValue, tableName, oid);
        }else{
            count = revisionMapper.countByProperties(columnName,columnValue,tableName);
        }
        if(count>0){
            return true;
        }
        return false;
    }
    /**
     * åˆ¤æ–­æ•°æ®æ˜¯å¦ä¸ºç©º
     * @param notNullFields éœ€è¦åˆ¤æ–­çš„属性
     * @param baseModel æ•°æ®å¯¹è±¡
     */
    public void checkFieldsRequired(List<Field> notNullFields, BaseModel baseModel) {
        if(!CollectionUtils.isEmpty(notNullFields)){
            String className = baseModel.getClass().getName();
            List<Field> nullValueFields = notNullFields.stream().filter( s -> checkFieldValueNull(s,baseModel)).collect(Collectors.toList());
            if(!CollectionUtils.isEmpty(nullValueFields)){
                //找对应的中文名称
                List<String> nullFieldChineseNames = new ArrayList<>();
                nullValueFields.stream().forEach( s -> {
                    //先从注释中上获取,但是怕的是之前没有注释,所以可能得从注解上获取
                    nullFieldChineseNames.add(getColumnChineseText(s));
                });
                //按理说这个错误信息不应该出现的,所以不做多语
                throw new VciBaseException("属性[" + nullFieldChineseNames.stream().collect(Collectors.joining(",")) + "]不能为空",nullFieldChineseNames.toArray());
            }
        }
    }
    /**
     * æ ¡éªŒå±žæ€§ä¸ºç©º
     * @param field å±žæ€§å¯¹è±¡
     * @param baseModel æ•°æ®å¯¹è±¡
     * @return true表示为空,false表示不为空
     */
    public boolean checkFieldValueNull(Field field,BaseModel baseModel){
        String className = baseModel.getClass().getName();
        field.setAccessible(true);
        try {
            Object value = field.get(baseModel);
            if(value == null || (value instanceof String) && StringUtils.isBlank((String)value)){
                return true;
            }
        } catch (IllegalAccessException e) {
            String msg = "判断某个对象的属性是否为空时出现了错误";
            if(logger.isErrorEnabled()) {
                logger.error(msg + ",{}.{}", className, field.getName(), e);
            }
            throw new VciBaseException(msg + "{0},{1}",new String[]{className,field.getName()},e);
        }
        return false;
    }
    /**
     * èŽ·å–
     * @param field å±žæ€§å¯¹è±¡
     * @return ä¸­æ–‡åç§°ï¼Œä¼˜å…ˆå–注释,否则取注解,最后返回属性的英文名称
     */
    public String getColumnChineseText(Field field){
        String className = field.getDeclaringClass().getName();
        if(modelColumnAnnotationMap.containsKey(className) && modelColumnAnnotationMap.get(className.toLowerCase()).containsKey(field.getName().toLowerCase())){
            return modelColumnAnnotationMap.get(className.toLowerCase()).get(field.getName().toLowerCase());
        }else{
            Column column = getColumnAnnotation(field);
            if(column!=null && StringUtils.isNotBlank(column.columnDefinition())){
                return column.columnDefinition();
            }else{
                //看看columnDefinition注解
                if(field.isAnnotationPresent(VciColumnDefinition.class)){
                    VciColumnDefinition columnDefinition = field.getDeclaredAnnotation(VciColumnDefinition.class);
                    if(columnDefinition == null){
                        columnDefinition = field.getAnnotation(VciColumnDefinition.class);
                    }
                    if(columnDefinition!=null) {
                        return columnDefinition.value();
                    }
                }
            }
            return field.getName();
        }
    }
    /**
     * èŽ·å–æ•°æ®å¯¹è±¡ä¸Šçš„åˆ—æ³¨è§£
     * @param field å­—段的属性对象
     * @return æ²¡æœ‰æ³¨è§£çš„æ—¶å€™è¿”回空,否则返回对应的注解
     */
    public Column getColumnAnnotation(Field field){
        if(field.isAnnotationPresent(Column.class)) {
            Column column = field.getDeclaredAnnotation(Column.class);
            if (column == null) {
                column = field.getAnnotation(Column.class);
            }
            return column;
        }
        return null;
    }
    /**
     * æ ¡éªŒæ˜¯å¦æŽ§åˆ¶å¯†çº§
     * @param doObject æ•°æ®å¯¹è±¡
     * @return true需要校验密级
     */
    public boolean isCheckSecret(BaseModel doObject){
        VciBtmType btmType = getBtmTypeAnnotation(doObject);
        return isCheckSecret(btmType);
    }
    /**
     * æ ¡éªŒæ˜¯å¦æŽ§åˆ¶å¯†çº§
     * @param btmType ä¸šåŠ¡ç±»åž‹çš„æ³¨è§£
     * @return true需要校验密级
     */
    public boolean isCheckSecret(VciBtmType btmType){
        if(btmType !=null && btmType.secretAble()){
            return true;
        }
        return false;
    }
    /**
     * å°è£…新的版本信息,会自动处理老的版本和最新版本的问题
     * @param oldModel è€ç‰ˆæœ¬çš„æ•°æ®å¯¹è±¡
     * @param newModel æ–°ç‰ˆæœ¬çš„æ•°æ®å¯¹è±¡
     * @throws VciBaseException å‚数错误,缺少注解,配置错误都会抛出这个异常
     */
    public void wrapperRevisionModel(BaseModel oldModel, BaseModel newModel) throws VciBaseException {
        VciBaseUtil.alertNotNull(oldModel,"老版本的数据对象",newModel,"新版本的数据对象");
        VciBtmType btmType = getBtmTypeAnnotation(newModel);
        if(btmType == null){
            throw new VciBaseException("没有VciBtmType注解,无法判断是否控制版本");
        }else {
            if ( isManageRevision(btmType)) {
                //升版的前提是有版本规则,并且如果是手动输入的时候,必须从前端输入值。
                //1. ä¸»é”®ä¸èƒ½ç›¸åŒ
                if (StringUtils.isBlank(newModel.getOid()) || newModel.getOid().equalsIgnoreCase(oldModel.getOid())) {
                    newModel.setOid(VciBaseUtil.getPk());
                }
                //2.nameOid要相同
                newModel.setNameOid(oldModel.getNameOid());
                //2.1 revisionOid不相同
                newModel.setRevisionOid(VciBaseUtil.getPk());
                //查找最后一个版本的版本值
                RevisionInfo lastRevision = null;
                if (revisionMapper != null) {
                    lastRevision = revisionMapper.selectLastRevision(newModel.getNameOid(),VciBaseUtil.getTableName(btmType.name()));
                } else {
                    //没有这个,那就直接用oldModel去获取版本号
                    lastRevision = new RevisionInfo();
                    BeanUtil.convert(oldModel, lastRevision);
                }
                newModel.setRevisionRule(lastRevision.getRevisionRule());
                newModel.setVersionRule(lastRevision.getVersionRule());
                //3.版本号
                if(StringUtils.isBlank(newModel.getRevisionValue())  &&  !isInputRevision(newModel) && StringUtils.isBlank(lastRevision.getRevisionRule())){
                    //不处理
                }else {
                    if (StringUtils.isBlank(newModel.getRevisionValue())) {
                        wrapperRevisionValue(newModel, btmType, lastRevision);
                    }
                }
                //如果有版次,那这个就是新版本的第一个版次
                if (isManageVersion(btmType)) {
                    wrapperFristVersion(newModel);
                }else{
                    //可能没有处理版次,但是必须要添加上
                    newModel.setFirstV("1");
                    newModel.setLastV("1");
                }
                //4.新的版本顺序
                newModel.setRevisionSeq(lastRevision.getRevisionSeq() + 1);
                newModel.setLastR("1");
                newModel.setFirstR("0");
                //5.修改老的版本的isLastR
                saveOldModel(oldModel);
                //而且可能oldModel不是最后的那个版本
            }
            //支持可以使用版本规则生成,也同时可以手动输入,所以当手动输入而值又没有的时候需要新生成
        }
    }
    /**
     * å°è£…新的版次信息,会自动处理老的版次和最新版次问题
     * @param oldModel è€ç‰ˆæ¬¡çš„æ•°æ®å¯¹è±¡
     * @param newModel æ–°ç‰ˆæ¬¡çš„æ•°æ®å¯¹è±¡
     * @throws VciBaseException å‚数错误,缺少注解,配置错误都会抛出这个异常
     */
    public void wrapperVersionModel(BaseModel oldModel, BaseModel newModel) throws VciBaseException {
        VciBaseUtil.alertNotNull(oldModel,"老版次的数据对象",newModel,"新版次的数据对象");
        VciBtmType btmType = getBtmTypeAnnotation(newModel);
        if(btmType == null){
            throw new VciBaseException("没有VciBtmType注解,无法判断是否控制版次");
        }else {
            if (isManageVersion(btmType)) {
                //才处理新的版次
                //主键不能相同,nameoid和revisionoid必须相同
                if (StringUtils.isBlank(newModel.getOid()) || newModel.getOid().equalsIgnoreCase(oldModel.getOid())) {
                    newModel.setOid(VciBaseUtil.getPk());
                }
                if(StringUtils.isBlank(newModel.getNameOid()) || !newModel.getNameOid().equalsIgnoreCase(oldModel.getNameOid())){
                    newModel.setNameOid(oldModel.getNameOid());
                }
                if(StringUtils.isBlank(newModel.getRevisionOid())
                        || !newModel.getRevisionOid().equalsIgnoreCase(oldModel.getRevisionOid())){
                    newModel.setRevisionOid(oldModel.getRevisionOid());
                }
                //查询这个相同的版本下的最新版次
                RevisionInfo lastRevision = null;
                if (revisionMapper != null) {
                    lastRevision = revisionMapper.selectLastVersion(newModel.getNameOid(),newModel.getRevisionOid(),VciBaseUtil.getTableName(btmType.name()));
                } else {
                    //没有这个,那就直接用oldModel去获取版本号
                    lastRevision = new RevisionInfo();
                    BeanUtil.convert(oldModel, lastRevision);
                }
                //版次号,就数字和字母两种
                if(oldModel.getVersionValue().matches(RegExpConstant.LETTER)){
                    //说明是字母的
                    newModel.setVersionValue(String.valueOf((char)(oldModel.getVersionValue().toCharArray()[0] + 1)));
                }else{
                    newModel.setVersionValue(String.valueOf(Integer.valueOf(oldModel.getVersionValue()) + 1));
                }
                newModel.setVersionSeq(lastRevision.getVersionSeq() + 1);
                newModel.setVersionRule(oldModel.getVersionRule());
                newModel.setLastV("1");
                newModel.setFirstV("0");
                //处理老版次
                saveOldModelVersion(oldModel);
            }
        }
    }
    /**
     * å¤„理业务类型的名称
     * @param baseModel æ•°æ®å¯¹è±¡
     */
    private void setBtmName(BaseModel baseModel){
        VciBaseUtil.alertNotNull(baseModel,"数据对象");
        if(StringUtils.isBlank(baseModel.getBtmname())){
            VciBtmType btmType = getBtmTypeAnnotation(baseModel);
            if(btmType == null){
                throw new VciBaseException("没有VciBtmType注解,无法判断业务类型");
            }
            baseModel.setBtmname(btmType.name());
        }
    }
    /**
     * ä¿å­˜æ—§çš„版本,会自动把以前最新版本的哪条数据修改,同时会把老的这条版本修改
     * @param oldModel è€ç‰ˆæœ¬çš„æ•°æ®å¯¹è±¡
     */
    public void saveOldModel(BaseModel oldModel){
        setBtmName(oldModel);
        if (revisionMapper != null) {
            revisionMapper.resetLastRevision(oldModel.getNameOid(),VciBaseUtil.getTableName(oldModel.getBtmname()));
            revisionMapper.resetOldRevision(oldModel.getOid(),VciBaseUtil.getTableName(oldModel.getBtmname()));
        }else{
            throw new VciBaseException("没有初始化版本规则的数据操作层,请开发人员检查maven是否引用");
        }
    }
    /**
     * ä¿å­˜æ—§çš„版次,会自动把以前最新版次的哪条数据修改,同时会把老的这条版次修改
     * @param oldModel è€ç‰ˆæ¬¡çš„æ•°æ®å¯¹è±¡
     */
    public void saveOldModelVersion(BaseModel oldModel){
        setBtmName(oldModel);
        if (revisionMapper != null) {
            revisionMapper.resetLastVersion(oldModel.getNameOid(),oldModel.getRevisionOid(),VciBaseUtil.getTableName(oldModel.getBtmname()));
            revisionMapper.resetOldVersion(oldModel.getOid(),VciBaseUtil.getTableName(oldModel.getBtmname()));
        }else{
            throw new VciBaseException("没有初始化版本规则的数据操作层,请开发人员检查maven是否引用");
        }
    }
    /**
     * å°è£…版本的信息,支持第一个版本的第一个版次,和升版的情况
     * @param newModel æ–°ç‰ˆæœ¬çš„æ•°æ®ï¼Œè¯·å…ˆè¡Œè®¾ç½®ç‰ˆæœ¬è§„则的值在这个对象中
     * @param btmType å¯¹è±¡çš„æ³¨è§£
     * @param lastRevision å½“前最新版本最新版次的对象,是第一个版本的第一个版本时传递null
     */
    public void wrapperRevisionValue(BaseModel newModel,VciBtmType btmType,RevisionInfo lastRevision){
        //没有版本号的时候必须使用编码规则来生成新的版本号
        if (RevisionConstant.CHARACTER.equalsIgnoreCase(newModel.getRevisionRule())) {
            //使用字母这个默认的字符,这个没有前缀,没有后缀,步长为1,没有跳跃字符
            newRevisionForLetter(newModel, lastRevision, btmType != null ? btmType.revisionRulePrefix() : "", btmType != null ? btmType.revisionRuleSubfix() : "");
        } else if (RevisionConstant.NUMBER.equalsIgnoreCase(newModel.getRevisionRule())) {
            newRevisionForNumber(newModel,lastRevision,btmType != null ? btmType.revisionRulePrefix() : "", btmType != null ? btmType.revisionRuleSubfix() : "");
        } else {
            if (revisionRuleProvider != null) {
                try {
                    BaseResult nextRevisionResult = revisionRuleProvider.getNextRevisionValue(newModel.getRevisionRule(), lastRevision==null?"":lastRevision.getRevisionValue());
                    if (nextRevisionResult.isSuccess()) {
                        newModel.setRevisionValue((String) nextRevisionResult.getObj());
                    } else {
                        throw new VciBaseException(nextRevisionResult.getMsg(), nextRevisionResult.getMsgObjs());
                    }
                } catch (Throwable e) {
                    throw new VciBaseException("获取下一个版本号出现了错误,{0}", new String[]{newModel.getRevisionRule()}, e);
                }
            } else {
                throw new VciBaseException("没有初始化版本规则的调用器,请开发人员检查feign");
            }
        }
    }
    /**
     * æ ¹æ®æ•°å­—的规则封装新的版本
     * @param baseModel åŸºç¡€æ•°æ®å¯¹è±¡
     * @param lastRevision æœ€åŽçš„版本对象
     * @param prefix å‰ç¼€
     * @param subfix åŽç¼€
     */
    private void newRevisionForNumber(BaseModel baseModel, RevisionInfo lastRevision,String prefix,String subfix) {
        if(prefix==null){
            prefix = "";
        }
        if(subfix == null){
            subfix = "";
        }
        if(lastRevision == null) {
            //说明是第一个版本
            baseModel.setRevisionValue(prefix + "1" + subfix);
        }else {
            String ruleValue = replacePrefixAndSubfix(lastRevision, prefix, subfix);
            if (ruleValue.matches(RegExpConstant.NUMBER)) {
                //数字可以不停地加
                ruleValue = String.valueOf(Integer.valueOf(ruleValue) + 1);
                baseModel.setRevisionValue(prefix + ruleValue + subfix);
            } else {
                //最后一个版本可能是手动输入的,那就直接找一下最后一排数字,
                if (ruleValue.matches(RegExpConstant.HAS_NUMBER)) {
                    String onlyNumber = getNumbers(ruleValue);
                    String nextNumber = String.valueOf(Integer.valueOf(onlyNumber) + 1);
                    if (ruleValue.startsWith(onlyNumber)) {
                        ruleValue = ruleValue.substring(onlyNumber.length());
                        baseModel.setRevisionValue(prefix + onlyNumber + ruleValue + subfix);
                    } else if (ruleValue.endsWith(onlyNumber)) {
                        ruleValue = ruleValue.substring(0, ruleValue.length() - onlyNumber.length() - 1);
                        baseModel.setRevisionValue(prefix + ruleValue + nextNumber + subfix);
                    } else {
                        baseModel.setRevisionValue(prefix + ruleValue.substring(0, ruleValue.lastIndexOf(onlyNumber)) + nextNumber + ruleValue.substring(ruleValue.lastIndexOf(onlyNumber) + 1) + subfix);
                    }
                } else {
                    //一个数字都没有
                    baseModel.setRevisionValue(prefix + ruleValue + "1" + subfix);
                }
            }
        }
    }
    /**
     * èŽ·å–å­—ç¬¦ä¸²ä¸­çš„æ•°å­—éƒ¨åˆ†
     * @param content å­—符串内容
     * @return æ•°å­—的部分,最后的那部分
     */
    private String getNumbers(String content) {
        Pattern pattern = Pattern.compile("\\d+");
        Matcher matcher = pattern.matcher(content);
        while (matcher.find()) {
            return matcher.group(matcher.groupCount()-1);
        }
        return "";
    }
    /**
     * æ›¿æ¢å‰ç¼€å’ŒåŽç¼€
     * @param lastRevision æœ€åŽç‰ˆæœ¬çš„对象
     * @param prefix å‰ç¼€
     * @param subfix åŽç¼€
     * @return åŽ»é™¤å‰ç¼€å’ŒåŽç¼€çš„ç‰ˆæœ¬è§„åˆ™
     */
    private String replacePrefixAndSubfix(RevisionInfo lastRevision,String prefix,String subfix){
        String ruleValue = lastRevision.getRevisionValue();
        if(prefix==null){
            prefix = "";
        }
        if(subfix == null){
            subfix = "";
        }
        if(StringUtils.isNotBlank(prefix) && ruleValue.startsWith(prefix)){
            ruleValue = ruleValue.substring(prefix.length());
        }
        if(StringUtils.isNotBlank(subfix) && ruleValue.endsWith(subfix)){
            ruleValue = ruleValue.substring(0,ruleValue.length()-subfix.length()-1);
        }
        return ruleValue;
    }
    /**
     * æ ¹æ®å­—母的规则封装新的版本
     * @param baseModel åŸºç¡€æ•°æ®å¯¹è±¡
     * @param lastRevision æœ€åŽçš„版本对象
     * @param prefix å‰ç¼€
     * @param subfix åŽç¼€
     */
    private void newRevisionForLetter(BaseModel baseModel,RevisionInfo lastRevision,String prefix,String subfix){
        if(prefix==null){
            prefix = "";
        }
        if(subfix == null){
            subfix = "";
        }
        if(lastRevision == null){
            //说明是第一个版本
            baseModel.setRevisionValue(prefix + "A" + subfix);
        }else {
            String ruleValue = replacePrefixAndSubfix(lastRevision, prefix, subfix);
            if (ruleValue.matches(RegExpConstant.LETTER)) {
                //从A到ZZ的形式
                String lastLetter = ruleValue.substring(ruleValue.length() - 1);
                if (lastLetter.equalsIgnoreCase("Z")) {
                    if (lastRevision.getRevisionValue().length() == 1) {
                        baseModel.setRevisionValue(prefix + "AA" + subfix);
                    } else {
                        lastLetter = ruleValue.substring(ruleValue.length() - 2, ruleValue.length() - 1);
                        lastLetter = String.valueOf((char) (lastLetter.toCharArray()[0] + 1));
                        baseModel.setRevisionValue(prefix + ruleValue.substring(0, ruleValue.length() - 2) + lastLetter + subfix);
                    }
                } else {
                    lastLetter = String.valueOf((char) (lastLetter.toCharArray()[0] + 1));
                    baseModel.setRevisionValue(prefix + ruleValue.substring(0, ruleValue.length() - 1) + lastLetter + subfix);
                }
            } else {
                //最后一个版本可能是手动输入的,如果我们之间存储A的话,可能会造成重复,最后一位是字母就在该字母上加1,最后一位不是字母,就原值上加A
                String lastLetter = ruleValue.substring(ruleValue.length() - 1);
                if (lastLetter.matches(RegExpConstant.LETTER)) {
                    lastLetter = String.valueOf((char) (lastLetter.toCharArray()[0] + 1));
                    baseModel.setRevisionValue(prefix + ruleValue.substring(0, ruleValue.length() - 1) + lastLetter + subfix);
                } else {
                    baseModel.setRevisionValue(prefix + ruleValue + "A" + subfix);
                }
            }
        }
    }
    /**
     * å°è£…某个版本的第一个版次
     * @param baseModel æ•°æ®å¯¹è±¡
     */
    public void wrapperFristVersion(BaseModel baseModel){
        VciBaseUtil.alertNotNull(baseModel,"数据对象");
        VciBtmType btmType = getBtmTypeAnnotation(baseModel);
        if(isManageVersion(btmType)) {
            //只支持从0,1,或者字母A开始
            if (StringUtils.isBlank(baseModel.getVersionRule())) {
                baseModel.setVersionRule(btmType.versionRule().getValue());
            }
            if (btmType.versionRule().equals(VciBtmType.VciBtmTypeVersionRule.INTSTART0)) {
                baseModel.setVersionValue("0");
            } else if (btmType.versionRule().equals(VciBtmType.VciBtmTypeVersionRule.INTSTART1)) {
                baseModel.setVersionValue("1");
            } else {
                baseModel.setVersionValue("A");
            }
        }
        baseModel.setVersionSeq(1);
        baseModel.setFirstV("1");
        baseModel.setLastV("1");
    }
    /**
     * å°è£…第一个版本的第一个版次
     * @param baseModel æ–°å¢žçš„æ•°æ®å¯¹è±¡ï¼ˆç¬¬ä¸€ä¸ªç‰ˆæœ¬çš„第一个版次
     */
    public void wrapperFristRevision(BaseModel baseModel){
        VciBaseUtil.alertNotNull(baseModel,"数据对象");
        //需要先判断是否控制版本
        VciBtmType btmType = getBtmTypeAnnotation(baseModel);
        if(isManageRevision(btmType)) {
            if (StringUtils.isBlank(baseModel.getOid())) {
                baseModel.setOid(VciBaseUtil.getPk());
            }
            //第一个版本的第一个版次
            if (StringUtils.isBlank(baseModel.getNameOid())) {
                baseModel.setNameOid(VciBaseUtil.getPk());
            }
            if (StringUtils.isBlank(baseModel.getRevisionOid())) {
                baseModel.setRevisionOid(VciBaseUtil.getPk());
            }
            //第一个版本
            if (btmType != null) {
                baseModel.setRevisionRule(btmType.revisionRule());
                baseModel.setVersionValue(btmType.versionRule().getValue());
            } else {
                throw new VciBaseException("没有VciBtmType注解,{0}");
            }
            //根据版本规则生成版本号
            //3.版本号
            //版本号为空,只能是手动后输入的时候,应该是错误
            //其他情况下版本号为空都设置版本号
            if (StringUtils.isBlank(baseModel.getRevisionValue() )&& isInputRevision(baseModel) && StringUtils.isBlank(baseModel.getRevisionRule())){
                //不处理
            }else {
                if (StringUtils.isBlank(baseModel.getRevisionValue())) {
                    wrapperRevisionValue(baseModel, btmType, null);
                }
            }
            //如果有版次,那这个就是新版本的第一个版次
            if (StringUtils.isNotBlank(baseModel.getVersionRule()) && StringUtils.isBlank(baseModel.getVersionValue())) {
                wrapperFristVersion(baseModel);
            } else {
                baseModel.setFirstV("1");
                baseModel.setLastV("1");
            }
            //4.版本顺序
            baseModel.setRevisionSeq(1);
            baseModel.setFirstR("1");
            baseModel.setLastR("1");
        }
    }
    /**
     * å°è£…生命周期
     * @param baseModel æ•°æ®å¯¹è±¡
     */
    public void wrapperLifeCycle(BaseModel baseModel){
        VciBaseUtil.alertNotNull(baseModel,"数据对象");
        VciBtmType btmType = getBtmTypeAnnotation(baseModel);
        if(StringUtils.isBlank(baseModel.getLcStatus()) &&isManageLifeCycle(btmType) ){
            //开始的时候获取生命周期的初始状态
            if(StringUtils.isNotBlank(btmType.startStatus())){
                baseModel.setLcStatus(btmType.startStatus());
            }else {
                if (lifeCycleProvider != null) {
                    try {
                        BaseResult lifeCycleResult = lifeCycleProvider.getStartStatus(btmType.lifeCycle());
                        if (lifeCycleResult.isSuccess()) {
                            baseModel.setLcStatus((String) lifeCycleResult.getObj());
                        } else {
                            throw new VciBaseException(lifeCycleResult.getMsg(), lifeCycleResult.getMsgObjs());
                        }
                    } catch (Throwable e) {
                        throw new VciBaseException("调用【生命周期】服务获取初始状态时出错,{0}", new String[]{btmType.lifeCycle()}, e);
                    }
                } else {
                    throw new VciBaseException("没有初始化生命周期的调用器,请开发人员检查feign");
                }
            }
        }
    }
    /**
     * æ˜¯å¦ç®¡ç†ç”Ÿå‘½å‘¨æœŸ
     * @param baseModel æ•°æ®å¯¹è±¡
     * @return true表示管理
     */
    public boolean isManageLifeCycle(BaseModel baseModel){
        VciBtmType btmType = getBtmTypeAnnotation(baseModel);
        return isManageLifeCycle(btmType);
    }
    /**
     * æ˜¯å¦ç®¡ç†ç”Ÿå‘½å‘¨æœŸ
     * @param btmType ä¸šåŠ¡ç±»åž‹æ³¨è§£
     * @return true表示管理
     */
    public boolean isManageLifeCycle(VciBtmType btmType){
        if(btmType !=null && (StringUtils.isNotBlank(btmType.lifeCycle()) && !"defaultLC".equalsIgnoreCase(btmType.lifeCycle()))){
            return true;
        }else{
            return false;
        }
    }
    /**
     * æ˜¯å¦ç®¡ç†ç‰ˆæœ¬
     * @param baseModel æ•°æ®å¯¹è±¡
     * @return true è¡¨ç¤ºç®¡ç†ç‰ˆæœ¬
     */
    public boolean isManageRevision(BaseModel baseModel){
        VciBtmType btmType = getBtmTypeAnnotation(baseModel);
        return isManageRevision(btmType);
    }
    /**
     * æ˜¯å¦ç®¡ç†ç‰ˆæœ¬
     * @param btmType ä¸šåŠ¡ç±»åž‹çš„æ³¨è§£
     * @return true è¡¨ç¤ºç®¡ç†ç‰ˆæœ¬
     */
    public boolean isManageRevision(VciBtmType btmType){
        if(btmType !=null && (btmType.revisionRuleInput() || StringUtils.isNotBlank(btmType.revisionRule()))){
            return true;
        }
        return false;
    }
    /**
     * æ˜¯å¦ç®¡ç†ç‰ˆæ¬¡ï¼Œå¿…须管理版本才可以管理版次
     * @param baseModel æ•°æ®å¯¹è±¡
     * @return true è¡¨ç¤ºç®¡ç†ç‰ˆæœ¬
     */
    public boolean isManageVersion(BaseModel baseModel){
        VciBtmType btmType = getBtmTypeAnnotation(baseModel);
        return isManageVersion(btmType);
    }
    /**
     * æ˜¯å¦ç®¡ç†ç‰ˆæ¬¡ï¼Œå¿…须管理版本才可以管理版次
     * @param btmType ä¸šåŠ¡ç±»åž‹çš„æ³¨è§£
     * @return true è¡¨ç¤ºç®¡ç†ç‰ˆæœ¬
     */
    public boolean isManageVersion(VciBtmType btmType){
        if(isManageRevision(btmType) && !btmType.versionRule().equals(VciBtmType.VciBtmTypeVersionRule.NONE)){
            return true;
        }
        return false;
    }
    /**
     * æ˜¯å¦å¯ä»¥æ‰‹åŠ¨è¾“å…¥ç‰ˆæœ¬å·
     * @param baseModel åŸºæœ¬æ•°æ®å¯¹è±¡
     * @return true允许手动输入版本号
     */
    public boolean isInputRevision(BaseModel baseModel) {
        VciBtmType btmType = getBtmTypeAnnotation(baseModel);
        return isInputRevision(btmType);
    }
    /**
     * æ˜¯å¦å¯ä»¥æ‰‹åŠ¨è¾“å…¥ç‰ˆæœ¬å·
     * @param btmType ä¸šåŠ¡ç±»åž‹çš„æ³¨è§£
     * @return true允许手动输入版本号
     */
    public boolean isInputRevision(VciBtmType btmType) {
        if(btmType !=null && btmType.revisionRuleInput()){
            return true;
        }
        return false;
    }
    /**
     * èŽ·å–æ•°æ®å¯¹è±¡ä¸Šçš„æ³¨è§£
     * @param baseModel æ•°æ®å¯¹è±¡
     * @return ä¸å­˜åœ¨æ³¨è§£çš„æ—¶å€™ä¼šè¿”回null
     */
    public VciBtmType getBtmTypeAnnotation(BaseModel baseModel){
        VciBaseUtil.alertNotNull(baseModel,"数据对象");
        return getBtmTypeAnnotation(baseModel.getClass());
    }
    /**
     * èŽ·å–DO对象上的注解
     * @param doClass do对象的类
     * @return ä¸å­˜åœ¨æ³¨è§£çš„æ—¶å€™ä¼šè¿”回null
     */
    public VciBtmType getBtmTypeAnnotation(Class<?> doClass){
        VciBaseUtil.alertNotNull(doClass,"要校验业务类型的类");
        if(modelAnnotationMap.containsKey(doClass.getName())){
            return modelAnnotationMap.get(doClass.getName());
        }
        if(doClass.isAnnotationPresent(VciBtmType.class)){
            VciBtmType btmType =  (VciBtmType)doClass.getAnnotation(VciBtmType.class);
            if(btmType == null){
                btmType = doClass.getDeclaredAnnotation(VciBtmType.class);
            }
            modelAnnotationMap.put(doClass.getName(),btmType);
            return btmType;
        }
        return null;
    }
    /**
     * å°è£…树形数据查询器.这个方法被废弃,改为 VciQueryWrapperForDO里的 parentQueryChild
     * @param treeQueryObject æ ‘形查询对象
     * @param doClass å®žä½“的类
     * @param parentFieldName ä¸Šçº§å±žæ€§çš„字段
     * @return æŸ¥è¯¢å°è£…器
     */
    @Deprecated
    public VciQueryWrapperForDO wrapperForTree(TreeQueryObject treeQueryObject,Class<?> doClass,String parentFieldName){
        if(doClass == null){
            throw new VciBaseException("数据对象所属的类不能为空,不能封装树形查询器");
        }
        if (treeQueryObject == null){
            treeQueryObject = new TreeQueryObject();
        }
        VciQueryWrapperOption queryWrapperOption = new VciQueryWrapperOption();
        if(treeQueryObject.isQueryAllRev()){
            queryWrapperOption.setThisObjectQueryLastRevision(false);
            queryWrapperOption.setThisObjectQueryRelease(false);
        }
        VciQueryWrapperForDO queryWrapper = new VciQueryWrapperForDO(treeQueryObject.getConditionMap(),doClass,new PageHelper(-1),true,queryWrapperOption);
        if(StringUtils.isBlank(parentFieldName)){
            return queryWrapper;
        }
        if(StringUtils.isNotBlank(treeQueryObject.getParentOid()) ){
            //说明传递了上级的
            if(treeQueryObject.isQueryAllLevel()){
                //全部的层级都要查询,我们使用start with先查询出结果后,再匹配查询条件
                queryWrapper.in(queryWrapper.getOidFieldName(), "select " + queryWrapper.getOidFieldName() + " from " + queryWrapper.getTableName()
                        + " start with " + parentFieldName + " = '" + treeQueryObject.getParentOid().trim()
                        + "' connect by prior " + queryWrapper.getOidFieldName() + " = " +  parentFieldName );
            }else {
                queryWrapper.eq(parentFieldName, treeQueryObject.getParentOid());
            }
        }else{
            if(treeQueryObject.isQueryAllLevel()){
                //全部的层级都要查询,我们使用start with先查询出结果后,再匹配查询条件
                queryWrapper.in(queryWrapper.getOidFieldName(), "select " + queryWrapper.getOidFieldName() + "  from " + queryWrapper.getTableName() + " start with " + parentFieldName
                        + " is null connect by prior " + queryWrapper.getOidFieldName() + " = " + parentFieldName );
            }else{
                queryWrapper.isNull(parentFieldName);
            }
        }
        return  queryWrapper;
    }
    /**
     * å°†æ•°æ®å¯¹è±¡è½¬æ¢ä¸ºæ ‘å½¢
     * @param doList æ•°æ®å¯¹è±¡
     * @param wrapperOptions å°è£…的信息
     * @return æ ‘列表
     */
    public <T,R> List<Tree> doList2Trees(List<T> doList, TreeWrapperOptions wrapperOptions, Function<T,R> f){
        if(CollectionUtils.isEmpty(doList)){
            return new ArrayList<>();
        }
        List<Tree> allTree = new ArrayList<Tree>();
        List<Tree> children = new ArrayList<Tree>();
        for (T doObject: doList) {
            Tree tree =new Tree();
            List<String> oidFieldNames = VciBaseUtil.str2List(wrapperOptions.getOidFieldName());
            List<String> oidValues = new LinkedList<>();
            oidFieldNames.stream().forEach( s->{
                oidValues.add(VciBaseUtil.getStringValueFromObject(VciBaseUtil.getValueFromField(s,doObject)));
            });
            tree.setOid(oidValues.stream().collect(Collectors.joining(wrapperOptions.getOidValueSep())));
            if(f !=null){
                tree.setText((String)f.apply(doObject));
            }else{
                List<String> textFieldNames = VciBaseUtil.str2List(wrapperOptions.getTextFieldName());
                List<String> textValues = new LinkedList<>();
                textFieldNames.stream().forEach( s->{
                    textValues.add(VciBaseUtil.getStringValueFromObject(VciBaseUtil.getValueFromField(s,doObject)));
                });
                tree.setText(textValues.stream().collect(Collectors.joining(wrapperOptions.getTextValueSep())));
            }
            if(StringUtils.isNotBlank(wrapperOptions.getParentFieldName())){
                tree.setParentId(VciBaseUtil.getStringValueFromObject(VciBaseUtil.getValueFromField(wrapperOptions.getParentFieldName(),doObject)));
            }
            if(wrapperOptions.isAllAttributes()) {
                try {
                    tree.setAttributes(VciBaseUtil.objectToMapString(doObject));
                } catch (Exception e) {
                    //这里不做处理
                    if (logger.isErrorEnabled()) {
                        logger.error("把对象转换为map时出现了错误,但是不影响树的展示,对业务可能有影响");
                    }
                }
            }
            if(wrapperOptions.isMultipleSelect() || wrapperOptions.isShowCheckBox()){
                tree.setShowCheckbox(true);
            }
            if(wrapperOptions.getParentOid() == null){
                wrapperOptions.setParentOid("");
            }
            if(StringUtils.isBlank(tree.getParentId())
                    || (StringUtils.isNotBlank(wrapperOptions.getParentOid()) && wrapperOptions.getParentOid().equalsIgnoreCase(tree.getParentId()))){
                allTree.add(tree);
            }else {
                children.add(tree);
            }
        }
        new Tree().findChild(allTree,children);
        if(allTree.size()<=0){
            allTree.addAll(children);
        }
        return allTree;
    }
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/revision/service/VciRevisionServiceI.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,104 @@
package com.vci.starter.revision.service;
import com.vci.starter.revision.model.*;
/**
 * ç‰ˆæœ¬å¤„理所需要的sql操作。因为要查询数据库,所以放到dataBase这个starter中
 * @author weidy
 * @date 2020/4/15
 */
public interface VciRevisionServiceI {
    /**
     * èŽ·å–æœ€åŽä¸€ä¸ªç‰ˆæœ¬çš„ä¿¡æ¯
     * @param nameOid å¯¹è±¡ä¸»é”®
     * @param tableName æ•°æ®åº“表格
     * @return æœ€åŽä¸€ä¸ªç‰ˆæœ¬ä¿¡æ¯ï¼Œå®ƒä¸ä¸€å®šæ˜¯å‘布的版本
     */
    RevisionInfo selectLastRevision(String nameOid,String tableName);
    /**
     * èŽ·å–æœ€åŽä¸€ä¸ªç‰ˆæ¬¡çš„ä¿¡æ¯
     * @param nameOid å¯¹è±¡çš„主键
     * @param revisionOid ç‰ˆæœ¬çš„主键
     * @param tableName æ•°æ®åº“表格
     * @return
     */
    RevisionInfo selectLastVersion(String nameOid, String revisionOid,String tableName);
    /**
     * èŽ·å–å·²å‘å¸ƒçš„ç‰ˆæœ¬çš„æ•°æ®å€¼
     * @param nameOid å¯¹è±¡çš„主键
     * @param btmName ä¸šåŠ¡ç±»åž‹çš„åç§°
     * @param tableName æ•°æ®åº“表格
     * @return ç‰ˆæœ¬ä¿¡æ¯
     */
    RevisionInfo selectRelease(String nameOid, String btmName, String tableName);
    /**
     * æ·»åŠ å‘å¸ƒçš„æ•°æ®,如果存在则更新,如果不存在则插入
     * @param releasedObj å‘布版本的数据
     * @return å—影响的行数
     */
    int saveReleased(ReleasedObjDO releasedObj);
    /**
     * æŠŠæœ€åŽä¸€ä¸ªç‰ˆæœ¬é‡ç½®isLastR
     * @param nameOid å¯¹è±¡çš„主键
     * @param tableName è¡¨æ ¼åç§°
     * @return å—影响的行数
     */
    int resetLastRevision(String nameOid,String tableName);
    /**
     * é‡ç½®è€ç‰ˆæœ¬çš„isLastR
     * @param oid è€ç‰ˆæœ¬çš„主键
     * @param tableName è¡¨æ ¼åç§°
     * @return å—影响的行数
     */
    int resetOldRevision(String oid,String tableName);
    /**
     * é€šè¿‡è€ç‰ˆæœ¬çš„主键来获取版本信息
     * @param copyFromVersion æ–°ç‰ˆæœ¬ä½¿ç”¨çš„老版本的主键
     * @param tableName è¡¨æ ¼åç§°
     * @return ç‰ˆæœ¬ä¿¡æ¯
     */
    RevisionInfo selectByOid(String copyFromVersion,String tableName);
    /**
     * é‡ç½®ä»¥å‰çš„æœ€æ–°ç‰ˆæ¬¡
     * @param nameOid å¯¹è±¡çš„主键
     * @param revisionOid ç‰ˆæœ¬çš„主键
     * @param tableName è¡¨æ ¼åç§°
     * @return å—影响的行数
     */
    int resetLastVersion(String nameOid, String revisionOid,String tableName);
    /**
     * é‡ç½®è€ç‰ˆæ¬¡ï¼ˆå®ƒä¸ä¸€å®šæ˜¯æœ€æ–°çš„)
     * @param oid è€ç‰ˆæ¬¡çš„主键
     * @param tableName è¡¨æ ¼åç§°
     * @return å—影响的行数
     */
    int resetOldVersion(String oid,String tableName);
    /**
     * æŸ¥è¯¢å±žæ€§ç­‰äºŽæŸä¸ªå€¼çš„æ•°æ®æ¡æ•°ï¼Œå¸¸ç”¨äºŽåˆ¤æ–­æ•°æ®æ˜¯å¦é‡å¤
     * @param key å±žæ€§çš„名称
     * @param value å±žæ€§çš„值
     * @param tableName è¡¨æ ¼çš„名称
     * @return ä¸ªæ•°
     */
    int countByProperties(String key,Object value,String tableName);
    /**
     * æŸ¥è¯¢å±žæ€§ç­‰äºŽæŸä¸ªå€¼å¹¶ä¸”不是某个主键的数据条数,常用于修改数据时判断数据是否重复
     * @param key å±žæ€§çš„名称
     * @param value å±žæ€§çš„值
     * @param tableName è¡¨æ ¼çš„名称
     * @param oid ä¸»é”®
     * @return æ•°æ®ä¸ªæ•°
     */
    int countByPropertiesNotIncludeSelf(String key,Object value,String tableName,String oid);
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/undo/bo/UndoTaskBO.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,63 @@
package com.vci.starter.undo.bo;
import com.vci.starter.web.pagemodel.SessionInfo;
/**
 * å¾…办任务的内容
 * @author weidy
 * @date 2022/8/1
 */
public class UndoTaskBO implements java.io.Serializable{
    /**
     * åºåˆ—化
     */
    private static final long serialVersionUID = -4189123149238900765L;
    /**
     * ç”¨æˆ·çš„会话信息
     */
    private SessionInfo sessionInfo;
    /**
     * é»˜è®¤çš„访问路径前缀,我们自行决定的
     */
    private String defaultUrl;
    /**
     * ä»»åŠ¡çš„ç±»åž‹
     */
    private String taskType;
    public SessionInfo getSessionInfo() {
        return sessionInfo;
    }
    public void setSessionInfo(SessionInfo sessionInfo) {
        this.sessionInfo = sessionInfo;
    }
    public String getDefaultUrl() {
        return defaultUrl;
    }
    public void setDefaultUrl(String defaultUrl) {
        this.defaultUrl = defaultUrl;
    }
    public String getTaskType() {
        return taskType;
    }
    public void setTaskType(String taskType) {
        this.taskType = taskType;
    }
    @Override
    public String toString() {
        return "UndoTaskBO{" +
                "sessionInfo=" + sessionInfo +
                ", defaultUrl='" + defaultUrl + '\'' +
                ", taskType='" + taskType + '\'' +
                '}';
    }
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/undo/query/UndoTaskQuery.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,147 @@
package com.vci.starter.undo.query;
import com.vci.starter.web.pagemodel.SessionInfo;
/**
 * å¾…办任务的查询对象
 * @author weidy
 * @date 2022/8/1
 */
public class UndoTaskQuery implements java.io.Serializable{
    /**
     * åºåˆ—化
     */
    private static final long serialVersionUID = 6668428964443134603L;
    /**
     * å½“前页
     */
    private Integer page;
    /**
     * æŸ¥è¯¢
     */
    private String title;
    /**
     * æ¯é¡µæ˜¾ç¤ºé¡µæ•°
     */
    private Integer limit = 25;
    /**
     * å¼€å§‹æ—¶é—´
     */
    private String startTime;
    /**
     * å¼€å§‹æ—¶é—´-起始
     */
    private String startTime_begin;
    /**
     * å¼€å§‹æ—¶é—´-终止
     */
    private String startTime_end;
    /**
     * ç»“束时间
     */
    private String endTime;
    /**
     * ç»“束时间--起始
     */
    private String endTime_begin;
    /**
     * ç»“束时间--终止
     */
    private String endTime_end;
    public Integer getPage() {
        return page;
    }
    public void setPage(Integer page) {
        this.page = page;
    }
    public String getTitle() {
        return title;
    }
    public void setTitle(String title) {
        this.title = title;
    }
    public Integer getLimit() {
        return limit;
    }
    public void setLimit(Integer limit) {
        this.limit = limit;
    }
    public String getStartTime() {
        return startTime;
    }
    public void setStartTime(String startTime) {
        this.startTime = startTime;
    }
    public String getStartTime_begin() {
        return startTime_begin;
    }
    public void setStartTime_begin(String startTime_begin) {
        this.startTime_begin = startTime_begin;
    }
    public String getStartTime_end() {
        return startTime_end;
    }
    public void setStartTime_end(String startTime_end) {
        this.startTime_end = startTime_end;
    }
    public String getEndTime() {
        return endTime;
    }
    public void setEndTime(String endTime) {
        this.endTime = endTime;
    }
    public String getEndTime_begin() {
        return endTime_begin;
    }
    public void setEndTime_begin(String endTime_begin) {
        this.endTime_begin = endTime_begin;
    }
    public String getEndTime_end() {
        return endTime_end;
    }
    public void setEndTime_end(String endTime_end) {
        this.endTime_end = endTime_end;
    }
    @Override
    public String toString() {
        return "UndoTaskQuery{" +
                ", page=" + page +
                ", title='" + title + '\'' +
                ", limit=" + limit +
                ", startTime='" + startTime + '\'' +
                ", startTime_begin='" + startTime_begin + '\'' +
                ", startTime_end='" + startTime_end + '\'' +
                ", endTime='" + endTime + '\'' +
                ", endTime_begin='" + endTime_begin + '\'' +
                ", endTime_end='" + endTime_end + '\'' +
                "} " + super.toString();
    }
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/undo/vo/UndoTaskVO.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,145 @@
package com.vci.starter.undo.vo;
/**
 * å¾…办的信息
 * @author weidy
 * @date 2022/8/1
 */
public class UndoTaskVO implements java.io.Serializable{
    /**
     * åºåˆ—化
     */
    private static final long serialVersionUID = 393050238018013429L;
    /**
     * ä¸»é”®--可以为空
     */
    private String oid;
    /**
     * ä»»åŠ¡çš„åç§°
     */
    private String taskName;
    /**
     * å¤„理人姓名
     */
    private String appSendName;
    /**
     * ä»»åŠ¡çš„ç±»åž‹
     */
    private String taskType;
    /**
     * å‘送时间
     */
    private String sendTime;
    /**
     * ç»“束时间-可能为空
     */
    private String endTime;
    /**
     * ç´§æ€¥ç¨‹åº¦ï¼Œ0-特急,1-紧急,2:-一般,
     */
    private Integer priority = 2;
    /**
     * å¾…办的任务地址
     */
    private String url;
    /**
     * å¾…办的描述
     */
    private String taskDesc;
    public String getOid() {
        return oid;
    }
    public void setOid(String oid) {
        this.oid = oid;
    }
    public String getTaskName() {
        return taskName;
    }
    public void setTaskName(String taskName) {
        this.taskName = taskName;
    }
    public String getAppSendName() {
        return appSendName;
    }
    public void setAppSendName(String appSendName) {
        this.appSendName = appSendName;
    }
    public String getTaskType() {
        return taskType;
    }
    public void setTaskType(String taskType) {
        this.taskType = taskType;
    }
    public String getSendTime() {
        return sendTime;
    }
    public void setSendTime(String sendTime) {
        this.sendTime = sendTime;
    }
    public String getEndTime() {
        return endTime;
    }
    public void setEndTime(String endTime) {
        this.endTime = endTime;
    }
    public Integer getPriority() {
        return priority;
    }
    public void setPriority(Integer priority) {
        this.priority = priority;
    }
    public String getUrl() {
        return url;
    }
    public void setUrl(String url) {
        this.url = url;
    }
    public String getTaskDesc() {
        return taskDesc;
    }
    public void setTaskDesc(String taskDesc) {
        this.taskDesc = taskDesc;
    }
    @Override
    public String toString() {
        return "UndoTaskVO{" +
                "oid='" + oid + '\'' +
                ", taskName='" + taskName + '\'' +
                ", appSendName='" + appSendName + '\'' +
                ", taskType='" + taskType + '\'' +
                ", sendTime='" + sendTime + '\'' +
                ", endTime='" + endTime + '\'' +
                ", priority=" + priority +
                ", url='" + url + '\'' +
                ", taskDesc='" + taskDesc + '\'' +
                '}';
    }
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/annotation/Column.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,101 @@
package com.vci.starter.web.annotation;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
 * æ•°æ®åº“的字段映射,对象与BO属性映射
 * @author weidy
 *
 */
@Target({ java.lang.annotation.ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Column {
    /**
     * åç§°ï¼Œå¦‚果相同(不区分大小写)可以不输入
     * @return é»˜è®¤ä¸ºç©º
     */
     String name() default "";
    /**
     * æ˜¯å¦å”¯ä¸€
     * @return é»˜è®¤ä¸å”¯ä¸€
     */
     boolean unique() default false;
    /**
     * æ ¡éªŒå”¯ä¸€çš„æ—¶å€™ï¼Œä¸åŒºåˆ†å¤§å°å†™
     * @return é»˜è®¤åŒºåˆ†
     */
     boolean unUniqueCase() default  false;
    /**
     * æ˜¯å¦å¯ä»¥ä¸ºç©º true表示可以为空;false表示不能为空
     * @return é»˜è®¤å¯ä»¥ä¸ºç©º
     */
    boolean nullable() default true;
    /**
     * æè¿°
     * @return é»˜è®¤ä¸ºç©º
     */
     String columnDefinition() default "";
    /**
     * é•¿åº¦
     * @return é»˜è®¤ä¸º0
     */
     int length() default 0;
    /**
     * ç²¾åº¦
     * @return é»˜è®¤ä¸º0
     */
    int precision() default 0;
    /**
     * åˆ»åº¦-double使用
     * @return é»˜è®¤ä¸º2
     */
    int scale() default 2;
    /**
     * å‚照字段显示的字段
     * @return é»˜è®¤ä¸ºç©º
     */
    String showTextField() default "";
    /**
     * ä½¿ç”¨æžšä¸¾
     * @return æžšä¸¾çš„英文名称
     */
     String useEnum() default "";
    /**
     * ä½¿ç”¨å‚ç…§
     * @return å¼•用的业务类型的英文名称
     */
    String useRefer() default "";
    /**
     * å€¼èŒƒå›´
     * @return å¤šä¸ªèŒƒå›´çš„值
     */
     String[] range() default "";
    /**
     * é»˜è®¤å€¼ï¼Œå¦‚果是日期或者数字形式的时候,也直接转换字符串
     * @return é»˜è®¤ä¸ºç©º
     */
    String defaultValue() default "";
    /**
     * ä½¿ç”¨å…¶ä»–参照字段的关联属性
     * @return é»˜è®¤ä¸ºç©º
     */
    String referColumnName() default "";
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/annotation/Id.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,11 @@
package com.vci.starter.web.annotation;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({java.lang.annotation.ElementType.TYPE, java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Id {
    boolean value() default true;
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/annotation/LifeCycleEvent.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,26 @@
package com.vci.starter.web.annotation;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
 * ç”Ÿå‘½å‘¨æœŸäº‹ä»¶å®šä¹‰
 * @author weidy
 */
@Target({java.lang.annotation.ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface LifeCycleEvent {
    /**
     * äº‹ä»¶æ˜¾ç¤ºæ–‡æœ¬
     * @return
     */
    String text() ;
    /**
     * äº‹ä»¶æè¿°
     * @return
     */
    String description() default "";
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/annotation/SOAService.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,32 @@
package com.vci.starter.web.annotation;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
 * æœåŠ¡ç«¯å®šä¹‰ï¼Œç”¨æˆ·è®¾ç½®corba等服务的名称,默认为使用这个注解的类的首字母小写
 * @author weidy
 */
@Target({java.lang.annotation.ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface SOAService {
    /**
     * æœåŠ¡çš„åå­—
     * @return æœåŠ¡çš„åç§°ï¼Œå¦‚æžœæ²¡æœ‰è®¾ç½®é»˜è®¤ä¸ºæ³¨è§£ç±»çš„é¦–å­—æ¯å°å†™
     */
    String value() default "";
    /**
     * æœåŠ¡çš„ç±»åž‹
     * @return æœåŠ¡ç±»åž‹æžšä¸¾
     */
    SOASericeType serviceType() default SOASericeType.CORBA;
    /**
     * æœåŠ¡çš„ç±»åž‹æžšä¸¾å®šä¹‰
     */
    public static enum SOASericeType{
        CORBA,THRIFT,WEBSERVICE,SOCKET
    }
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/annotation/Transient.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,23 @@
package com.vci.starter.web.annotation;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({java.lang.annotation.ElementType.TYPE, java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Transient {
    boolean value() default true;
    /**
     * å‚照列或者枚举列;参照的列为xxx.name;枚举列为枚举编号_枚举值的属性
     * @return
     */
    String referColumn() default "";
    /**
     * å…³è”的值的字段,默认为oid
     * @return å­—段的名称
     */
    String valueField() default "oid";
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/annotation/VciBtmType.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,143 @@
package com.vci.starter.web.annotation;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({java.lang.annotation.ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface VciBtmType {
    /**
     * è‹±æ–‡åç§°
     * @return è‹±æ–‡åç§°
     */
    String name() default "";
    /**
     * æ˜¾ç¤ºæ–‡æœ¬
     * @return æ˜¾ç¤ºæ–‡æœ¬
     */
    String text() default "";
    /**
     * æè¿°
     * @return æè¿°
     */
    String description() default "";
    /**
     * è¡¨æ ¼åç§°
     * @return è¡¨æ ¼åç§°
     */
    String tableName() default "";
    /**
     *是否可以手动输入版本
     * @return true表示手动输入版本
     */
    boolean revisionRuleInput() default false;
    /**
     * ç‰ˆæœ¬è§„则
     * @return ç‰ˆæœ¬è§„程
     */
    String revisionRule() default "";
    /**
     *  ç‰ˆæ¬¡å·è§„则
     * @return ç‰ˆæ¬¡å·è§„则
     */
    VciBtmTypeVersionRule versionRule() default VciBtmTypeVersionRule.NONE;
    /**
     * å½“是字母和数字的规则的时候,可以设置前缀
     * @return å‰ç¼€
     */
    String revisionRulePrefix() default "";
    /**
     * å½“是字母和数字的规则的时候,可以设置后缀
     * @return åŽç¼€çš„值
     */
    String revisionRuleSubfix() default "";
    /**
     * æ‰€å±žç”Ÿå‘½å‘¨æœŸ
     * @return ä¸»ç”Ÿå‘½å‘¨æœŸ
     */
    String lifeCycle() ;
    /**
     * ç”Ÿå‘½å‘¨æœŸçš„初始的值,这个注解的优先级大于生命周期的起始状态
     * @return åˆå§‹çŠ¶æ€ï¼Œä¼˜å…ˆçº§æœ€é«˜
     */
    String startStatus() default "";
    /**
     * å¤‡ç”¨ç”Ÿå‘½å‘¨æœŸ
     * @return å¤‡ç”¨ç”Ÿå‘½å‘¨æœŸåˆ—表或者空
     */
    String[] subLifeCycle() default "";
    /**
     * æ˜¯å¦ç®¡ç†å¯†çº§
     * @return true表示需要管理
     */
    boolean secretAble() default false;
    /**
     * æ˜¯å¦å…¼å®¹ä»¥å‰çš„平台
     * @return true表示兼容,会对默认的属性有不同的处理
     */
    boolean compatbility() default false;
    /**
     * ä¸Šçº§çš„字段名字
     * @return ä¸Šçº§å­—段
     */
    String parentField() default "";
    /**
     * ç‰ˆæ¬¡ç‰ˆæœ¬çš„æžšä¸¾
     */
    public enum VciBtmTypeVersionRule {
        /**
         * ä»Ž1开始的自然数
         */
        INTSTART1("int1"),
        /**
         * ä»Ž0开的自然数
         */
        INTSTART0("int0"),
        /**
         * ä¸ä½¿ç”¨ç‰ˆæ¬¡
         */
        NONE("none"),
        /**
         * å¤§å†™å­—母A开始
         */
        LETTER("letter");
        private String value;
        /**
         * æžšä¸¾æž„造函数
         * @param value æžšä¸¾çš„值
         */
        private VciBtmTypeVersionRule(String value) {
            this.value = value;
        }
        /**
         * èŽ·å–æžšä¸¾çš„å€¼
         * @return æžšä¸¾çš„值
         */
        public String getValue() {
            return value;
        }
    }
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/annotation/VciColumnDefinition.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,20 @@
package com.vci.starter.web.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
 * åˆ—描述
 */
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface VciColumnDefinition {
    /**
     * å…·ä½“的值
     * @return
     */
    String value();
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/annotation/VciEnum.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,38 @@
package com.vci.starter.web.annotation;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
 * æžšä¸¾å®šä¹‰
 * @author weidy
 */
@Target({java.lang.annotation.ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface VciEnum {
    /**
     * è‹±æ–‡åç§°
     * @return
     */
    String name() default "";
    /**
     * å€¼ç±»åž‹ï¼Œé»˜è®¤ä¸ºå­—符串
     * @return
     */
    Class valueType() default java.lang.String.class;
    /**
     * æ˜¾ç¤ºæ–‡æœ¬
     * @return
     */
    String text() default "";
    /**
     * æè¿°
     * @return
     */
    String description() default "";
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/annotation/VciFieldType.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,22 @@
package com.vci.starter.web.annotation;
import com.vci.starter.web.enumpck.VciFieldTypeEnum;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
 * VCI平台中所属的字段类型
 * @author weidy
 */
@Target({java.lang.annotation.ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface VciFieldType {
    /**
     * ç±»åž‹çš„值,默认为字符串
     * @return
     */
    VciFieldTypeEnum value() default VciFieldTypeEnum.VTString;
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/annotation/VciLifeCycle.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,44 @@
package com.vci.starter.web.annotation;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
 * ç”Ÿå‘½å‘¨æœŸå¯¹è±¡å®šä¹‰ï¼Œåœ¨å…¶ä¸­å®šä¹‰ä¸ŠåŸºæœ¬ä¿¡æ¯ï¼Œåœ¨ä½¿ç”¨è¿™ä¸ªæ³¨è§£çš„对象上定义状态,和流向
 * @author weidy
 */
@Target({java.lang.annotation.ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface VciLifeCycle {
    /**
     * è‹±æ–‡åç§°
     * @return
     */
    String name() default "";
    /**
     * èµ·å§‹çŠ¶æ€
     * @return
     */
    String startStatus() default "";
    /**
     * æ˜¾ç¤ºæ–‡æœ¬
     * @return
     */
    String text() default "";
    /**
     * æè¿°
     * @return
     */
    String description() default "";
    /**
     * è¿žæŽ¥çº¿
     * @return
     */
    VciLifeCycleTrans[] translations() default @VciLifeCycleTrans(source = "",target = "",name="");
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/annotation/VciLifeCycleTranEvent.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,28 @@
package com.vci.starter.web.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
 * ç”Ÿå‘½å‘¨æœŸè¿žæŽ¥çº¿çš„事件
 * @author weidy
 */
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface VciLifeCycleTranEvent {
    /**
     * ç±»å…¨è·¯å¾„
     * @return ç±»è·¯å¾„名称
     */
    String classFullName() ;
    /**
     * æ˜¾ç¤ºåç§°
     * @return æ˜¾ç¤ºåç§°
     */
    String showName();
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/annotation/VciLifeCycleTrans.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,41 @@
package com.vci.starter.web.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
 * ç”Ÿå‘½å‘¨æœŸçŠ¶æ€æµå‘
 * @author weidy
 */
@Target({java.lang.annotation.ElementType.TYPE, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface VciLifeCycleTrans {
    /**
     * èµ·å§‹çŠ¶æ€
     * @return
     */
    String source() default "";
    /**
     * ç›®æ ‡çŠ¶æ€
     * @return
     */
    String target() default "";
    /**
     * åç§°
     * @return
     */
    String name() ;
    /**
     * æ‰€éœ€äº‹ä»¶
     * @return
     */
    VciLifeCycleTranEvent[] listeners() default  @VciLifeCycleTranEvent(classFullName = "",showName = "");
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/annotation/VciLinkType.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,57 @@
package com.vci.starter.web.annotation;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
 * é“¾æŽ¥ç±»åž‹
 */
@Target({java.lang.annotation.ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface VciLinkType {
    /**
     * è‹±æ–‡åç§°
     * @return
     */
    String name() default "";
    /**
     * æ˜¾ç¤ºæ–‡æœ¬
     * @return
     */
    String text() default "";
    /**
     * æè¿°
     * @return
     */
    String description() default "";
    /**
     * è¡¨æ ¼åç§°
     * @return
     */
    String tableName() default "";
    /**
     * from端
     * @return
     */
    String[] fromBtmTypes() ;
    /**
     * to端
     * @return
     */
    String[] toBtmTypes();
    /**
     * æ˜¯å¦ç®¡ç†å¯†çº§
     * @return true表示需要管理
     */
    boolean secretAble() default false;
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/annotation/VciPlatformScan.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,21 @@
package com.vci.starter.web.annotation;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
 * vci平台扫描的包,会自动扫描业务类型,链接类型,枚举,生命周期,版本规则
 * @author weidy
 */
@Target({java.lang.annotation.ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface VciPlatformScan {
    /**
     * åŒ…名,到什么包开始就行,会自动找它的下级包
     * @return
     */
    String[] value();
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/annotation/VciRevisionRule.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,62 @@
package com.vci.starter.web.annotation;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
 * ç‰ˆæœ¬è§„则定义
 * @author weidy
 */
@Target({java.lang.annotation.ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface VciRevisionRule {
    /**
     * è‹±æ–‡åç§°
     * @return
     */
    String name() ;
    /**
     * æ˜¾ç¤ºæ–‡æœ¬
     * @return
     */
    String text() ;
    /**
     * æè¿°
     * @return
     */
    String description() default "";
    /**
     * è·³è·ƒå­—符
     * @return
     */
    String skipChar() default "";
    /**
     * åˆå§‹å­—符
     * @return
     */
    String startChar() ;
    /**
     * æ­¥é•¿
     * @return
     */
    int stepNumber() default  1;
    /**
     * å‰ç¼€
     * @return
     */
    String prefixString() default  "";
    /**
     * åŽç¼€
     * @return
     */
    String suffixString() default "";
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/annotation/VciUseEnum.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,42 @@
package com.vci.starter.web.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
 * ä½¿ç”¨æžšä¸¾
 * @author weidy
 */
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface VciUseEnum {
    /**
     * ä½¿ç”¨æžšä¸¾çš„英文名称
     * @return
     */
    String value() ;
    /**
     * é»˜è®¤çš„值
     * @return
     */
    String defaultValue() default "";
    /**
     * æ˜¾ç¤ºçš„字段
     * @return
     */
     String showTextField() ;
    /**
     * æ˜¯å¦å­˜å‚¨å¤šä¸ª
     * @return
     */
     boolean multiple() default false;
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/annotation/VciUseRefer.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,26 @@
package com.vci.starter.web.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
 * ä½¿ç”¨å‚照的注解
 * @author weidy
 */
@Target({ ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface VciUseRefer {
    /**
     * å¼•用的业务类型
     * @return
     */
    String value();
    /**
     * æ˜¾ç¤ºæ–‡æœ¬çš„字段
     * @return
     */
    String showTextField() default "";
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/annotation/XmlType.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,22 @@
package com.vci.starter.web.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
 * æ˜¯å¦ä¸ºxmltype的格式(老平台)
 * @author weidy
 * @date 2022-2-15
 */
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface XmlType {
    /**
     * å€¼
     * @return æ˜¯å¦
     */
    boolean value() default true;
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/annotation/bus/PortalTodoPublishImpl.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,10 @@
package com.vci.starter.web.annotation.bus;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({java.lang.annotation.ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface PortalTodoPublishImpl {
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/annotation/bus/VciChangeDataAfter.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,29 @@
package com.vci.starter.web.annotation.bus;
import com.vci.starter.web.enumpck.VciChangeDocumentTypeEnum;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
 * ä¿®æ”¹æ•°æ®åŽçš„æ‰§è¡Œæ’ä»¶
 * @author weidy
 * @date 2020/1/29
 */
@Target({ ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface VciChangeDataAfter {
    /**
     * è¦ç›‘听的业务类型的名称
     * @return ä¸šåŠ¡ç±»åž‹çš„åç§°
     */
    String[] btmType() default "";
    /**
     * è¦ç›‘听修改的类型
     */
    VciChangeDocumentTypeEnum[] changeType() default VciChangeDocumentTypeEnum.ALL;
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/annotation/bus/VciChangeDataBefore.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,29 @@
package com.vci.starter.web.annotation.bus;
import com.vci.starter.web.enumpck.VciChangeDocumentTypeEnum;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
 * ä¿®æ”¹æ•°æ®ä¹‹å‰çš„æ‰§è¡Œæ’ä»¶
 * @author weidy
 * @date 2020/1/29
 */
@Target({ ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface VciChangeDataBefore {
    /**
     * è¦ç›‘听的业务类型的名称
     * @return ä¸šåŠ¡ç±»åž‹çš„åç§°
     */
    String[] btmType() default "";
    /**
     * è¦ç›‘听修改的类型
     */
    VciChangeDocumentTypeEnum[] changeType() default VciChangeDocumentTypeEnum.ALL;
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/annotation/bus/VciChangeDataPlugin.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,40 @@
package com.vci.starter.web.annotation.bus;
import com.vci.starter.web.enumpck.VciChangeDocumentTypeEnum;
import org.springframework.core.annotation.AliasFor;
import org.springframework.stereotype.Component;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
 * æ•°æ®å˜åŒ–的扩展插件
 * @author weidy
 * @date 2020/2/23
 */
@Target({ ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Component
public @interface VciChangeDataPlugin {
    /**
     * bean的名称
     * @return é»˜è®¤ä¸ºé¦–写字母小写
     */
    @AliasFor(
            annotation = Component.class
    )
    String value() default "";
    /**
     * è¦ç›‘听的业务类型的名称
     * @return ä¸šåŠ¡ç±»åž‹çš„åç§°
     */
    String[] btmType() default "";
    /**
     * è¦ç›‘听修改的类型
     */
    VciChangeDocumentTypeEnum[] changeType() default VciChangeDocumentTypeEnum.ALL;
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/annotation/bus/VciChangeDocument.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,55 @@
package com.vci.starter.web.annotation.bus;
import com.vci.starter.web.enumpck.VciChangeDocumentTypeEnum;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
 * æ·»åŠ ï¼Œä¿®æ”¹ï¼Œåˆ é™¤æ•°æ®
 * ç¼“存更新,全文检索,编码规则监控等
 * @author weidy
 * @date 2020/3/29
 */
@Target({ ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface VciChangeDocument {
    /**
     * ä¸šåŠ¡ç±»åž‹çš„åç§°
     * @return ä¸šåŠ¡ç±»åž‹çš„åç§°
     */
    String[] btmType() default "";
    /**
     * ä¸»é”®çš„字段,支持spel(spring的表达式,参考缓存
     * @return ä¸»é”®çš„字段
     */
    String[] oidField() default "";
    /**
     * å…³è”的业务类型
     * @return å½“前的业务类型关联的业务类型
     */
    String[] linkBtmType() default "";
    /**
     * ä¿®æ”¹çš„类型
     */
    VciChangeDocumentTypeEnum changeType() default VciChangeDocumentTypeEnum.ADD;
    /**
     * ä¸åŒ…含的表达式,支持spel
     * @return
     */
    String unless() default "";
    /**
     * æŽ¥å£åˆ¤æ–­å¹‚等性
     * @return é»˜è®¤æ˜¯å¼€å¯å¹‚等性,因为只要对数据进行变更都应该注意
     */
    boolean idempotence() default true;
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/annotation/bus/VciLoginAfter.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,16 @@
package com.vci.starter.web.annotation.bus;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
 * ç™»å½•后的事件
 * @author weidy
 * @date 2020/1/29
 */
@Target({ ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface VciLoginAfter {
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/annotation/bus/VciLoginBefore.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,18 @@
package com.vci.starter.web.annotation.bus;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
 *
 * ç™»å½•之前的事件
 * @author weidy
 * @date 2020/1/29
 */
@Target({ ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface  VciLoginBefore {
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/annotation/bus/VciLoginPlugin.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,28 @@
package com.vci.starter.web.annotation.bus;
import org.springframework.core.annotation.AliasFor;
import org.springframework.stereotype.Component;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
 * ç™»å½•的插件
 * @author weidy
 * @date 2020/2/23
 */
@Target({ ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Component
public @interface VciLoginPlugin {
    /**
     * bean的名称
     * @return
     */
    @AliasFor(
            annotation = Component.class
    )
    String value() default "";
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/annotation/bus/VciLogoutAfter.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,17 @@
package com.vci.starter.web.annotation.bus;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
 * é€€å‡ºç³»ç»Ÿä¹‹åŽ
 * @author weidy
 * @date 2020/1/29
 */
@Target({ ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface VciLogoutAfter {
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/annotation/bus/VciLogoutBefore.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,16 @@
package com.vci.starter.web.annotation.bus;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
 * é€€å‡ºç³»ç»Ÿä¹‹å‰äº‹ä»¶
 * @author weidy
 * @date 2020/1/29
 */
@Target({ ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface VciLogoutBefore {
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/annotation/bus/VciLogoutPlugin.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,28 @@
package com.vci.starter.web.annotation.bus;
import org.springframework.core.annotation.AliasFor;
import org.springframework.stereotype.Component;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
 * é€€å‡ºç™»å½•的插件
 * @author weidy
 * @date 2020/2/23
 */
@Target({ ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Component
public @interface VciLogoutPlugin {
    /**
     * bean的名称
     * @return
     */
    @AliasFor(
            annotation = Component.class
    )
    String value() default "";
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/annotation/bus/VciNoUseBaseResult.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,16 @@
package com.vci.starter.web.annotation.bus;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
 * ä¸ä½¿ç”¨ç»Ÿä¸€çš„æ•°æ®å¯¹è±¡è¿”回
 * @author weidy
 * @date 2019/12/3 8:36 PM
 */
@Target({ java.lang.annotation.ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface VciNoUseBaseResult {
    boolean value() default true;
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/annotation/bus/VciTaskAfter.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,22 @@
package com.vci.starter.web.annotation.bus;
import com.vci.starter.web.enumpck.VciTaskBusTypeEnum;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
 * ä»»åŠ¡åŽç½®çš„äº‹ä»¶
 * @author weidy
 * @date 2020/1/29
 */
@Target({ ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface VciTaskAfter {
    /**
     * å˜æ›´ç±»åž‹
     */
    VciTaskBusTypeEnum busTypeEnum();
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/annotation/bus/VciTaskBefore.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,23 @@
package com.vci.starter.web.annotation.bus;
import com.vci.starter.web.enumpck.VciTaskBusTypeEnum;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
 *
 * æ‰§è¡Œä»»åŠ¡ä¹‹å‰
 * @author weidy
 * @date 2020/1/29
 */
@Target({ ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface VciTaskBefore {
    /**
     * å˜æ›´ç±»åž‹
     */
    VciTaskBusTypeEnum busTypeEnum();
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/annotation/bus/VciTaskPlugin.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,28 @@
package com.vci.starter.web.annotation.bus;
import org.springframework.core.annotation.AliasFor;
import org.springframework.stereotype.Component;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
 * ä»»åŠ¡ç›¸å…³çš„æ’ä»¶
 * @author weidy
 * @date 2020/2/23
 */
@Target({ ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Component
public @interface VciTaskPlugin {
    /**
     * bean的名称
     * @return é»˜è®¤ä¸ºé¦–写字母小写
     */
    @AliasFor(
            annotation = Component.class
    )
    String value() default "";
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/annotation/config/VciConfigField.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,61 @@
package com.vci.starter.web.annotation.config;
import org.springframework.core.annotation.AliasFor;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
 * é…ç½®ä¸­å¿ƒçš„æ¨¡å—下的配置字段
 * @author weidy
 * @date 2020/2/5
 */
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface VciConfigField {
    /**
     * åœ¨é…ç½®ä¸­å¿ƒé‡Œçš„配置项
     * @return
     */
    @AliasFor("name")
    String value() default "";
    /**
     * åœ¨é…ç½®ä¸­å¿ƒé‡Œçš„配置项名称
     * @return
     */
    String name() default "";
    /**
     * åœ¨é…ç½®ä¸­å¿ƒé‡Œé…ç½®é¡¹çš„æ ‡é¢˜
     * @return
     */
    String title();
    /**
     * æ‰€å±žæ¨¡å—,自动继承这个注解所属类上的注解
     * @return
     */
    String model() default "";
    /**
     * æ˜¯å¦ä¿®æ”¹åŽç«‹å³ç”Ÿæ•ˆ
     * @return
     */
    boolean effectOnEdit() default false;
    /**
     * æ˜¯å¦å¤šé€‰
     * @return
     */
    boolean mutliValue() default false;
    /**
     * æè¿°
     * @return
     */
    String description() default "";
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/annotation/config/VciConfigFieldSelect.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,44 @@
package com.vci.starter.web.annotation.config;
import org.springframework.core.annotation.AliasFor;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
 * é…ç½®é¡¹çš„选择页面配置
 * @author weidy
 * @date 2020/2/5
 */
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface VciConfigFieldSelect {
    /**
     * æ˜¾ç¤ºçš„Url的值
     * @return
     */
    @AliasFor("url")
    String value();
    /**
     * æ˜¾ç¤ºé€‰æ‹©å€¼çš„url
     * @return
     */
    @AliasFor("url")
    String url();
    /**
     * å€¼çš„字段
     * @return
     */
    String valueField() default "oid";
    /**
     * æ˜¾ç¤ºçš„字段
     * @return
     */
    String textField() default "name";
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/annotation/config/VciConfigModule.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,47 @@
package com.vci.starter.web.annotation.config;
import org.springframework.core.annotation.AliasFor;
import org.springframework.stereotype.Component;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
 * é…ç½®ä¸­å¿ƒçš„æ¨¡å—
 * @author weidy
 * @date 2020/2/5
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Component
public @interface VciConfigModule {
    /**
     * bean的名称
     * @return
     */
    @AliasFor(
            annotation = Component.class
    )
    String value() default "";
    /**
     * åç§°
     * @return åœ¨é…ç½®ä¸­å¿ƒçš„名称
     */
    String name();
    /**
     * æ ‡é¢˜
     * @return åœ¨é…ç½®ä¸­å¿ƒæ˜¾ç¤ºçš„æ ‡é¢˜
     */
    String title();
    /**
     * æè¿°ä¿¡æ¯
     * @return æè¿°ä¿¡æ¯
     */
    String description() default "";
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/annotation/controller/VciReturnErrorUseFile.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,18 @@
package com.vci.starter.web.annotation.controller;
import com.vci.starter.web.enumpck.VciReturnFileTypeEnum;
/**
 * ä½¿ç”¨æ–‡ä»¶è¿”回错误信息
 * @author weidy
 * @date 2020/2/19
 */
public @interface VciReturnErrorUseFile {
    /**
     * é»˜è®¤ä¸ºæ–‡æœ¬æ–‡ä»¶
     * @return
     */
    VciReturnFileTypeEnum value() default VciReturnFileTypeEnum.TXT;
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/annotation/controller/VciUnCheckRight.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,22 @@
package com.vci.starter.web.annotation.controller;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
 * ä¸æ ¡éªŒæƒé™çš„路径
 * @author weidy
 * @date 2020/2/28
 */
@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface VciUnCheckRight {
    /**
     * å€¼ï¼Œå¯ä»¥ä¸è®¾ç½®
     * @return true表示不校验
     */
    boolean value() default true;
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/annotation/controller/VciUnUseResponseAdvice.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,22 @@
package com.vci.starter.web.annotation.controller;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
 * ä¸ä½¿ç”¨ç»Ÿä¸€çš„返回接口
 * @author weidy
 * @date 2022/12/06
 */
@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface VciUnUseResponseAdvice {
    /**
     * å€¼ï¼Œå¯ä»¥ä¸è®¾ç½®
     * @return true表示不校验
     */
    boolean value() default true;
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/annotation/log/VciBusinessLog.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,44 @@
package com.vci.starter.web.annotation.log;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({java.lang.annotation.ElementType.TYPE, java.lang.annotation.ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface VciBusinessLog {
    /**
     * æ‰€å±žåŠŸèƒ½æ¨¡å—
     * @return
     */
    String modelName() default "";
    /**
     * æ‰€å±žæ“ä½œåç§°
     * @return
     */
    String operateName() default "";
    /**
     * æ—¥å¿—类型--登录日志,操作日志,授权日志
     * @return
     */
    VciLogType logType() default VciLogType.Operate;
    /**
     * æè¿°ä¿¡æ¯
     * @return
     */
    String description() default "";
    /**
     * ä¸å­˜å‚¨æ—¥å¿—
     * @return
     */
    boolean notStore() default false;
    public static enum VciLogType{
        Login,Operate,Audit
    }
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/annotation/log/VciUnLog.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,16 @@
package com.vci.starter.web.annotation.log;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
 * ä¸è®°å½•运行日志
 * @author weidy
 * @date 2020/4/10
 */
@Target({java.lang.annotation.ElementType.TYPE, java.lang.annotation.ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface VciUnLog {
    boolean value() default true;
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/annotation/permission/VciPermission.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,137 @@
package com.vci.starter.web.annotation.permission;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
 * æƒé™æŽ§åˆ¶çš„æ³¨è§£
 * ç”¨äºŽè‡ªåŠ¨æŽ§åˆ¶åŠŸèƒ½æƒé™ï¼ŒæŒ‰é’®æƒé™ï¼Œå’Œæ•°æ®æƒé™--数据权限会通过AOP的方式将数据权限的规则注入到QueryMap中
 * @author weidy
 *
 */
@Target({java.lang.annotation.ElementType.TYPE, java.lang.annotation.ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface VciPermission {
    /**
     * æ‰€å±žåŠŸèƒ½æ¨¡å—key--与功能菜单中的编号对应
     * @return
     */
    String[] modelKey() default "";
    /**
     * æ‰€å±žæŒ‰é’®key--会自动注入到平台的操作类型中
     * @return
     */
    String[] methodKey() default "";
    /**
     * æ‰€å±žæŒ‰é’®çš„名称
     * @return
     */
    String[] methodName() default "";
    /**
     * æ‰€å±žæŒ‰é’®çš„名称
     * @return
     */
    String[] methodAlias() default "";
    /**
     * æ‰€å±žæŒ‰é’®çš„æè¿°
     * @return
     */
    String[] methodDesc() default "";
    /**
     * æ‰€å±žæŒ‰é’®åœ¨èœå•中的排序
     * @return
     */
    int[] methodOrder() default 0;
    /**
     * å›ºå®šçš„角色--角色的编码,多个使用逗号分隔
     * æ”¯æŒè¡¨è¾¾å¼${lt}角色的类型值,表示访问的用户的角色类型必须小于某种类型,${eq}表示相等,${more}表示大于
     * *可以用于做通配符
     * @return
     */
    String defineRole() default "";
    /**
     * å…è®¸çš„密级等级
     * @return
     */
    int secretGrade() default -1;
    /**
     * å…è®¸ip密级
     * @return
     */
    String ipSecret() default "";
    /**
     * æ–¹æ³•的权限控制,如果为空时取defineRole的值
     * å›ºå®šçš„角色--角色的编码,多个使用逗号分隔
     * æ”¯æŒè¡¨è¾¾å¼${lt}角色的类型值,表示访问的用户的角色类型必须小于某种类型,${eq}表示相等,${more}表示大于
     * *可以用于做通配符
     * @return
     */
    String defineRoleForMethod() default "";
    /**
     * æ–¹æ³•的权限密级控制,如果为空时取secretGrade的值
     * @return
     */
    int secretGradeForMethod() default -2;
    /**
     * æ–¹æ³•的权限IP控制,如果为空时取ipSecret的值
     * @return
     */
    String ipSecretForMethod() default "";
    /**
     * æ•°æ®æƒé™åˆ¤æ–­æ‰€éœ€çš„业务类型
     * @return
     */
    String dataPermissionBtmType() default "";
    /**
     * æ•°æ®æƒé™åˆ¤æ–­æ‰€éœ€çš„æ–¹æ³•key。默认等于methodKey,所以不用设置
     * @return
     */
    String[] dataPermissionMethodKey() default "";
    /**
     * æ˜¯å¦æŽ§åˆ¶æ•°æ®æƒé™,如果在config.properties里配置了right.switch后,默认值会处理为配置的值
     * @return
     */
    boolean controlDataPermission() default false;
    /**
     * æ˜¯å¦æŽ§åˆ¶åŠŸèƒ½æƒé™ï¼Œå¦‚æžœåœ¨config.properties里配置了function.switch后,默认值会处理为配置的值
     * @return
     */
    boolean controlModelPermission() default true;
    /**
     * æ˜¯å¦æŽ§åˆ¶æŒ‰é’®æƒé™ï¼Œå¦‚果在config.properties里配置了ui.right.switch后,默认值会处理为配置的值
     * @return
     */
    boolean controlMethodPermission() default true;
    /**
     * ç”¨æˆ·å¯†çº§
     * none--非密
     * inner--内部
     * secret--秘密
     * privacy--机密
     * @author weidy
     *
     */
    public static enum UserSecretGrade{
        none,inner,secret,privacy
    }
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/annotation/permission/VciReferPermission.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,20 @@
package com.vci.starter.web.annotation.permission;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
 * å‚照方法注解,表示这个方法是提供给其他地方参照引用的
 * @author weidy
 */
@Target({ java.lang.annotation.ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface VciReferPermission {
    /**
     * å‚ç…§çš„key,需要唯一值,在系统启动的时候会扫描,建议使用被业务类型来代替
     * @return
     */
    String referedKey()  ;
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/annotation/permission/VciUseReferMethod.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,19 @@
package com.vci.starter.web.annotation.permission;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
 * ä½¿ç”¨å‚照的注解
 * @author weidy
 */
@Target({ java.lang.annotation.ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface VciUseReferMethod {
    /**
     * ä½¿ç”¨å‚ç…§çš„key
     * @return
     */
    String[] useReferKey() ;
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/annotation/undo/UndoTaskCount.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,18 @@
package com.vci.starter.web.annotation.undo;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
 * å¾…办事项的查询总数方法
 * @author weidy
 * @date 2022/8/1
 */
@Target({ ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface UndoTaskCount {
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/annotation/undo/UndoTaskMethod.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,18 @@
package com.vci.starter.web.annotation.undo;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
 * å¾…办事项的查询方法
 * @author weidy
 * @date 2022/8/1
 */
@Target({ ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface UndoTaskMethod {
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/annotation/undo/UndoTaskPlugin.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,68 @@
package com.vci.starter.web.annotation.undo;
import org.springframework.stereotype.Component;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
 * å¾…办事项的查询的内容
 * æ¡ä»¶æ˜¯or的方式判断
 * @author weidy
 * @date 2022/8/1
 */
@Target({ ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Component
public @interface UndoTaskPlugin {
    /**
     * æŽ’序号
     * @return æŽ’序的内容
     */
    int order() ;
    /**
     * ä»»åŠ¡ç±»åž‹
     * @return ä»»åŠ¡ç±»åž‹
     */
    String name() default "";
    /**
     * æƒé™çš„名字
     * @return æƒé™çš„名字
     */
    String[] funcNames() default "";
    /**
     * æŒ‡å®šè§’色的名称
     * @return è§’色名称
     */
    String[] roles() default "";
    /**
     * æŒ‡å®šçš„部门名称
     * @return éƒ¨é—¨åç§°
     */
    String[] depts() default "";
    /**
     * æŒ‡å®šçš„用户名
     * @return ç”¨æˆ·å
     */
    String[] users() default "";
    /**
     * æŒ‡å®šçš„角色类型
     * @return è§’色类型
     */
    String[] roleTypes() default "";
    /**
     * æ‰§è¡Œçš„用户类型
     * @return ç”¨æˆ·ç±»åž‹
     */
    String[] userTypes() default "";
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/annotation/workflow/WorkflowEvent.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,51 @@
package com.vci.starter.web.annotation.workflow;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
 * æµç¨‹äº‹ä»¶
 * ç›®å‰æµç¨‹äº‹ä»¶åœ¨é…ç½®æ–‡ä»¶ä¸­ï¼Œæ€»æ˜¯å‡ºçŽ°é…ç½®é”™è¯¯çš„æƒ…å†µï¼Œå› ä¸ºæµç¨‹äº‹ä»¶åŸºæœ¬æ˜¯å›ºå®šçš„ï¼Œå› æ­¤å¼•æ³¨è§£æ¥ä½¿ç”¨
 * @author weidy
 */
@Target({java.lang.annotation.ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface WorkflowEvent {
    /**
     * key,事件的唯一识别码,默认取使用注解的类的名称(首字母小写)
     * @return
     */
    String value() default "";
    /**
     * ä¸­æ–‡åå­—,如果为空的时候,取使用注解的类的名称(首字母小写)
     * @return
     */
    String name() default "";
    /**
     * ç”¨äºŽæµç¨‹ä»»åŠ¡å¼€å§‹äº‹ä»¶
     * @return
     */
    boolean useInStart() default true;
    /***
     * ç”¨äºŽæµç¨‹ä»»åŠ¡å®Œæˆäº‹ä»¶
     * @return
     */
    boolean useInComplete() default  true;
    /**
     * ç”¨äºŽæµç¨‹ä»»åŠ¡ç»ˆæ­¢äº‹ä»¶
     * @return
     */
    boolean useInEnd() default true;
    /**
     * ç”¨äºŽè·¯ç”±çº¿äº‹ä»¶
     * @return
     */
    boolean useInTransition() default true;
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/annotation/workflow/WorkflowEventField.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,22 @@
package com.vci.starter.web.annotation.workflow;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
 * æµç¨‹äº‹ä»¶ä¸­çš„字段
 * é…åˆWorkflowEvent使用,自动读取字段的名称和类型
 * @author weidy
 */
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface WorkflowEventField {
    /**
     * æ˜¯å¦å¿…输
     * @return
     */
    boolean required() default false;
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/autoconfigure/AppAutoConfigure.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,113 @@
package com.vci.starter.web.autoconfigure;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
/**
 * åº”用信息配置
 * @author weidy
 */
@Configuration
@ConfigurationProperties(prefix = "app")
public class AppAutoConfigure {
    /**
     * æ‰€å±žç»„织
     */
    private String group;
    /**
     * åº”用名称
     */
    private String name;
    /**
     * åº”用描述
     */
    private String description;
    /**
     * ä½œè€…
     */
    private String author;
    /**
     * é‚®ä»¶
     */
    private String email;
    /**
     * é“¾æŽ¥åœ°å€
     */
    private String url;
    /**
     * åº”用私钥
     */
    private String privateTokenKey;
    public String getGroup() {
        return group;
    }
    public void setGroup(String group) {
        this.group = group;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getDescription() {
        return description;
    }
    public void setDescription(String description) {
        this.description = description;
    }
    public String getAuthor() {
        return author;
    }
    public void setAuthor(String author) {
        this.author = author;
    }
    public String getEmail() {
        return email;
    }
    public void setEmail(String email) {
        this.email = email;
    }
    public String getUrl() {
        return url;
    }
    public void setUrl(String url) {
        this.url = url;
    }
    public String getPrivateTokenKey() {
        return privateTokenKey;
    }
    public void setPrivateTokenKey(String privateTokenKey) {
        this.privateTokenKey = privateTokenKey;
    }
    @Override
    public String toString() {
        return "AppAutoConfigure{" +
                "group='" + group + '\'' +
                ", name='" + name + '\'' +
                ", description='" + description + '\'' +
                ", author='" + author + '\'' +
                ", email='" + email + '\'' +
                ", url='" + url + '\'' +
                ", privateTokenKey='" + privateTokenKey + '\'' +
                '}';
    }
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/autoconfigure/DubboConfig.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,9 @@
package com.vci.starter.web.autoconfigure;
/**
 * dubbo的调用处理器
 * @author weidy
 * @date 2020/6/16
 */
public class DubboConfig {
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/autoconfigure/FeignConfig.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,223 @@
package com.vci.starter.web.autoconfigure;
import com.alibaba.fastjson.JSONObject;
import com.vci.starter.web.constant.TokenKeyConstant;
import com.vci.starter.web.pagemodel.SessionInfo;
import com.vci.starter.web.util.VciBaseUtil;
import feign.*;
import feign.form.spring.SpringFormEncoder;
import feign.okhttp.OkHttpClient;
import okhttp3.ConnectionPool;
import org.slf4j.MDC;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
import org.springframework.cloud.commons.httpclient.OkHttpClientConnectionPoolFactory;
import org.springframework.cloud.commons.httpclient.OkHttpClientFactory;
import org.springframework.cloud.openfeign.support.FeignHttpClientProperties;
import org.springframework.cloud.openfeign.support.ResponseEntityDecoder;
import org.springframework.cloud.openfeign.support.SpringDecoder;
import org.springframework.cloud.openfeign.support.SpringEncoder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.web.bind.annotation.RequestMethod;
import javax.annotation.PreDestroy;
import java.nio.charset.StandardCharsets;
import java.util.Map;
import java.util.concurrent.TimeUnit;
/**
 * feign客户端配置
 * @author weidy
 * @date 2019/11/5 10:23 AM
 */
@AutoConfigureAfter(AppAutoConfigure.class)
@Configuration
public class FeignConfig implements RequestInterceptor {
    /**
     * ä½¿ç”¨okHttpClient来传输数据
     */
    private okhttp3.OkHttpClient okHttpClient;
    /**
     * å½“前应用程序的私钥
     */
    @Value("${app.privateTokenKey:}")
    private String privateTokenKey;
    /**
     * å®¢æˆ·ç«¯è¿žæŽ¥æ± 
     * @param httpClientProperties http链接配置
     * @param connectionPoolFactory è¿žæŽ¥æ± å·¥ç¨‹
     * @return è¿žæŽ¥æ± 
     */
    @Bean
    @ConditionalOnMissingBean({ConnectionPool.class})
    public ConnectionPool httpClientConnectionPool(FeignHttpClientProperties httpClientProperties, OkHttpClientConnectionPoolFactory connectionPoolFactory) {
        Integer maxTotalConnections = httpClientProperties.getMaxConnections();
        Long timeToLive = httpClientProperties.getTimeToLive();
        TimeUnit ttlUnit = httpClientProperties.getTimeToLiveUnit();
        return connectionPoolFactory.create(maxTotalConnections, timeToLive, ttlUnit);
    }
    /**
     * åˆå§‹åŒ–okHttp的客户端对象
     * @param httpClientFactory å®¢æˆ·ç«¯é“¾æŽ¥å·¥ç¨‹
     * @param connectionPool è¿žæŽ¥æ± 
     * @param httpClientProperties å®¢æˆ·ç«¯é“¾æŽ¥é…ç½®
     * @return
     */
    @Bean
    public okhttp3.OkHttpClient client(OkHttpClientFactory httpClientFactory, ConnectionPool connectionPool, FeignHttpClientProperties httpClientProperties) {
        Boolean followRedirects = httpClientProperties.isFollowRedirects();
        Integer connectTimeout = httpClientProperties.getConnectionTimeout();
        Boolean disableSslValidation = httpClientProperties.isDisableSslValidation();
        this.okHttpClient = httpClientFactory.createBuilder(disableSslValidation).connectTimeout((long)connectTimeout, TimeUnit.MILLISECONDS).followRedirects(followRedirects).readTimeout(30*60,TimeUnit.SECONDS).connectionPool(connectionPool).build();
        return this.okHttpClient;
    }
    /**
     * é”€æ¯ä¹‹å‰å…³é—­okHttp
     */
    @PreDestroy
    public void destroy() {
        if (this.okHttpClient != null) {
            this.okHttpClient.dispatcher().executorService().shutdown();
            this.okHttpClient.connectionPool().evictAll();
        }
    }
    /**
     * é…ç½®feign的客户端类
     * @param client å®¢æˆ·ç«¯é“¾æŽ¥å¯¹è±¡
     * @return å®¢æˆ·ç«¯è¿žæŽ¥å¯¹è±¡
     */
    @Bean
    @ConditionalOnMissingBean({Client.class})
    public Client feignClient(okhttp3.OkHttpClient client) {
        return new OkHttpClient(client);
    }
    /**
     * è®¾ç½®è¯·æ±‚的连接时间和读取的时间
     * @param client é“¾æŽ¥çš„客户端
     * @return é“¾æŽ¥çš„客户端
     */
    @Bean
    public Request.Options feignOptions(okhttp3.OkHttpClient client) {
        return new Request.Options(client.connectTimeoutMillis(), client.readTimeoutMillis());
    }
    /**
     * é…ç½®feign的日志等级
     * @return æ—¥å¿—等级
     */
    @Bean
    Logger.Level feignLoggerLevel() {
        //这里记录所有,根据实际情况选择合适的日志level
        return Logger.Level.FULL;
    }
    /**
     * å°†fastjson设置到decoder中,解码器
     * @return decoder
     */
    @Bean
    public ResponseEntityDecoder feignDecoder(){
        HttpMessageConverter fastJsonConverter = SpringMVCConfig.createFastJsonConverter();
        ObjectFactory<HttpMessageConverters> objectFactory = () -> new HttpMessageConverters(new StringHttpMessageConverter(StandardCharsets.UTF_8),fastJsonConverter);
        return new ResponseEntityDecoder(new SpringDecoder(objectFactory));
    }
    /**
     * å°†fastjson设置到encoder中,编码器
     * @return encoder
     */
    @Bean
    public SpringFormEncoder feignEncoder(){
        HttpMessageConverter fastJsonConverter = SpringMVCConfig.createFastJsonConverter();
        ObjectFactory<HttpMessageConverters> objectFactory = () -> new HttpMessageConverters(new StringHttpMessageConverter(StandardCharsets.UTF_8),fastJsonConverter);
        return new SpringFormEncoder(new SpringEncoder(objectFactory));
    }
    /**
     * åœ¨å‘送请求的时候,设置拦截器,将用户的token和当前服务的私钥传递过去,并且传递当前服务的名称用于追溯日志
     * @param requestTemplate è¯·æ±‚的目标
     */
    @Override
    public void apply(RequestTemplate requestTemplate) {
        //如果是GET,但是body里有内容
        Request.Body body = requestTemplate.requestBody();
        if(RequestMethod.GET.toString().equalsIgnoreCase(requestTemplate.method())
                && body != null && body.length() > 0){
            //主要是列表查询和树查询这几个地方,支持map的传输
            String bodyString = new String(body.asBytes(),requestTemplate.requestCharset());
            try{
                JSONObject jsonObject = JSONObject.parseObject(bodyString);
                for(String key : jsonObject.keySet()){
                    Object value = jsonObject.get(key);
                    if(value == null){
                        requestTemplate.query(key,"");
                    }else{
                        if(value instanceof Map){
                            //说明这个属性是map
                            Map mapValues = (Map)value;
                            for(Object mapKey : mapValues.keySet()){
                                Object mapQueryValue = mapValues.get(mapKey);
                                String mapQueryValueString = "";
                                if(mapQueryValue == null){
                                    mapQueryValueString = "";
                                }else{
                                    mapQueryValueString = VciBaseUtil.getStringValueFromObject(mapQueryValue);
                                }
                                requestTemplate.query(key + "[\"" + mapKey.toString() + "\"]",mapQueryValueString);
                            }
                        }else{
                            requestTemplate.query(key,VciBaseUtil.getStringValueFromObject(value));
                        }
                    }
                }
                requestTemplate.body(Request.Body.empty());
            }catch (Throwable e){
                //可能不是json的类型
            }
        }
        //需要传递用户的token
        //系统的token,用于权限验证
        //日志的链接ID
        SessionInfo sessionInfo = VciBaseUtil.getCurrentUserSessionInfoNotException();
        if(sessionInfo != null){
            requestTemplate.header(TokenKeyConstant.USER_TOKEN_KEY,sessionInfo.getToken());
        }else{
            requestTemplate.header(TokenKeyConstant.USER_TOKEN_KEY,"");
        }
        requestTemplate.header(TokenKeyConstant.SYSTEM_PRIVATE_KEY,getPrivateTokenKey());
        String logTraceId = MDC.get(TokenKeyConstant.TRACE_ID);
        if(logTraceId == null){
            logTraceId = "";
        }
        requestTemplate.header(TokenKeyConstant.LOG_TRACE_ID_KEY,logTraceId);
        //设置语言
        requestTemplate.header(TokenKeyConstant.LANGUAGE_KEY,LocaleContextHolder.getLocale().toLanguageTag());
    }
    public String getPrivateTokenKey() {
        return privateTokenKey;
    }
    public void setPrivateTokenKey(String privateTokenKey) {
        this.privateTokenKey = privateTokenKey;
    }
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/autoconfigure/ResponseModifyAdvice.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,149 @@
package com.vci.starter.web.autoconfigure;
import com.vci.starter.web.annotation.controller.VciUnUseResponseAdvice;
import com.vci.starter.web.constant.TokenKeyConstant;
import com.vci.starter.web.pagemodel.BaseResult;
import com.vci.starter.web.pagemodel.DataGrid;
import com.vci.starter.web.pagemodel.Tree;
import com.vci.starter.web.util.MessageUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.MDC;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
/**
 * åœ¨è¿”回结果前,封装统一的数据对象
 * @author weidy
 * @date 2019/11/7 4:05 PM
 */
@ControllerAdvice(annotations = {RestController.class, Controller.class})
public class ResponseModifyAdvice implements ResponseBodyAdvice<Object>{
    /**
     * è¿‡æ»¤å“ªäº›éœ€è¦æ‹¦æˆªå¤„理
     * Whether this component supports the given controller method return type
     * and the selected {@code HttpMessageConverter} type.
     *
     * @param returnType    the return type
     * @param converterType the selected converter type
     * @return {@code true} if {@link #beforeBodyWrite} should be invoked;
     * {@code false} otherwise
     */
    @Override
    public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
        //全部都支持
        if(returnType.getMethod().isAnnotationPresent(VciUnUseResponseAdvice.class)){
            return false;
        }
        return true;
    }
    /**
     * Invoked after an {@code HttpMessageConverter} is selected and just before
     * its write method is invoked.
     *
     * @param body                  the body to be written
     * @param returnType            the return type of the controller method
     * @param selectedContentType   the content type selected through content negotiation
     * @param selectedConverterType the converter type selected to write to the response
     * @param request               the current request
     * @param response              the current response
     * @return the body that was passed in or a modified (possibly new) instance
     */
    @Nullable
    @Override
    public Object beforeBodyWrite(@Nullable Object body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
        String traceId = MDC.get(TokenKeyConstant.TRACE_ID);
        if(returnType.getMethod().isAnnotationPresent(VciUnUseResponseAdvice.class)){
            return body;
        }
        String returnTypeName = returnType.getParameterType().getName();
        if("void".equalsIgnoreCase(returnTypeName)){
            BaseResult baseResult = BaseResult.success();
            baseResult.setFinishTime(System.currentTimeMillis());
            baseResult.setTraceId(traceId);
            formateMsg(baseResult);
            return baseResult;
        }
        if("com.vci.starter.web.pagemodel.BaseResult".equals(returnTypeName)){
            BaseResult baseResult = ((BaseResult)body);
            baseResult.setTraceId(traceId);
            baseResult.setFinishTime(System.currentTimeMillis());
            formateMsg(baseResult);
            return baseResult;
        }
        if("com.vci.starter.web.pagemodel.DataGrid".equals(returnTypeName)){
            DataGrid dataGrid = ((DataGrid)body);
            BaseResult baseResult = BaseResult.dataGrid(dataGrid);
            baseResult.setTraceId(traceId);
            baseResult.setFinishTime(System.currentTimeMillis());
            formateMsg(baseResult);
            return baseResult;
        }
        if("com.vci.starter.web.pagemodel.Tree".equals(returnTypeName)){
            //returnType.getP
            Tree tree = ((Tree)body);
            List<Tree> treeList = new ArrayList<>();
            treeList.add(tree);
            BaseResult baseResult = BaseResult.tree(treeList);
            baseResult.setTraceId(traceId);
            baseResult.setFinishTime(System.currentTimeMillis());
            formateMsg(baseResult);
            return baseResult;
        }
        if(body instanceof Collection){
            //说明是集合
            String genericParamterTypeName = returnType.getGenericParameterType().getTypeName();
            if(genericParamterTypeName.contains("<")
                    && genericParamterTypeName.contains(">")){
                String elementTypeName = genericParamterTypeName.substring(genericParamterTypeName.indexOf("<")+ 1,genericParamterTypeName.indexOf(">"));
                if("com.vci.starter.web.pagemodel.Tree".equalsIgnoreCase(elementTypeName)){
                    Collection<Tree> treeCollection = ((Collection<Tree>)body);
                    BaseResult baseResult = BaseResult.tree(treeCollection);
                    baseResult.setTraceId(traceId);
                    baseResult.setFinishTime(System.currentTimeMillis());
                    formateMsg(baseResult);
                    return baseResult;
                }else{
                    //放到Obj属性里
                    Collection<Object> objectCollection = ((Collection<Object>)body);
                    BaseResult baseResult =  BaseResult.success(objectCollection);
                    baseResult.setTraceId(traceId);
                    baseResult.setFinishTime(System.currentTimeMillis());
                    formateMsg(baseResult);
                    return baseResult;
                }
            }
        }
        if(body instanceof Object){
            BaseResult baseResult = BaseResult.success((Object)body);
            baseResult.setTraceId(traceId);
            baseResult.setFinishTime(System.currentTimeMillis());
            formateMsg(baseResult);
            return baseResult;
        }
        return body;
    }
    /**
     * å¤šè¯­æ ¼å¼åŒ–
     * @param baseResult ç»“果对象
     */
    private void formateMsg(BaseResult baseResult ){
        if(baseResult!=null && StringUtils.isNotBlank(baseResult.getMsg())){
            baseResult.setMsg(MessageUtils.get(baseResult.getMsg(),baseResult.getMsgObjs()));
        }
    }
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/autoconfigure/SpringMVCConfig.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,421 @@
package com.vci.starter.web.autoconfigure;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.support.config.FastJsonConfig;
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
import com.vci.starter.web.interceptor.VciLocaleInterceptor;
import com.vci.starter.web.interceptor.VciLogAfterInterceptor;
import com.vci.starter.web.interceptor.VciLogBeforeInterceptor;
import com.vci.starter.web.interceptor.VciSecurityInterceptor;
import com.vci.starter.web.properties.CorsProperties;
import com.vci.starter.web.toolmodel.String2DateConverterForSpringMvc;
import com.vci.starter.web.util.LocalFileUtil;
import com.vci.starter.web.util.VciDateUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.format.FormatterRegistry;
import org.springframework.http.CacheControl;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.web.filter.FormContentFilter;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.config.annotation.*;
import org.springframework.web.servlet.i18n.SessionLocaleResolver;
import java.io.File;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
/**
 * spring mvc的相关配置
 *
 * @author weidy
 */
@Configuration
@EnableWebMvc
@ConditionalOnProperty(prefix = "vcispringmvc",name="enabled",havingValue = "true",matchIfMissing = true)
@ConfigurationProperties(prefix = "vcispringmvc")
public class SpringMVCConfig  implements WebMvcConfigurer {
    /**
     * æ—¥å¿—对象
     */
    private Logger log = LoggerFactory.getLogger(SpringMVCConfig.class);
    /**
     * å¤–部文件夹的映射地址
     */
    private Map<String,String> resourceFolderMap ;
    /**
     * ä¸æ ¡éªŒå®‰å…¨çš„链接地址
     */
    private List<String> unCheckUrls;
    /**
     * ä¸æ›´æ–°è¯·æ±‚时间的链接地址
     */
    private List<String> unStorageRequestTimeUrls;
    /**
     * è·¨åŸŸçš„配置
     */
    @Autowired(required = false)
    private CorsProperties corsProperties;
    /**
     * é»˜è®¤å…è®¸çš„域名
     */
    private String[] DEFAULT_ORIGINS = {"*"};
    /**
     * é»˜è®¤å…è®¸çš„头
     */
    private String[] DEFAULT_ALLOWED_HEADERS = {"*"};
    /**
     * é»˜è®¤å…è®¸çš„æ–¹æ³•
     */
    private String[] DEFAULT_METHODS = {"PUT", "DELETE","GET","POST"};
    /**
     * é»˜è®¤æš´éœ²çš„头
     */
    private String[] DEFAULT_EXPOSEDHEADERS = {"access-control-allow-headers",
            "access-control-allow-methods",
            "access-control-allow-origin",
            "access-control-max-age",
            "X-Frame-Options"};
    /**
     * é»˜è®¤æ˜¯å¦å…è®¸è¯ä¹¦
     */
    private boolean DEFAULT_ALLOW_CREDENTIALS = true;
    /**
     * é»˜è®¤çš„æœ€å¤§å€¼
     */
    private long DEFAULT_MAX_AGE = 1800;
    public Map<String, String> getResourceFolderMap() {
        return resourceFolderMap;
    }
    public void setResourceFolderMap(Map<String, String> resourceFolderMap) {
        this.resourceFolderMap = resourceFolderMap;
    }
    /**
     * å¢žåŠ PUT和DELETE的支持
     * @return è¿‡æ»¤å™¨
     */
    @Bean
    public FormContentFilter formContentFilter() {
        return new FormContentFilter();
    }
    /**
     * ä½¿ç”¨fastjson返回值
     * @param converters æ‰€æœ‰çš„æ¶ˆæ¯è½¬æ¢å™¨
     */
    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters){
        converters.add(new StringHttpMessageConverter(StandardCharsets.UTF_8));
        converters.add(createFastJsonConverter());
    }
    /**
     * èŽ·å–fastjson的转换器,即springmvc和fegin都使用fastjson来序列化
     * @return fastjson转换器对象,日期格式都是yyyy-MM-dd HH:mm:ss.SSS
     */
    public static HttpMessageConverter createFastJsonConverter(){
        FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter();
        List<MediaType> supportedMediaTypes = new ArrayList<>();
        supportedMediaTypes.add(MediaType.APPLICATION_JSON);
        supportedMediaTypes.add(MediaType.APPLICATION_JSON_UTF8);
        supportedMediaTypes.add(MediaType.APPLICATION_ATOM_XML);
        supportedMediaTypes.add(MediaType.APPLICATION_FORM_URLENCODED);
        supportedMediaTypes.add(MediaType.APPLICATION_OCTET_STREAM);
        supportedMediaTypes.add(MediaType.APPLICATION_PDF);
        supportedMediaTypes.add(MediaType.APPLICATION_RSS_XML);
        supportedMediaTypes.add(MediaType.APPLICATION_XHTML_XML);
        supportedMediaTypes.add(MediaType.APPLICATION_XML);
        supportedMediaTypes.add(MediaType.IMAGE_GIF);
        supportedMediaTypes.add(MediaType.IMAGE_JPEG);
        supportedMediaTypes.add(MediaType.IMAGE_PNG);
        supportedMediaTypes.add(MediaType.TEXT_EVENT_STREAM);
        supportedMediaTypes.add(MediaType.TEXT_HTML);
        supportedMediaTypes.add(MediaType.TEXT_MARKDOWN);
        //supportedMediaTypes.add(MediaType.TEXT_PLAIN);
        supportedMediaTypes.add(MediaType.TEXT_XML);
        fastConverter.setSupportedMediaTypes(supportedMediaTypes);
        //创建配置类
        FastJsonConfig fastJsonConfig = new FastJsonConfig();
        //修改配置返回内容的过滤
        //WriteNullListAsEmpty  ï¼šList字段如果为null,输出为[],而非null
        //WriteNullStringAsEmpty ï¼š å­—符类型字段如果为null,输出为"",而非null
        //DisableCircularReferenceDetect ï¼šæ¶ˆé™¤å¯¹åŒä¸€å¯¹è±¡å¾ªçŽ¯å¼•ç”¨çš„é—®é¢˜ï¼Œé»˜è®¤ä¸ºfalse(如果不配置有可能会进入死循环)
        //WriteNullBooleanAsFalse:Boolean字段如果为null,输出为false,而非null
        //WriteMapNullValue:是否输出值为null的字段,默认为false
        fastJsonConfig.setSerializerFeatures(
                SerializerFeature.DisableCircularReferenceDetect,
                SerializerFeature.WriteMapNullValue
        );
        fastJsonConfig.setDateFormat(VciDateUtil.DateTimeMillFormat);
        fastConverter.setFastJsonConfig(fastJsonConfig);
        return fastConverter;
    }
    /**
     * è®¾ç½®æ ¼å¼è½¬æ¢å™¨ï¼Œåœ¨æŽ¥æ”¶åˆ°å‚数封装到对象时使用
     * @param registry æ ¼å¼æ³¨å†Œå™¨
     */
    @Override
    public void addFormatters(FormatterRegistry registry) {
        //添加日期的转换器
        registry.addConverter(new String2DateConverterForSpringMvc());
        //registry.addConverter(new StringEscapeEditor());
    }
    /**
     * æ·»åŠ éœ€è¦è½¬æ¢çš„è·¯å¾„,常用于读取tomcat外部的路径
     * @param registry èµ„源转换注册器
     */
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry){
        if(resourceFolderMap!=null){
            for(String resourceUrl :resourceFolderMap.keySet() ){
                String folder = resourceFolderMap.get(resourceUrl);
                if(folder.contains("$[projectPath]")){
                    folder = folder.replace("$[projectPath]", LocalFileUtil.getProjectFolder(LocalFileUtil.mainClass));
                }
                log.info("注册了外部路径转换器, " + resourceUrl + ":" + folder);
                registry.addResourceHandler("/" + resourceUrl + "/**").addResourceLocations("file:" + folder + File.separator);
            }
        }
        String logs = "file:" + LocalFileUtil.getProjectFolder(LocalFileUtil.mainClass) + File.separator + "logs" +File.separator;
        log.info("日志的文件夹映射为" + logs);
        registry.addResourceHandler("/log/**").addResourceLocations( logs);
        registry.addResourceHandler("/doc/**").addResourceLocations( "classpath:/md/");
        registry.addResourceHandler("/**")
                .addResourceLocations("classpath:/META-INF/resources/")
                .addResourceLocations("classpath:/resources/")
                .addResourceLocations("classpath:/static/")
                .addResourceLocations("classpath:/html/")
                .addResourceLocations("classpath:/public/").setCacheControl(CacheControl.noStore());
    }
    /**
     * é…ç½®index
     * @param registry æ³¨å†Œå™¨
     */
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/").setViewName("forward:index.html");
    }
    /**
     * è®¾ç½®é»˜è®¤çš„语言为简体中文
     * @return é»˜è®¤è¯­è¨€è§£æžå™¨
     */
    @Bean
    public LocaleResolver localeResolver(){
        SessionLocaleResolver localeResolver = new SessionLocaleResolver();
        localeResolver.setDefaultLocale(Locale.SIMPLIFIED_CHINESE);
        return localeResolver;
    }
    /**
     * é…ç½®æ‹¦æˆªå™¨
     * @param registry æ‹¦æˆªå™¨æ³¨å†Œå™¨
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry){
/*        preHandle按拦截器定义顺序地调用
        postHandle按拦截器定义逆序地调用
        afterCompletion按拦截器定义逆序地调用
        postHandle在截器链内所有拦截器返回成功调用
        afterCompletion只有在preHandle返回true才调用*/
        //1. éœ€è¦é…ç½®å¤šè¯­çš„æ‹¦æˆªå™¨ï¼Œé…ç½®å¤šè¯­çŽ¯å¢ƒ
        //2. éœ€è¦é…ç½®token的拦截器,这个必须在权限拦截器之前,里面包括用户的session信息,日志的
        //3. é…ç½®æƒé™çš„æ‹¦æˆªå™¨ï¼Œå¦‚果不符合要求则返回异常。需要处理系统访问的权限,接口访问的权限,数据访问的权限三种类型
        //4. æ›´æ–°ç”¨æˆ·è¯·æ±‚的最后时间
        //添加日志的MDC
        registry.addInterceptor(vciLogBeforeInterceptor());
        //多语言
        registry.addInterceptor(vciLocaleInterceptor());
        registry.addInterceptor(vciSecurityInterceptor()).excludePathPatterns("/error").excludePathPatterns("/**.*");
        //移除日志的MDC
        registry.addInterceptor(vciLogAfterInterceptor());
    }
    /**
     * å¤šè¯­è¨€ç›¸å…³çš„æ‹¦æˆªå™¨
     * @return å¤šè¯­è¨€æ‹¦æˆªå™¨
     */
    @Bean
    public VciLocaleInterceptor vciLocaleInterceptor(){
        return new VciLocaleInterceptor();
    }
    /**
     * å®‰å…¨ç›¸å…³çš„æ‹¦æˆªå™¨
     * @return å®‰å…¨ç›¸å…³çš„æ‹¦æˆªå™¨
     */
    @Bean
    public VciSecurityInterceptor vciSecurityInterceptor(){
        return new VciSecurityInterceptor();
    }
    /**
     * æ—¥å¿—相关的拦截器
     * @return æ—¥å¿—拦截器
     */
    @Bean
    public VciLogBeforeInterceptor vciLogBeforeInterceptor(){
        return new VciLogBeforeInterceptor();
    }
    /**
     * æ—¥å¿—相关的拦截器
     * @return æ—¥å¿—拦截器
     */
    @Bean
    public VciLogAfterInterceptor vciLogAfterInterceptor(){
        return new VciLogAfterInterceptor();
    }
    /**
     * è®¾ç½®è·¨åŸŸ
     * @param registry è·¨åŸŸæ³¨å†Œå™¨
     */
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        log.info("进入跨域配置");
        if(corsProperties !=null && "true".equalsIgnoreCase(corsProperties.getEnabled())) {
            log.info("打开了跨域开关");
            String[] allowedOrigins = corsProperties.getAllowedOrigins();
            String[] allowedHeaders = corsProperties.getAllowedHeaders();
            String[] allowedMethods = corsProperties.getAllowedMethods();
            String[] exposedHeaders = corsProperties.getExposedHeaders();
            Boolean allowCredentials = corsProperties.getAllowCredentials();
            Long maxAge = corsProperties.getMaxAge();
            log.info("注册跨域内容 = [" + allowedOrigins + "]");
            String mappings = corsProperties.getMappings();
            if (allowedHeaders == null || allowedHeaders.length == 0) {
                allowedHeaders = DEFAULT_ALLOWED_HEADERS;
            }
            if (allowedOrigins == null || allowedOrigins.length == 0) {
                allowedOrigins = DEFAULT_ORIGINS;
            }
            if (exposedHeaders == null || exposedHeaders.length == 0) {
                exposedHeaders = DEFAULT_EXPOSEDHEADERS;
            }
            if (allowedMethods == null || allowedMethods.length == 0){
                allowedMethods = DEFAULT_METHODS;
            }
            if (maxAge == null || maxAge == 0) {
                maxAge = DEFAULT_MAX_AGE;
            }
            if (allowCredentials == null) {
                allowCredentials = DEFAULT_ALLOW_CREDENTIALS;
            }
            if (mappings == null || mappings.trim() == "") {
                mappings = "/**";
            }
            log.info("跨域映射的URL:" + mappings);
            registry.addMapping(mappings)
                    .allowedOrigins(allowedOrigins)
                    .allowedMethods(allowedMethods)
                    .allowedHeaders(allowedHeaders)
                    .exposedHeaders(exposedHeaders)
                    .allowCredentials(allowCredentials).maxAge(maxAge);
        }else{
            log.info("没有打开跨域开关");
        }
    }
    public CorsProperties getCorsProperties() {
        return corsProperties;
    }
    public void setCorsProperties(CorsProperties corsProperties) {
        this.corsProperties = corsProperties;
    }
    public String[] getDEFAULT_ORIGINS() {
        return DEFAULT_ORIGINS;
    }
    public void setDEFAULT_ORIGINS(String[] DEFAULT_ORIGINS) {
        this.DEFAULT_ORIGINS = DEFAULT_ORIGINS;
    }
    public String[] getDEFAULT_ALLOWED_HEADERS() {
        return DEFAULT_ALLOWED_HEADERS;
    }
    public void setDEFAULT_ALLOWED_HEADERS(String[] DEFAULT_ALLOWED_HEADERS) {
        this.DEFAULT_ALLOWED_HEADERS = DEFAULT_ALLOWED_HEADERS;
    }
    public String[] getDEFAULT_METHODS() {
        return DEFAULT_METHODS;
    }
    public void setDEFAULT_METHODS(String[] DEFAULT_METHODS) {
        this.DEFAULT_METHODS = DEFAULT_METHODS;
    }
    public boolean isDEFAULT_ALLOW_CREDENTIALS() {
        return DEFAULT_ALLOW_CREDENTIALS;
    }
    public void setDEFAULT_ALLOW_CREDENTIALS(boolean DEFAULT_ALLOW_CREDENTIALS) {
        this.DEFAULT_ALLOW_CREDENTIALS = DEFAULT_ALLOW_CREDENTIALS;
    }
    public long getDEFAULT_MAX_AGE() {
        return DEFAULT_MAX_AGE;
    }
    public void setDEFAULT_MAX_AGE(long DEFAULT_MAX_AGE) {
        this.DEFAULT_MAX_AGE = DEFAULT_MAX_AGE;
    }
    public List<String> getUnCheckUrls() {
        return unCheckUrls;
    }
    public void setUnCheckUrls(List<String> unCheckUrls) {
        this.unCheckUrls = unCheckUrls;
    }
    public List<String> getUnStorageRequestTimeUrls() {
        return unStorageRequestTimeUrls;
    }
    public void setUnStorageRequestTimeUrls(List<String> unStorageRequestTimeUrls) {
        this.unStorageRequestTimeUrls = unStorageRequestTimeUrls;
    }
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/autoconfigure/VciAsyncConfig.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,109 @@
package com.vci.starter.web.autoconfigure;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.Executor;
/**
 * timer需要的默认的线程池
 * @author weidy
 * @date 2021-2-2
 */
@Configuration
@EnableAsync
@ConditionalOnProperty(prefix = "vciasync",name="enabled",havingValue = "true",matchIfMissing = false)
public class VciAsyncConfig {
    /**
     * åˆå§‹åŒ–大小
     */
    private int corePoolSize;
    /**
     * æœ€å¤§çš„值
     */
    private int maxPoolSize;
    /**
     * é˜Ÿåˆ—的个数
     */
    private int queueCapacity;
    /**
     * å­˜æ´»æ—¶é—´
     */
    private int keepAliveSeconds = 60;
    /**
     * é»˜è®¤çš„线程池,
     * @return çº¿ç¨‹æ± å¯¹è±¡
     */
    @Bean
    @ConditionalOnMissingBean
    public Executor taskExecutor() {
        ThreadPoolTaskExecutor executor = new VciThreadPoolTaskExecutor();
        int cpu =  Runtime.getRuntime().availableProcessors();
        if(getCorePoolSize() == 0){
            setCorePoolSize(cpu);
        }
        if(getMaxPoolSize() == 0){
            setMaxPoolSize(2* cpu);
        }
        if(getQueueCapacity() == 0){
            setQueueCapacity(100);
        }
        executor.setCorePoolSize(getCorePoolSize());
        executor.setMaxPoolSize(getMaxPoolSize());
        executor.setQueueCapacity(getQueueCapacity());
        executor.setKeepAliveSeconds(getKeepAliveSeconds());
        executor.initialize();
        return executor;
    }
    public int getCorePoolSize() {
        return corePoolSize;
    }
    public void setCorePoolSize(int corePoolSize) {
        this.corePoolSize = corePoolSize;
    }
    public int getMaxPoolSize() {
        return maxPoolSize;
    }
    public void setMaxPoolSize(int maxPoolSize) {
        this.maxPoolSize = maxPoolSize;
    }
    public int getQueueCapacity() {
        return queueCapacity;
    }
    public void setQueueCapacity(int queueCapacity) {
        this.queueCapacity = queueCapacity;
    }
    public int getKeepAliveSeconds() {
        return keepAliveSeconds;
    }
    public void setKeepAliveSeconds(int keepAliveSeconds) {
        this.keepAliveSeconds = keepAliveSeconds;
    }
    @Override
    public String toString() {
        return "VciAsyncConfig{" +
                "corePoolSize=" + corePoolSize +
                ", maxPoolSize=" + maxPoolSize +
                ", queueCapacity=" + queueCapacity +
                '}';
    }
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/autoconfigure/VciThreadPoolTaskExecutor.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,113 @@
package com.vci.starter.web.autoconfigure;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.util.concurrent.ListenableFuture;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
 * çº¿ç¨‹æ± ,增加监控
 * @author weidy
 * @date 2021-2-2
 */
public class VciThreadPoolTaskExecutor extends ThreadPoolTaskExecutor {
    /**
     * æ—¥å¿—
     */
    private static final Logger logger = LoggerFactory.getLogger(VciThreadPoolTaskExecutor.class);
    /**
     * æ‰“印日志
     * @param prefix å‰ç¼€
     */
    private void printLog(String prefix){
        ThreadPoolExecutor threadPoolExecutor = getThreadPoolExecutor();
        if (null == threadPoolExecutor) {
            return;
        }
        logger.info(prefix + ", task_count [" + threadPoolExecutor.getTaskCount()
                + "], completed_task_count [" + threadPoolExecutor.getCompletedTaskCount()
                + "], active_thread_count [" + threadPoolExecutor.getActiveCount()
                + "], blocking_queue_size [" + threadPoolExecutor.getQueue().size()
                + "], thread_pool_size [" + threadPoolExecutor.getPoolSize()
                + "], largest_pool_size_ever [" + threadPoolExecutor.getLargestPoolSize()
                + "], core_thread_pool_size [" + threadPoolExecutor.getCorePoolSize()
                + "], max_thread_pool_size [" + threadPoolExecutor.getMaximumPoolSize()
                + "], thread_keep_alive_time [" + threadPoolExecutor.getKeepAliveTime(TimeUnit.SECONDS)
                + "]");
    }
    /**
     * æ‰§è¡Œ
     * @param task ä»»åŠ¡çš„å¯¹è±¡
     */
    @Override
    public void execute(Runnable task) {
        printLog("1. do execute æ‰§è¡Œä»»åŠ¡");
        super.execute(task);
    }
    /**
     * æ‰§è¡Œä»»åŠ¡ï¼Œå¹¶è®¾ç½®è¶…æ—¶
     * @param task ä»»åŠ¡çš„å¯¹è±¡
     * @param startTimeout è¶…æ—¶
     */
    @Override
    public void execute(Runnable task, long startTimeout) {
        printLog("2. do execute,执行任务,并且设置超时" );
        super.execute(task, startTimeout);
    }
    /**
     * æäº¤
     * @param task ä»»åŠ¡
     * @return æ‰§è¡Œ
     */
    @Override
    public Future<?> submit(Runnable task) {
        printLog("1. do submit,提交");
        return super.submit(task);
    }
    /**
     * æäº¤
     * @param task ä»»åŠ¡
     * @param <T> ç±»åž‹
     * @return ç±»åž‹
     */
    @Override
    public <T> Future<T> submit(Callable<T> task) {
        printLog("2. do submit");
        return super.submit(task);
    }
    /**
     * æäº¤å¯ç›‘听
     * @param task ä»»åŠ¡
     * @return ç›‘听
     */
    @Override
    public ListenableFuture<?> submitListenable(Runnable task) {
        printLog("1. do submitListenable");
        return super.submitListenable(task);
    }
    /**
     * æäº¤å¯ç›‘听
     * @param task ä»»åŠ¡
     * @param <T> ç±»åž‹
     * @return ç›‘听的类型
     */
    @Override
    public <T> ListenableFuture<T> submitListenable(Callable<T> task) {
        printLog("2. do submitListenable");
        return super.submitListenable(task);
    }
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/clientutil/BaseClientUtil.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,103 @@
package com.vci.starter.web.clientutil;
import com.vci.starter.web.exception.VciBaseException;
import com.vci.starter.web.pagemodel.BaseResult;
import com.vci.starter.web.pagemodel.DataGrid;
import com.vci.starter.web.util.LangBaseUtil;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
/**
 * é»˜è®¤çš„客户端调用类
 * @author weidy
 */
public interface BaseClientUtil{
    /**
     * ä½¿ç”¨è°ƒç”¨å™¨æŸ¥è¯¢data类型的属性
     * @param interfaceName æŽ¥å£çš„名称,可以不要多语
     * @param clientUtilProcesser è°ƒç”¨å™¨æ‰§è¡Œå‡½æ•°
     * @param <T> è¿”回结果的类型
     * @return åˆ—表数据
     * @throws VciBaseException å‚数错误,调用错误会抛出异常
     */
   default <T> List<T> queryData(String interfaceName,ClientUtilProcesser<T> clientUtilProcesser) throws VciBaseException {
       List<T> dataList = new ArrayList<>();
       BaseResult<T> result = queryByProvider(interfaceName,clientUtilProcesser);
       dataList.addAll(result.getData());
       return dataList;
   }
    /**
     * ä½¿ç”¨è°ƒç”¨å™¨æŸ¥è¯¢
     * @param interfaceName æŽ¥å£çš„名称
     * @param clientUtilProcesser è°ƒç”¨å™¨æ‰§è¡Œå‡½æ•°
     * @param <T> è¿”回的类型
     * @return æ‰§è¡Œçš„结果
     * @throws VciBaseException è°ƒç”¨é”™è¯¯çš„æ—¶å€™ä¼šæŠ›å‡ºå¼‚常
     */
   default <T> BaseResult<T> queryByProvider(String interfaceName,ClientUtilProcesser<T> clientUtilProcesser) throws VciBaseException {
       try{
           BaseResult<T> result = null;
           if (clientUtilProcesser != null ) {
               result  = clientUtilProcesser.queryByProvider();
           }
           if(result == null){
               throw new VciBaseException("调用【{0}】接口,服务端没有返回值",new String[]{interfaceName});
           }
           if(!result.isSuccess()){
               throw new VciBaseException(result.getMsg(),result.getMsgObjs());
           }
           return result;
       }catch (VciBaseException e){
           throw e;
       }catch (Throwable e){
           throw new VciBaseException(LangBaseUtil.getErrorMsg(e),new String[0],e);
       }
   }
    /**
     * ä½¿ç”¨è°ƒç”¨æŸ¥è¯¢obj类型的属性
     * @param interfaceName æŽ¥å£æ–¹æ³•的名字
     * @param clientUtilProcesser  è°ƒç”¨å™¨æ‰§è¡Œå‡½æ•°
     * @param <T> è¿”回的结果累成,取决于调用器的返回值
     * @return obj属性的值
     * @throws VciBaseException è°ƒç”¨é”™è¯¯æ—¶ä¼šæŠ›å‡ºå¼‚常
     */
   default <T> T queryObj(String interfaceName,ClientUtilProcesser<T> clientUtilProcesser) throws VciBaseException {
       return queryByProvider(interfaceName,clientUtilProcesser).getObj();
   }
    /**
     * æŸ¥è¯¢åˆ—表数据
     * @param interfaceName æŽ¥å£æ–¹æ³•的名字
     * @param clientUtilProcesser  è°ƒç”¨å™¨æ‰§è¡Œå‡½æ•°
     * @param <T> è¿”回的结果,取决于调用器的返回值
     * @return åˆ—表数据
     * @throws VciBaseException è°ƒç”¨é”™è¯¯æ—¶ä¼šæŠ›å‡ºå¼‚常
     */
   default <T> DataGrid<T> queryGrid(String interfaceName,ClientUtilProcesser<T> clientUtilProcesser) throws VciBaseException{
       BaseResult<T> result = queryByProvider(interfaceName,clientUtilProcesser);
       DataGrid<T> dataGrid = new DataGrid<>();
       if(result.getData()!=null) {
           dataGrid.setData(result.getData().stream().collect(Collectors.toList()));
       }
       dataGrid.setTotal(result.getTotal());
       return dataGrid;
   }
    /**
     * æ‰§è¡Œæ•°æ®ï¼Œè¿”回执行结果
     * @param interfaceName æŽ¥å£æ–¹æ³•的名字
     * @param clientUtilProcesser  è°ƒç”¨å™¨æ‰§è¡Œå‡½æ•°
     * @param <T> è¿”回的结果,取决于调用器的返回值
     * @return true表示成功,失败的时候会直接抛出异常
     * @throws VciBaseException è°ƒç”¨é”™è¯¯æ—¶ä¼šæŠ›å‡ºå¼‚常
     */
   default <T> boolean executeData(String interfaceName,ClientUtilProcesser<T> clientUtilProcesser) throws VciBaseException{
       BaseResult<T> result = queryByProvider(interfaceName,clientUtilProcesser);
       return result.isSuccess();
   }
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/clientutil/ClientUtilProcesser.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,18 @@
package com.vci.starter.web.clientutil;
import com.vci.starter.web.pagemodel.BaseResult;
/**
 * å®¢æˆ·ç«¯è°ƒç”¨ç±»çš„通用
 * @author weidy
 */
@FunctionalInterface
public interface ClientUtilProcesser<T> {
    /**
     * ä½¿ç”¨è°ƒç”¨å™¨æŸ¥è¯¢
     * @return æ‰§è¡Œçš„结果
     */
    BaseResult<T> queryByProvider();
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/constant/CommonReturnCodeConstant.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,60 @@
package com.vci.starter.web.constant;
/**
 * å¸¸ç”¨è¿”回值
 * @author weidy
 */
public class CommonReturnCodeConstant {
    /**
     * æ²¡æœ‰ç™»å½•
     */
    public static final String NO_LOGIN = "NO_LOGIN";
    /**
     * æ²¡æœ‰æƒé™
     */
    public static final String NO_RIGHT = "NO_RIGHT";
    /**
     * è¢«å¼ºåˆ¶ä¸‹çº¿
     */
    public static final String POP_OFFLINE ="POP_OFFLINE";
    /**
     * æ²¡æœ‰æ•°æ®æƒé™
     */
    public static final String NO_DATA_RIGHT = "NO_DATA_RIGHT";
    /**
     * æ²¡æœ‰UI权限
     */
    public static final String NO_UI_RIGHT = "NO_UI_RIGHT";
    /**
     * ç”¨æˆ·å¯†çº§ä¸å…è®¸
     */
    public static final String USER_SECRET_LOW = "USER_SECRET_LOW";
    /**
     * è¯·æ±‚路径没有找到
     */
    public static final String URL_NOT_FOUND = "URL_NOT_FOUND";
    /**
     * å‡ºçŽ°äº†å¼‚å¸¸
     */
    public static final String EXCEPTION = "EXCEPTION";
    /**
     * å‚数错误
     */
    public static final String PARAM_ERROR="PARAM_ERROR";
    /**
     * æ•°æ®é‡å¤
     */
    public static final String DATA_REPEAT = "dataRepeat";
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/constant/FileExtensionConstant.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,79 @@
package com.vci.starter.web.constant;
/**
 * å¸¸ç”¨æ–‡ä»¶çš„后缀名
 * @author weidy
 * @date 2020/5/5
 */
public class FileExtensionConstant {
    /**
     * excel2003文件
     */
    public static final String XLS = "xls";
    /**
     * excel2007及以上版本文件
     */
    public static final String XLSX = "xlsx";
    /**
     * word2003文件
     */
    public static final String DOC = "doc";
    /**
     * word2007及以上版本文件
     */
    public static final String DOCX = "docx";
    /**
     * å¹»ç¯ç‰‡2003文件
     */
    public static final String PPT = "ppt";
    /**
     * å¹»ç¯ç‰‡2007及以上版本
     */
    public static final String PPTX = "pptx";
    /**
     * Pdf文件
     */
    public static final String PDF = "pdf";
    /**
     * æ–‡æœ¬æ–‡ä»¶
     */
    public static final String TXT ="txt";
    /**
     * ç½‘页文件
     */
    public static final String HTML = "html";
    /**
     * è¡¨å•文件
     */
    public static final String DVF = "dvf";
    /**
     * æ¨¡æ¿
     */
    public static final String DTF = "dtf";
    /**
     * å›¾ç‰‡
     */
    public static final String PNG = "png";
    /**
     * jpg图片
     */
    public static final String JPG = "jpg";
    /**
     * XPS
     */
    public static final String XPS = "xps";
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/constant/FrameWorkLcStatusConstant.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,24 @@
package com.vci.starter.web.constant;
/**
 * å¹³å°æ¡†æž¶çš„生命周期的编号
 * @author weidy
 * @date 2019/12/27
 */
public class FrameWorkLcStatusConstant {
    /**
     * å¹³å°æ¡†æž¶çš„业务档案通用的生命周期
     */
    public static final String FRAME_WORK_LIFE_CYCLE_NAME = "frameworkDataLc";
    /**
     * é»˜è®¤çš„生命周期
     */
    public static final String EMTYPE_LIFE_CYCLE = "defaultLC";
    /**
     * é€šç”¨çš„发布生命周期,编制,审核,发布
     */
    public static final String RELEASE_LIFE_CYCLE = "releaseDataLc";
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/constant/QueryOptionConstant.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,76 @@
package com.vci.starter.web.constant;
/**
 * æŸ¥è¯¢ç±»åž‹
 * @author weidy
 */
public class QueryOptionConstant {
    /**
     * IN
     */
    public  static  final String IN = "\\IN";
    /**
     * NOT IN
     */
    public     static  final String NOTIN ="\\NOTIN";
    /**
     * ä¸ç­‰äºŽ
     */
    public  static  final String NOTEQUAL = "!=";
    /**
     *  å¤§äºŽ
     */
    public  static  final String MORE=">";
    /**
     * å¤§äºŽç­‰äºŽ
     */
    public  static  final String MORETHAN=">=";
    /**
     * å°äºŽ
     */
    public  static  final String LESS = "<";
    /**
     * å°äºŽç­‰äºŽ
     */
    public  static  final String LESSTHAN = "<=";
    /**
     * æˆ–者
     */
    public  static  final String OR = "\\OR";
    /**
     * ç­‰äºŽç©º
     */
    public  static  final String ISNULL ="=null";
    /**
     * ä¸ç­‰äºŽç©º
     */
    public  static  final String ISNOTNULL="!=null";
    /**
     * ç­‰äºŽ
     */
    public static  final String  EQUAL = "=";
    /**
     * ä¸Ž
     */
    public static final String AND = "and";
    /**
     * æ—¢ä¸æ˜¯and,也不是or的方式。这种是直接拼接到where后
     */
    public static final String NO_OR_AND = "${no_or_and}";
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/constant/RegExpConstant.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,84 @@
package com.vci.starter.web.constant;
/**
 * æ­£åˆ™è¡¨è¾¾å¼
 * @author weidy
 * @date 2019/10/18 17:35
 */
public class RegExpConstant {
    /**
     * åŒ…含中文
     */
    public static final String INCLUDE_CHINESE = "[\u0391-\uFFE5]";
    /**
     * å…¨éƒ¨æ˜¯æ•°å­—
     */
    public static final String NUMBER = "^[0-9]*$";
    /**
     * æ•´æ•°
     */
    public static final String INT = "/^-?[1-9]+[0-9]*$/";
    /**
     * é•¿æ•´å½¢
     */
    public static final String LONG = "/^-?[1-9]+[0-9]*$/";
    /**
     * åŒç²¾åº¦
     */
    public static final String DOUBLE = "[0-9]*(\\.[0-9]*|[eE][+-][0-9]*)$";
    /**
     * å…¨éƒ¨éƒ½æ˜¯å­—母
     */
    public static final String LETTER = "^[A-Za-z]+$";
    /**
     * å­—母和数字
     */
    public static final String LETTER_AND_NUMBER = "^[A-Za-z0-9]+$";
    /**
     * å…¨éƒ¨æ˜¯å¤§å†™å­—母
     */
    public static final String UP_LETTER = "^[A-Z]+$";
    /**
     * å…¨éƒ¨æ˜¯å°å†™å­—母
     */
    public static final String LOW_LETTER = "^[a-z]+$";
    /**
     * å…¨éƒ¨ç‰¹æ®Šå­—符
     */
    public static final String SPECIAL_CHARACTER = "^[` ~!@#$%^&*()_\\-+=<>?:\"{}|,.\\/;'\\[\\]·~!@#ï¿¥%……&*()——\\-+={}|《》?:“”【】、;‘’,。、]+$";
    /**
     * åŒ…含有字母
     */
    public static final String HAS_LETTER = ".*[a-z][A-Z]{1,}.*";
    /**
     * åŒ…含有大写字母
     */
    public static final String HAS_UP_LETTER = ".*[A-Z]{1,}.*";
    /**
     * åŒ…含有小写字母
     */
    public static final String HAS_LOW_LETTER = ".*[a-z]{1,}.*";
    /**
     * åŒ…含有阿拉伯数字
     */
    public static final String HAS_NUMBER  = ".*[0-9]{1,}.*";
    /**
     * åŒ…含有特殊字符
     */
    public static final String HAS_SPECIAL_CHARACTER = ".*[` ~!@#$%^&*()_\\-+=<>?:\"{}|,.\\/;'\\[\\]·~!@#ï¿¥%……&*()——\\-+={}|《》?:“”【】、;‘’,。、]{1,}.*";
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/constant/RevisionConstant.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,19 @@
package com.vci.starter.web.constant;
/**
 * é»˜è®¤çš„版本规则的名称
 * @author weidy
 * @date 2020/4/15
 */
public class RevisionConstant {
    /**
     * ä»¥å­—母大A开始的编码规则,没有前缀和后缀,步长为1,并且也没有跳跃字符
     */
    public static final String CHARACTER = "characterversionrule";
    /**
     * ä»¥æ•°å­—
     */
    public static final String NUMBER = "numberversionrule";
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/constant/SpecialCharacterConstant.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,60 @@
package com.vci.starter.web.constant;
/**
 * ç‰¹æ®Šçš„符号,为了符合规范,请勿在判断语句中直接写符号内容
 * @author weidy
 * @date 2020/5/5
 */
public class SpecialCharacterConstant {
    /**
     * è‹±æ–‡å¥å·
     */
    public static final String POINT = ".";
    /**
     * ä¸‹åˆ’线
     */
    public static final String UNDER_LINE = "_";
    /**
     * è¿žæŽ¥æ¨ªçº¿
     */
    public static final String CONNECTOR = "-";
    /**
     * ç­‰å·
     */
    public static final String EQUAL = "=";
    /**
     * åˆ†å·
     */
    public static final String SEMICOLON = ";";
    /**
     * é€—号
     */
    public static final String COMMA = ",";
    /**
     * ç¾Žå…ƒç¬¦å·
     */
    public static final String DOLLAR = "$";
    /**
     * æ˜Ÿå·
     */
    public static final String STAR = "*";
    /**
     * at符号
     */
    public static final String AT = "@";
    /**
     * #号
     */
    public static final String SHARP = "#";
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/constant/TokenKeyConstant.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,40 @@
package com.vci.starter.web.constant;
/**
 * token的相关key
 * @author weidy
 * @date 2019/11/7 10:10 AM
 */
public class TokenKeyConstant {
    /**
     * ç”¨æˆ·çš„token传输时使用的名称
     */
    public static final String USER_TOKEN_KEY ="AuthorizationToken";
    /**
     * ç³»ç»Ÿçš„token传输时使用的名称
     */
    public static final String SYSTEM_PRIVATE_KEY = "AuthorizationSystemToken";
    /**
     * ç³»ç»Ÿçš„æ—¥å¿—链路主键传输时使用的名称
     */
    public static final String LOG_TRACE_ID_KEY = "AuthorizationLogTraceId";
    /**
     * æ—¥å¿—的追踪主键的名称
     */
    public static final String TRACE_ID = "logTraceId";
    /**
     * ç³»ç»Ÿçš„多语参数名称
     */
    public static final String LANGUAGE_KEY = "vciLanguageCode";
    /**
     * è¯·æ±‚的时间参数
     */
    public static final String REQUEST_TIMESTAMP = "vciHttpStartRequestTime";
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/constant/VciSystemVarConstants.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,152 @@
package com.vci.starter.web.constant;
import com.vci.starter.web.pagemodel.SessionInfo;
import com.vci.starter.web.util.VciBaseUtil;
import com.vci.starter.web.util.VciDateUtil;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
/**
 * ç³»ç»Ÿå˜é‡
 * @author weidy
 */
public  class VciSystemVarConstants {
    /**
     * åˆå§‹åŒ–的时候放入数据
     */
    public VciSystemVarConstants(){
        SYSTEM_VAR_KEYNAMEMAP.put(CURRENTTIME,"当前时间");
        SYSTEM_VAR_KEYNAMEMAP.put(CURRENTDATE,"当前日期");
        SYSTEM_VAR_KEYNAMEMAP.put(CURRENTDATETIME,"当前日期时间");
        SYSTEM_VAR_KEYNAMEMAP.put(CURRENTUSER_OID,"当前用户主键");
        SYSTEM_VAR_KEYNAMEMAP.put(CURRENTUSER_ID,"当前用户账户");
        SYSTEM_VAR_KEYNAMEMAP.put(CURRENTUSER_NAME,"当前用户姓名");
        SYSTEM_VAR_KEYNAMEMAP.put(CURRENTUSER_SECRETGRADE,"当前用户密级");
        SYSTEM_VAR_KEYNAMEMAP.put(CURRENTUSER_IP_SECRET,"当前用户的机器密级");
        SYSTEM_VAR_KEYNAMEMAP.put(CURRENTUSER_GROUPOID,"当前用户的部门的主键");
//        SYSTEM_VAR_KEYNAMEMAP.put(CURRENTUSER_GROUPNUM,"当前用户所属部门编号");
        SYSTEM_VAR_KEYNAMEMAP.put(CURRENTUSER_GROUPNAME,"当前用户所属部门名称");
        SYSTEM_VAR_KEYNAMEMAP.put(CURRENTUSER_EMAIL,"当前用户邮件地址");
        SYSTEM_VAR_KEYNAMEMAP.put(CURRENTUSER_ROLENAME,"当前用户所属角色名称");
        SYSTEM_VAR_KEYNAMEMAP.put(CURRENTUSER_BUSINESS_UNIT,"当前用户所属业务单元主键");
        SYSTEM_VAR_KEYNAMEMAP.put(CURRENTUSER_BUSINESS_UNIT_NAME,"当前用户所属业务单元");
    }
    /**
     * å½“前用户主键
     */
    public static final String CURRENTUSER_OID = "#CURRENTUSER.OID#";
    /**
     * å½“前用户账户
     */
    public static final String CURRENTUSER_ID = "#CURRENTUSER.ID#";
    /**
     * å½“前时间
     */
    public static final String CURRENTTIME = "#CURRENTTIME#";
    /**
     * å½“前日期
     */
    public static final String CURRENTDATE = "#CURRENTDATE#";
    /**
     * å½“前日期时间
     */
    public static final String CURRENTDATETIME = "#CURRENTDATETIME#";
    /**
     * å½“前用户姓名
     */
    public static final String CURRENTUSER_NAME = "#CURRENTUSER_NAME#";
    /**
     * å½“前用户密级
     */
    public static final String CURRENTUSER_SECRETGRADE = "#CURRENTUSER.SECRETGRADE#";
    /**
     * å½“前用户的IP密级
     */
    public static final String CURRENTUSER_IP_SECRET = "#CURRENTUSER.IPSECRET#";
    /**
     * å½“前用户所属业务单元
     */
    public static final String CURRENTUSER_BUSINESS_UNIT = "#CURRENTUSER.BUSINESSUNIT#";
    /**
     * å½“前用户所属业务单元名称
     */
    public static final String CURRENTUSER_BUSINESS_UNIT_NAME = "#CURRENTUSER.BUSINESSUNITNAME#";
//    /**
//     * å½“前用户所属部门编号
//     */
//    public static final String CURRENTUSER_GROUPNUM = "#CURRENTUSER.GROUPNUM#";
    /**
     * å½“前用户的部门主键
     */
    public static final String CURRENTUSER_GROUPOID = "#CURRENTUSER.GROUPOID#";
    /**
     * å½“前用户所属部门名称
     */
    public static final String CURRENTUSER_GROUPNAME = "#CURRENTUSER.GROUPNAME#";
    /**
     * å½“前用户邮件地址
     */
    public static final String CURRENTUSER_EMAIL  ="#CURRENTUSER.EMAIL#";
    /**
     * å½“前用户所属角色名称
     */
    public static final String CURRENTUSER_ROLENAME = "#CURRENTUSER.ROLENAME#";
    /**
     * ç³»ç»Ÿå˜é‡çš„æ•°ç»„
     */
    public static final String[] SYSTEM_VAR_KEYS = {CURRENTUSER_OID,CURRENTUSER_ID,CURRENTDATE,CURRENTTIME,CURRENTDATETIME,CURRENTUSER_GROUPOID,CURRENTUSER_NAME,CURRENTUSER_SECRETGRADE,
            CURRENTUSER_GROUPNAME,CURRENTUSER_EMAIL,CURRENTUSER_ROLENAME,CURRENTUSER_IP_SECRET,CURRENTUSER_BUSINESS_UNIT,CURRENTUSER_BUSINESS_UNIT_NAME};
    /**
     * ç³»ç»Ÿå˜é‡å¯¹åº”的中文
     */
    public static final Map<String,String> SYSTEM_VAR_KEYNAMEMAP = new HashMap<String, String>();
    /**
     * èŽ·å–ç³»ç»Ÿçš„å˜é‡çš„å€¼
     * @return å˜é‡çš„值
     */
    public static Map<String,String> getSystemVarValueMap(){
        Map<String,String> systemVarMap = new HashMap<>();
        SessionInfo sessionInfo = VciBaseUtil.getCurrentUserSessionInfo();
        if(sessionInfo!=null){
            systemVarMap.put(CURRENTUSER_OID,sessionInfo.getUserOid());
            systemVarMap.put(CURRENTUSER_ID,sessionInfo.getUserId());
            systemVarMap.put(CURRENTUSER_NAME,sessionInfo.getUserName());
            systemVarMap.put(CURRENTDATETIME, VciDateUtil.getNowString());
            systemVarMap.put(CURRENTDATE,VciDateUtil.getNowString(VciDateUtil.DateFormat));
            systemVarMap.put(CURRENTTIME,VciDateUtil.getNowString(VciDateUtil.TimeFormat));
            systemVarMap.put(CURRENTUSER_SECRETGRADE,sessionInfo.getUserSecret());
            systemVarMap.put(CURRENTUSER_GROUPNAME,sessionInfo.getDeptName());
            systemVarMap.put(CURRENTUSER_GROUPOID,sessionInfo.getDeptOid());
            systemVarMap.put(CURRENTUSER_EMAIL,sessionInfo.getEmail());
            systemVarMap.put(CURRENTUSER_ROLENAME, Optional.ofNullable(sessionInfo.getRolesName().values()).orElseGet(()->new ArrayList<>()).stream().collect(Collectors.joining(",")));
            systemVarMap.put(CURRENTUSER_IP_SECRET,sessionInfo.getIpSecret());
            systemVarMap.put(CURRENTUSER_BUSINESS_UNIT,sessionInfo.getOrgsOid());
            systemVarMap.put(CURRENTUSER_BUSINESS_UNIT_NAME,sessionInfo.getOrgsName());
        }
        return systemVarMap;
    }
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/enumpck/BaseEnum.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,22 @@
package com.vci.starter.web.enumpck;
/**
 * åŸºæœ¬çš„æžšä¸¾ç±»ï¼Œè¯·ç”Ÿå‘½å‘¨æœŸå’Œæžšä¸¾éƒ½å®žçŽ°è¿™ä¸ªæŽ¥å£ï¼Œå¦åˆ™æ— æ³•è¢«å¹³å°æ‰«æåˆ°
 * @author weidy
 * @date 2019/10/31 10:38 AM
 */
public interface BaseEnum {
    /**
     * èŽ·å–æžšä¸¾å€¼
     * @return æžšä¸¾å€¼
     */
    String getValue();
    /**
     * èŽ·å–æ˜¾ç¤ºæ–‡æœ¬
     * @return æ˜¾ç¤ºæ–‡æœ¬
     */
    String getText();
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/enumpck/BaseEnumInt.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,23 @@
package com.vci.starter.web.enumpck;
/**
 * åŸºæœ¬çš„æžšä¸¾ç±»ï¼Œè¯·ç”Ÿå‘½å‘¨æœŸå’Œæžšä¸¾éƒ½å®žçŽ°è¿™ä¸ªæŽ¥å£ï¼Œå¦åˆ™æ— æ³•è¢«å¹³å°æ‰«æåˆ°
 * è¿™ä¸ªæ˜¯å€¼ä¸ºæ•°å­—åž‹
 * @author weidy
 * @date 2019/10/31 10:38 AM
 */
public interface BaseEnumInt {
    /**
     * èŽ·å–æžšä¸¾å€¼
     * @return æžšä¸¾å€¼
     */
    int getValue();
    /**
     * èŽ·å–æ˜¾ç¤ºæ–‡æœ¬
     * @return æ˜¾ç¤ºæ–‡æœ¬
     */
    String getText();
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/enumpck/BooleanEnum.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,41 @@
package com.vci.starter.web.enumpck;
/**
 * å¹³å°é‡Œçš„VIBoolean类型字段
 * @author weidy
 */
public enum BooleanEnum {
    /**
     * true
     */
    TRUE("true"),
    /**
     * false
     */
    FASLE("false");
    /**
     * æžšä¸¾çš„值
     */
    private final String value ;
    /**
     * æžšä¸¾å†…部构造方法
     * @param value æžšä¸¾çš„值
     */
    private BooleanEnum(String value){
        this.value = value;
    }
    /**
     * èŽ·å–å€¼
     * @return æžšä¸¾å€¼
     */
    public String getValue() {
        return value;
    }
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/enumpck/DataBaseEnum.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,148 @@
package com.vci.starter.web.enumpck;
/**
 * æ•°æ®åº“的类型枚举
 * @author weidy
 * @date 2019/10/30 2:46 PM
 */
public enum DataBaseEnum implements BaseEnum{
    /**
     * MYSQL
     */
    MYSQL("mysql","MYSQL"),
    /**
     * ORACLE
     */
    ORACLE("oracle","ORACLE"),
    /**
     * POSTGRESQL
     */
    POSTGRESQL("postgresql","POSTGRESQL"),
    /**
     * DB2
     */
    DB2("db2","DB2"),
    /**
     * SQL_SERVER
     */
    SQL_SERVER("mssql","SQL_SERVER"),
    /**
     * å›½äº§è¾¾æ¢¦
     */
    DM("dm","达梦"),
    /**
     * é˜¿é‡Œå·´å·´OceanBase
     */
    OCEAN_BASE("oceanbase","阿里巴巴OceanBase"),
    /**
     * sqlite
     */
    SQLITE("sqlite","SQLITE");
    /**
     * æžšä¸¾çš„值
     */
    private String value;
    /**
     * æžšä¸¾æ˜¾ç¤ºæ–‡æœ¬
     */
    private String text;
    /**
     * èŽ·å–æžšä¸¾å€¼
     * @return æžšä¸¾å€¼
     */
    @Override
    public String getValue() {
        return value;
    }
    /**
     * è®¾ç½®æžšä¸¾å€¼
     * @param value æžšä¸¾å€¼
     */
    public void setValue(String value) {
        this.value = value;
    }
    /**
     * èŽ·å–æžšä¸¾æ˜¾ç¤ºæ–‡æœ¬
     * @return  æ˜¾ç¤ºæ–‡æœ¬
     */
    @Override
    public String getText() {
        return text;
    }
    /**
     * è®¾ç½®æ˜¾ç¤ºæ–‡æœ¬
     * @param text æ˜¾ç¤ºæ–‡æœ¬
     */
    public void setText(String text) {
        this.text = text;
    }
    /**
     * æž„造函数
     * @param value å€¼
     * @param text æ˜¾ç¤ºæ–‡æœ¬
     */
    private DataBaseEnum(String value, String text){
        this.value = value;
        this.text = text;
    }
    /**
     * æ ¹æ®åç§°èŽ·å–å¯¹åº”çš„æžšä¸¾å€¼
     * @param text åç§°
     * @return æžšä¸¾å€¼
     */
    public static String getValueByText(String text){
        for(DataBaseEnum wenum : DataBaseEnum.values()){
            if(wenum.getText().equalsIgnoreCase(text)){
                return wenum.getValue();
            }
        }
        return "";
    }
    /**
     * æ ¹æ®æžšä¸¾å€¼èŽ·å–åç§°
     * @param value æžšä¸¾å€¼
     * @return åç§°
     */
    public static String getTextByValue(String value){
        for(DataBaseEnum wenum : DataBaseEnum.values()){
            if(wenum.getValue().equalsIgnoreCase(value)){
                return wenum.getText();
            }
        }
        return "";
    }
    /**
     * æ ¹æ®æžšä¸¾å€¼èŽ·å–æžšä¸¾å¯¹è±¡
     * @param value æžšä¸¾å€¼
     * @return
     */
    public static DataBaseEnum forValue(String value){
        for(DataBaseEnum wenum : DataBaseEnum.values()){
            if(wenum.getValue().equalsIgnoreCase(value)){
                return wenum;
            }
        }
        return ORACLE;
    }
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/enumpck/DataSecretEnum.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,122 @@
package com.vci.starter.web.enumpck;
import com.vci.starter.web.annotation.VciEnum;
/**
 * å¯†çº§ç®¡ç†
 * @author weidy
 */
@VciEnum(name="Enumsecretgrade",text = "数据密级",description = "默认为非密,内部,秘密,机密;有些单位没有内部,则可以在配置文件中配置vciEnum.Enumsecretgrade.inner=false")
public enum DataSecretEnum implements BaseEnumInt{
    /**
     * éžå¯†
     */
    NONE(10,"非密"),
    /**
     * å†…部
     */
    INNER(15,"内部"),
    /**
     * ç§˜å¯†
     */
    SECRET(20,"秘密"),
    /**
     * æœºå¯†
     */
    PRIVACY(30,"机密");
    /**
     * æžšä¸¾å€¼
     */
    private int value;
    /**
     * æžšä¸¾æ˜¾ç¤ºå€¼
     */
    private String text;
    /**
     * èŽ·å–æžšä¸¾å€¼
     * @return æžšä¸¾å€¼
     */
    public int getValue() {
        return value;
    }
    /**
     * è®¾ç½®æžšä¸¾å€¼
     * @param value æžšä¸¾å€¼
     */
    public void setValue(int value) {
        this.value = value;
    }
    /**
     * èŽ·å–æ˜¾ç¤ºæ–‡æœ¬
     * @return æ˜¾ç¤ºæ–‡æœ¬
     */
    public String getText() {
        return text;
    }
    /**
     * è®¾ç½®æ˜¾ç¤ºæ–‡æœ¬
     * @param text æ˜¾ç¤ºæ–‡æœ¬
     */
    public void setText(String text) {
        this.text = text;
    }
    /**
     * æžšä¸¾å†…部构造方法
     * @param secret æžšä¸¾å€¼
     * @param secretText æ˜¾ç¤ºæ–‡æœ¬
     */
    private DataSecretEnum(int secret,String secretText){
        this.value = secret;
        this.text = secretText;
    }
    /**
     * æ ¹æ®æžšä¸¾çš„值获取显示文本
     * @param secret æžšä¸¾å€¼
     * @return æ˜¾ç¤ºæ–‡æœ¬
     */
    public static String getSecretText(int secret){
        for(DataSecretEnum eu:DataSecretEnum.values()){
            if(eu.value == secret){
                return eu.text;
            }
        }
        return NONE.text;
    }
    /**
     * æ ¹æ®æžšä¸¾æ˜¾ç¤ºæ–‡æœ¬èŽ·å–æžšä¸¾å€¼
     * @param text æ˜¾ç¤ºæ–‡æœ¬
     * @return æžšä¸¾å€¼
     */
    public static int getSecretValueByText(String text){
        for(DataSecretEnum eu:DataSecretEnum.values()){
            if(eu.text.equalsIgnoreCase(text)){
                return eu.value;
            }
        }
        return NONE.value;
    }
    /**
     * æ˜¯å¦æœ‰æ•ˆçš„密级值
     * @param secret å¯†çº§å€¼
     * @return ç¬¦åˆèŒƒå›´è¦æ±‚则返回true
     */
    public static boolean isValid(int secret){
        for(DataSecretEnum eu:DataSecretEnum.values()){
            if(eu.value == secret){
                return true;
            }
        }
        return false;
    }
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/enumpck/LangCodeEnum.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,85 @@
package com.vci.starter.web.enumpck;
import com.vci.starter.web.annotation.VciEnum;
/**
 * è¯­è¨€çš„代码大全枚举,目前只支持中文和英语
 * @author weidy
 * @date 2020/1/29
 */
@VciEnum(name= "langCode",text = "语言代码")
public enum LangCodeEnum implements BaseEnum {
    /**
     * è‹±è¯­
     */
    EN_US("en_US","英语"),
    /**
     * ç®€ä½“中文
     */
    ZH_CN("zh_CN","简体中文"),
    /**
     * ç¹ä½“中文
     */
    ZH_TW("zh_TW","繁体中文");
    /**
     * å€¼
     */
    private String value;
    /**
     * æ˜¾ç¤ºæ–‡æœ¬
     */
    private String text;
    @Override
    public String getValue() {
        return value;
    }
    @Override
    public String getText() {
        return text;
    }
    public void setValue(String value) {
        this.value = value;
    }
    public void setText(String text) {
        this.text = text;
    }
    private LangCodeEnum(String value,String text){
        this.value = value;
        this.text = text;
    }
    /**
     * æ ¹æ®åç§°èŽ·å–å¯¹åº”çš„æžšä¸¾å€¼
     * @param text åç§°
     * @return æžšä¸¾å€¼
     */
    public static String getValueByText(String text){
        for(LangCodeEnum wenum : LangCodeEnum.values()){
            if(wenum.getText().equalsIgnoreCase(text)){
                return wenum.getValue();
            }
        }
        return "";
    }
    /**
     * æ ¹æ®æžšä¸¾å€¼èŽ·å–åç§°
     * @param value æžšä¸¾å€¼
     * @return åç§°
     */
    public static String getTextByValue(String value){
        for(LangCodeEnum wenum : LangCodeEnum.values()){
            if(wenum.getValue().equalsIgnoreCase(value)){
                return wenum.getText();
            }
        }
        return "";
    }
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/enumpck/LogLevelEnum.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,39 @@
package com.vci.starter.web.enumpck;
/**
 * æŸ¥çœ‹æ—¥å¿—的等级
 * @author weidy
 * @date 2020/4/13
 */
public enum LogLevelEnum {
    /**
     * è¿½æº¯
     */
    TRACE,
    /**
     * è°ƒè¯•
     */
    DEBUG,
    /**
     * ä¿¡æ¯
     */
    INFO,
    /**
     * è­¦å‘Š
     */
    WARN,
    /**
     * é”™è¯¯
     */
    ERROR,
    /**
     * è‡´å‘½
     */
    FATAL,
    /**
     * å…³é—­
     */
    OFF;
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/enumpck/ResultCodeEnum.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,57 @@
package com.vci.starter.web.enumpck;
/**
 * è¿”回的状态码,参考http的状态码,layui等前端可以直接获取
 * @author weidy
 * @date 2019/12/3 6:52 PM
 */
public enum ResultCodeEnum {
    /**
     * æˆåŠŸ
     */
    SUCCESS(200),
    /**
     *失败
     */
    FAIL(400),
    /**
     * æœªè®¤è¯ï¼ˆç­¾åé”™è¯¯ï¼‰,或者没有用户
     */
    UNAUTHORIZED(401),
    /**
     * æ²¡æœ‰æƒé™
     */
    NOT_RIGHT(402),
    /**
     * é”™è¯¯çš„参数格式
     */
    BAD_PARAM(403),
    /**
     * æŽ¥å£ä¸å­˜åœ¨
     */
    NOT_FOUND(404),
    /**
     * æœåŠ¡å™¨å†…éƒ¨é”™è¯¯
     */
    INTERNAL_SERVER_ERROR(500);
    /**
     * çŠ¶æ€ç 
     */
    public int code;
    /**
     * æžšä¸¾å†…部构造方法
     * @param code çŠ¶æ€å€¼
     */
    private ResultCodeEnum(int code){
        this.code = code;
    }
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/enumpck/SessionStorageTypeEnum.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,93 @@
package com.vci.starter.web.enumpck;
/**
 * ä¼šè¯ä¿¡æ¯å­˜å‚¨çš„æ–¹å¼ï¼Œå®žé™…上和spring-session的管理方式是一样的,但是为了兼容以前的项目,又重复造了轮子
 * @author weidy
 * @date 2020/2/5
 */
public enum SessionStorageTypeEnum implements BaseEnum {
    /**
     * redis管理
     */
    REDIS("redis","缓存"),
    /**
     * æ•°æ®åº“
     */
    DATABASE("database","数据库");
    /**
     * å€¼
     */
    private String value;
    /**
     * æ˜¾ç¤ºæ–‡æœ¬
     */
    private String text;
    @Override
    public String getValue() {
        return value;
    }
    @Override
    public String getText() {
        return text;
    }
    public void setValue(String value) {
        this.value = value;
    }
    public void setText(String text) {
        this.text = text;
    }
    private SessionStorageTypeEnum(String value,String text){
        this.value = value;
        this.text = text;
    }
    /**
     * æ ¹æ®åç§°èŽ·å–å¯¹åº”çš„æžšä¸¾å€¼
     * @param text åç§°
     * @return æžšä¸¾å€¼
     */
    public static String getValueByText(String text){
        for(SessionStorageTypeEnum wenum : SessionStorageTypeEnum.values()){
            if(wenum.getText().equalsIgnoreCase(text)){
                return wenum.getValue();
            }
        }
        return "";
    }
    /**
     * æ ¹æ®æžšä¸¾å€¼èŽ·å–åç§°
     * @param value æžšä¸¾å€¼
     * @return åç§°
     */
    public static String getTextByValue(String value){
        for(SessionStorageTypeEnum wenum : SessionStorageTypeEnum.values()){
            if(wenum.getValue().equalsIgnoreCase(value)){
                return wenum.getText();
            }
        }
        return "";
    }
    /**
     * å€¼è½¬æ¢ä¸ºæžšä¸¾å¯¹è±¡
     * @param value å€¼
     * @return å¦‚果不符合要求返回Null
     */
    public static SessionStorageTypeEnum forValue(String value){
        for(SessionStorageTypeEnum wenum : SessionStorageTypeEnum.values()){
            if(wenum.getValue().equalsIgnoreCase(value)){
                return wenum;
            }
        }
        return SessionStorageTypeEnum.REDIS;
    }
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/enumpck/UserSecretEnum.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,119 @@
package com.vci.starter.web.enumpck;
import com.vci.starter.web.annotation.VciEnum;
/**
 * ç”¨æˆ·å¯†çº§
 * @author weidy
 * @date 2019-07-14
 */
@VciEnum(name = "usersecurityenum",text = "人员密级",description = "用户,人员的密级")
public enum UserSecretEnum implements BaseEnumInt{
    /**
     * å†…部
     */
    NONE(10,"内部"),
    /**
     * ä¸€èˆ¬
     */
    SECRET(20,"一般"),
    /**
     * é‡è¦
     */
    PRIVACY(30,"重要");
    /**
     * æžšä¸¾å€¼
     */
    private int value;
    /**
     * æžšä¸¾æ˜¾ç¤ºå€¼
     */
    private String text;
    /**
     * èŽ·å–æžšä¸¾å€¼
     * @return æžšä¸¾å€¼
     */
    public int getValue() {
        return value;
    }
    /**
     * è®¾ç½®æžšä¸¾å€¼
     * @param value æžšä¸¾å€¼
     */
    public void setValue(int value) {
        this.value = value;
    }
    /**
     * èŽ·å–æ˜¾ç¤ºæ–‡æœ¬
     * @return æ˜¾ç¤ºæ–‡æœ¬
     */
    public String getText() {
        return text;
    }
    /**
     * è®¾ç½®æ˜¾ç¤ºæ–‡æœ¬
     * @param text æ˜¾ç¤ºæ–‡æœ¬
     */
    public void setText(String text) {
        this.text = text;
    }
    /**
     * æžšä¸¾å†…部构造方法
     * @param secret æžšä¸¾å€¼
     * @param secretText æ˜¾ç¤ºæ–‡æœ¬
     */
    private UserSecretEnum(int secret, String secretText){
        this.value = secret;
        this.text = secretText;
    }
    /**
     * æ ¹æ®æžšä¸¾çš„值获取显示文本
     * @param secret æžšä¸¾å€¼
     * @return æ˜¾ç¤ºæ–‡æœ¬
     */
    public static String getSecretText(int secret){
        for(UserSecretEnum eu:UserSecretEnum.values()){
            if(eu.value == secret){
                return eu.text;
            }
        }
        return NONE.text;
    }
    /**
     * æ˜¯å¦æœ‰æ•ˆçš„密级值
     * @param secret å¯†çº§å€¼
     * @return ç¬¦åˆèŒƒå›´è¦æ±‚则返回true
     */
    public static boolean isValid(int secret){
        for(UserSecretEnum eu:UserSecretEnum.values()){
            if(eu.value == secret){
                return true;
            }
        }
        return false;
    }
    /**
     * æ ¹æ®æžšä¸¾æ˜¾ç¤ºæ–‡æœ¬èŽ·å–æžšä¸¾å€¼
     * @param text æ˜¾ç¤ºæ–‡æœ¬
     * @return æžšä¸¾å€¼
     */
    public static int getSecretValueByText(String text){
        for(UserSecretEnum eu:UserSecretEnum.values()){
            if(eu.text.equalsIgnoreCase(text)){
                return eu.value;
            }
        }
        return NONE.value;
    }
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/enumpck/VciChangeDocumentTypeEnum.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,120 @@
package com.vci.starter.web.enumpck;
/**
 * æ•°æ®ä¿®æ”¹ç±»åž‹
 * @author weidy
 * @date 2019/10/10 4:23 PM
 */
public  enum VciChangeDocumentTypeEnum {
    /**
     * æ·»åŠ 
     */
    ADD,
    /**
     * ä¿®æ”¹
     */
    EDIT,
    /**
     * åˆ é™¤
     */
    DELETE,
    /**
     * ç”Ÿå‘½å‘¨æœŸå˜åŒ–
     */
    LCSTATUS,
    /**
     * å‡ç‰ˆ
     */
    UPREVISION,
    /**
     * æäº¤æµç¨‹
     */
    SUBMIT,
    /**
     * å‘布
     */
    RELEASED,
    /**
     * å…¨éƒ¨
     */
    ALL;
    /**
     * æ ¹æ®åç§°èŽ·å–å¯¹åº”çš„æžšä¸¾å€¼
     * @param text åç§°
     * @return æžšä¸¾å€¼
     */
    public static String getValueByText(String text){
        if(text == null || text.trim().length() == 0){
            return "";
        }else{
            if("删除".equalsIgnoreCase(text)){
                return DELETE.name();
            }else if("修改".equalsIgnoreCase(text)){
                return EDIT.name();
            }else if("生命周期变更".equalsIgnoreCase(text)){
                return LCSTATUS.name();
            }else if("升版".equalsIgnoreCase(text)){
                return UPREVISION.name();
            }else if("提交流程".equalsIgnoreCase(text)){
                return SUBMIT.name();
            }else if("发布".equalsIgnoreCase(text)){
                return RELEASED.name();
            }else if("全部".equalsIgnoreCase(text)){
                return ALL.name();
            }else{
                return ADD.name();
            }
        }
    }
    /**
     * æ ¹æ®æžšä¸¾å€¼èŽ·å–åç§°
     * @param value æžšä¸¾å€¼
     * @return åç§°
     */
    public static String getTextByValue(String value){
        VciChangeDocumentTypeEnum wenum = forValue(value);
        if(wenum == null){
            return  "";
        }
        switch (wenum){
            case DELETE:
                return "删除";
            case EDIT:
                return "修改";
            case LCSTATUS:
                return "生命周期变更";
            case UPREVISION:
                return "升版";
            case SUBMIT:
                return "提交流程";
            case RELEASED:
                return "发布";
            case ALL:
                return "全部";
            default:
                return "添加";
        }
    }
    /**
     * æ ¹æ®æžšä¸¾å€¼èŽ·å–æžšä¸¾å¯¹è±¡
     * @param value æžšä¸¾å€¼
     * @return å¯¹åº”的枚举对象,不匹配的时候返回null
     */
    public static VciChangeDocumentTypeEnum forValue(String value){
        for(VciChangeDocumentTypeEnum wenum : VciChangeDocumentTypeEnum.values()){
            if(wenum.name().equalsIgnoreCase(value)){
                return wenum;
            }
        }
        return null;
    }
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/enumpck/VciFieldTypeEnum.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,134 @@
package com.vci.starter.web.enumpck;
import com.vci.starter.web.annotation.VciEnum;
/**
 * å±žæ€§çš„类型
 * @author weidy
 * @date 2019/10/10 4:23 PM
 */
@VciEnum(name = "VciFieldType",text = "属性类型")
public  enum VciFieldTypeEnum {
    /**
     * å­—符串
     */
    VTString,
    /**
     * æ•´å½¢
     */
    VTInteger,
    /**
     * é•¿æ•´å½¢
     */
    VTLong,
    /**
     * é‡‘额/双精度
     */
    VTDouble,
    /**
     * å¸ƒå°”åž‹
     */
    VTBoolean,
    /**
     * æ—¥æœŸ
     */
    VTDate,
    /**
     * æ—¥æœŸæ—¶é—´
     */
    VTDateTime,
    /**
     * æ—¶é—´
     */
    VTTime,
    /**
     * æ–‡ä»¶
     */
    VTFilePath,
    /**
     * è¶…长文本
     */
    VTClob;
    /**
     * æ ¹æ®åç§°èŽ·å–å¯¹åº”çš„æžšä¸¾å€¼
     * @param text åç§°
     * @return æžšä¸¾å€¼
     */
    public static String getValueByText(String text){
        if(text == null || text.trim().length() == 0){
            return "";
        }else{
            if("布尔型".equalsIgnoreCase(text)){
                return VTBoolean.name();
            }else if("长文本".equalsIgnoreCase(text)){
                return VTClob.name();
            }else if("日期".equalsIgnoreCase(text)){
                return VTDate.name();
            }else if("日期时间".equalsIgnoreCase(text)){
                return VTDateTime.name();
            }else if("时间".equalsIgnoreCase(text)){
                return VTTime.name();
            }else if("长整型".equalsIgnoreCase(text)){
                return VTLong.name();
            }else if("金额/双精度".equalsIgnoreCase(text)){
                return VTDouble.name();
            }else if("整形".equalsIgnoreCase(text)){
                return VTInteger.name();
            }else if("文件".equalsIgnoreCase(text)){
                return VTFilePath.name();
            }else{
                return VTString.name();
            }
        }
    }
    /**
     * æ ¹æ®æžšä¸¾å€¼èŽ·å–åç§°
     * @param value æžšä¸¾å€¼
     * @return åç§°
     */
    public static String getTextByValue(String value){
        VciFieldTypeEnum wenum = forValue(value);
        if(wenum == null){
            return  "";
        }
        switch (wenum){
            case VTBoolean:
                return "布尔型";
            case VTClob:
                return "长文本";
            case VTDate:
                return "日期";
            case VTDateTime:
                return "日期时间";
            case VTTime:
                return "时间";
            case VTLong:
                return "长整型";
            case VTDouble:
                return "金额/双精度";
            case VTInteger:
                return "整形";
            case VTFilePath:
                return "文件";
            default:
                return "字符串";
        }
    }
    /**
     * æ ¹æ®æžšä¸¾å€¼èŽ·å–æžšä¸¾å¯¹è±¡
     * @param value æžšä¸¾å€¼
     * @return å¯¹åº”的枚举对象,不匹配的时候返回null
     */
    public static VciFieldTypeEnum forValue(String value){
        for(VciFieldTypeEnum wenum : VciFieldTypeEnum.values()){
            if(wenum.name().equalsIgnoreCase(value)){
                return wenum;
            }
        }
        return null;
    }
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/enumpck/VciReturnFileTypeEnum.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,100 @@
package com.vci.starter.web.enumpck;
/**
 * controller中返回文件的类型,一般都是在下载文件出错的时候使用
 * @author weidy
 * @date 2020/2/19
 */
public enum VciReturnFileTypeEnum implements BaseEnum {
    /**
     * æ–‡æœ¬æ–‡æ¡£
     */
    TXT("txt","文本文件"),
    /**
     * PDF文件
     */
    PDF("pdf","PDF文件"),
    /**
     * å›¾ç‰‡
     */
    IMAGE("image","图片");
    /**
     * æžšä¸¾çš„值
     */
    private String value;
    /**
     * æžšä¸¾çš„æ˜¾ç¤ºæ–‡æœ¬
     */
    private String text;
    /**
     * å†…部构造函数
     * @param value æžšä¸¾çš„值
     */
    private VciReturnFileTypeEnum(String value,String text){
        this.value = value;
        this.text = text;
    }
    /**
     * æ ¹æ®åç§°èŽ·å–å¯¹åº”çš„æžšä¸¾å€¼
     * @param text åç§°
     * @return æžšä¸¾å€¼
     */
    public static String getValueByText(String text){
        for(VciReturnFileTypeEnum wenum : VciReturnFileTypeEnum.values()){
            if(wenum.getText().equalsIgnoreCase(text)){
                return wenum.getValue();
            }
        }
        return "";
    }
    /**
     * æ ¹æ®æžšä¸¾å€¼èŽ·å–åç§°
     * @param value æžšä¸¾å€¼
     * @return åç§°
     */
    public static String getTextByValue(String value){
        for(VciReturnFileTypeEnum wenum : VciReturnFileTypeEnum.values()){
            if(wenum.getValue().equalsIgnoreCase(value)){
                return wenum.getText();
            }
        }
        return "";
    }
    /**
     * æ ¹æ®æžšä¸¾å€¼èŽ·å–æžšä¸¾å¯¹è±¡
     * @param value æžšä¸¾å€¼
     * @return
     */
    public static VciReturnFileTypeEnum forValue(String value){
        for(VciReturnFileTypeEnum wenum : VciReturnFileTypeEnum.values()){
            if(wenum.getValue().equalsIgnoreCase(value)){
                return wenum;
            }
        }
        return null;
    }
    @Override
    public String getValue() {
        return value;
    }
    public void setValue(String value) {
        this.value = value;
    }
    @Override
    public String getText() {
        return text;
    }
    public void setText(String text) {
        this.text = text;
    }
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/enumpck/VciTaskBusTypeEnum.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,116 @@
package com.vci.starter.web.enumpck;
/**
 * ä»»åŠ¡è°ƒæ•´ç±»åž‹
 * @author weidy
 * @date 2019/10/10 4:23 PM
 */
public  enum VciTaskBusTypeEnum {
    /**
     * æ·»åŠ 
     */
    ADD,
    /**
     * ä¿®æ”¹
     */
    EDIT,
    /**
     * åˆ é™¤
     */
    DELETE,
    /**
     * å†»ç»“
     */
    FREEZE,
    /**
     * æ¢å¤
     */
    RECOVER,
    /**
     * å®Œæˆ
     */
    FINISH,
    /**
     * åˆ†è§£
     */
    RESOLVE,
    /**
     * å…¨éƒ¨
     */
    ALL;
    /**
     * æ ¹æ®åç§°èŽ·å–å¯¹åº”çš„æžšä¸¾å€¼
     * @param text åç§°
     * @return æžšä¸¾å€¼
     */
    public static String getValueByText(String text){
        if(text == null || text.trim().length() == 0){
            return "";
        }else{
            if("删除".equalsIgnoreCase(text)){
                return DELETE.name();
            }else if("修改".equalsIgnoreCase(text)){
                return EDIT.name();
            }else if("冻结".equalsIgnoreCase(text)){
                return FREEZE.name();
            }else if("恢复".equalsIgnoreCase(text)){
                return RECOVER.name();
            }else if("完成".equalsIgnoreCase(text)){
                return FINISH.name();
            }else if("分解".equalsIgnoreCase(text)){
                return RESOLVE.name();
            }else if("全部".equalsIgnoreCase(text)){
                return ALL.name();
            }else{
                return ADD.name();
            }
        }
    }
    /**
     * æ ¹æ®æžšä¸¾å€¼èŽ·å–åç§°
     * @param value æžšä¸¾å€¼
     * @return åç§°
     */
    public static String getTextByValue(String value){
        VciTaskBusTypeEnum wenum = forValue(value);
        if(wenum == null){
            return  "";
        }
        switch (wenum){
            case DELETE:
                return "删除";
            case EDIT:
                return "修改";
            case FREEZE:
                return "冻结";
            case RECOVER:
                return "恢复";
            case FINISH:
                return "完成";
            case RESOLVE:
                return "分解";
            case ALL:
                return "全部";
            default:
                return "添加";
        }
    }
    /**
     * æ ¹æ®æžšä¸¾å€¼èŽ·å–æžšä¸¾å¯¹è±¡
     * @param value æžšä¸¾å€¼
     * @return å¯¹åº”的枚举对象,不匹配的时候返回null
     */
    public static VciTaskBusTypeEnum forValue(String value){
        for(VciTaskBusTypeEnum wenum : VciTaskBusTypeEnum.values()){
            if(wenum.name().equalsIgnoreCase(value)){
                return wenum;
            }
        }
        return null;
    }
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/exception/ExceptionAdviceHandler.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,173 @@
package com.vci.starter.web.exception;
import com.vci.starter.web.constant.TokenKeyConstant;
import com.vci.starter.web.enumpck.ResultCodeEnum;
import com.vci.starter.web.pagemodel.BaseResult;
import com.vci.starter.web.util.LangBaseUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
import org.springframework.beans.TypeMismatchException;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartException;
import javax.servlet.ServletException;
import java.util.List;
/**
 * æä¾›ç»™spring mvc的统一的错误处理
 * @author weidy
 */
@ControllerAdvice
public class ExceptionAdviceHandler {
    /**
     * æ—¥å¿—对象
     */
    private Logger logger = LoggerFactory.getLogger(getClass());
    /**
     * å½“抓取到Throwable异常的时候,返回错误信息
     * @param e å¼‚常对象
     * @return JSON对象,不论是树,列表,还是post的方法,前端都可以获取success,code和msg属性
     */
    @ResponseBody
    @ExceptionHandler(value = Throwable.class)
    public BaseResult defaultErrorHandler(Exception e){
        BaseResult baseResult = this.handler(e);
        String traceId = MDC.get(TokenKeyConstant.TRACE_ID);
        baseResult.setTraceId(traceId);
        baseResult.setFinishTime(System.currentTimeMillis());
        if(logger.isErrorEnabled()) {
            logger.error(baseResult.toString(), e);
        }
        return baseResult;
    }
    /**
     * ä»Žå¼‚常上获取信息并返回
     * @param e å¼‚常对象
     * @return JSON对象
     */
    private BaseResult handler(Exception e) {
        //不支持的http方法
        if(e instanceof VciBaseException){
            BaseResult baseResult = BaseResult.error(LangBaseUtil.getErrorMsg(e));
            baseResult.setExceptionClassName(e.getClass().getName());
            return  baseResult;
        } else if (e instanceof HttpRequestMethodNotSupportedException) {
            return this.httpRequestMethodNotSupportedException(e);
        } else if (e instanceof HttpMessageNotReadableException) {
            return this.httpMessageNotReadableException(e);
        } else if (e instanceof TypeMismatchException || e instanceof MultipartException ||e instanceof ServletException) {
           return this.parameterException(e);
        } else if (e instanceof MethodArgumentNotValidException) {
            return this.methodArgumentNotValidException(e);
        } else if (e.getClass().getName().equalsIgnoreCase("org.springframework.jdbc.BadSqlGrammarException")) {
            return this.badSqlGrammarException(e);
        } else if(e instanceof BindException){
            return this.bindException((BindException) e);
        }else {
            //其他的
            return BaseResult.error(LangBaseUtil.getErrorMsg(e));
        }
    }
    /**
     * ä¸æ”¯æŒçš„http方法
     * @param e å¼‚常的对象
     * @return JSON对象
     */
    private BaseResult httpRequestMethodNotSupportedException(Exception e){
        String message = "请开发人员检查,不支持的http方法";
        BaseResult baseResult = BaseResult.error(message);
        baseResult.setExceptionClassName(e.getClass().getName());
        return  baseResult;
    }
    /**
     * å‚数不能被读取
     * @param e å¼‚常对象
     * @return json对象
     */
    private BaseResult httpMessageNotReadableException(Exception e){
        String message = "请开发人员检查你请求的参数和参数的类型是否符合后台接口的要求";
        BaseResult baseResult = BaseResult.makeResult(ResultCodeEnum.BAD_PARAM.code,message,null);
        baseResult.setExceptionClassName(e.getClass().getName());
        return  baseResult;
    }
    /**
     * å‚数的类型异常
     * @param e å¼‚常对象
     * @return  json对象
     */
    private BaseResult parameterException(Exception e){
        String message = "请开发人员检查你参数的类型";
        BaseResult baseResult = BaseResult.makeResult(ResultCodeEnum.BAD_PARAM.code,message,null);
        baseResult.setExceptionClassName(e.getClass().getName());
        return  baseResult;
    }
    /**
     * æ–¹æ³•的参数无效
     * @param e å¼‚常状态
     * @return json对象
     */
    private BaseResult methodArgumentNotValidException(Exception e){
        StringBuffer buffer = new StringBuffer();
        List<ObjectError> list = ((MethodArgumentNotValidException) e).getBindingResult().getAllErrors();
        list.forEach(error -> {
            if (error instanceof FieldError) {
                buffer.append(((FieldError) error).getField()).append(":");
            }
            buffer.append(error.getDefaultMessage()).append(",");
        });
        buffer.append("请开发人员检查请求方法的参数");
        BaseResult baseResult = BaseResult.makeResult(ResultCodeEnum.BAD_PARAM.code,buffer.toString(),null);
        baseResult.setExceptionClassName(e.getClass().getName());
        return  baseResult;
    }
    /**
     * ç»‘定参数错误
     * @param e å¼‚常状态
     * @return json对象
     */
    private BaseResult bindException(BindException e){
        String message = "请开发人员检查参数,参数绑定出现了错误";
        List<ObjectError> objectErrorList = e.getBindingResult().getAllErrors();
        if(!CollectionUtils.isEmpty(objectErrorList)){
            ObjectError objectError = objectErrorList.get(0);
            if(objectError instanceof FieldError){
                FieldError fieldError = (FieldError) objectError;
                message = "[" + fieldError.getField() + "]" + fieldError.getDefaultMessage();
            }
        }
        BaseResult baseResult = BaseResult.makeResult(ResultCodeEnum.BAD_PARAM.code,message,null);
        baseResult.setExceptionClassName(e.getClass().getName());
        return  baseResult;
    }
    /**
     * SQL语句错误
     * @param e å¼‚常对象
     * @return json对象
     */
    private BaseResult badSqlGrammarException(Exception e){
        String message = "请开发人员检查参数或者后台sql语句," + LangBaseUtil.getErrorMsg(e);
        BaseResult baseResult = BaseResult.error(message);
        baseResult.setExceptionClassName(e.getClass().getName());
        return  baseResult;
    }
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/exception/VciBaseException.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,160 @@
package com.vci.starter.web.exception;
import com.vci.starter.web.util.MessageUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.text.MessageFormat;
import java.util.Locale;
import java.util.ResourceBundle;
/**
 * åŸºæœ¬çš„异常,继承自RuntimeException可以被spring的事务管理自动处理
 */
public class VciBaseException extends RuntimeException {
    /**
     * æ—¥å¿—对象
     */
    private Logger log = LoggerFactory.getLogger(getClass());
    /**
     * å‚数为空
     */
    public static final String paramNull = "com.vci.base.paramNull";
    /**
     * å­—段的值重复
     */
    public static final String fieldValueRepeat="com.vci.base.fieldValueRepeat";
    /**
     * å¯¹è±¡æ²¡æœ‰åœ¨ç³»ç»Ÿä¸­å­˜åœ¨
     */
    public static final String objectNotFoundInDb="com.vci.base.objectNotFoundInDb";
    /**
     * ts的值不存在
     */
    public static final String tsNotEqual="com.vci.base.tsNotEqual";
    /**
     * å€¼ä¸ç¬¦åˆæ—¥æœŸæ ¼å¼çš„要求
     */
    public static final String dateValueFormatError="com.vci.base.dateValueForamtError";
    /**
     * æ²¡æœ‰ç™»å½•
     */
    public static final String notLogin="com.vci.base.notLogin";
    /**
     * æ²¡æœ‰æƒé™
     */
    public static final String notRight="com.vci.base.notRight";
    /**
     * æ²¡æœ‰æ•°æ®æƒé™
     */
    public static final String notDataRight="com.vci.base.notDataRight";
    /**
     * æ²¡æœ‰UI权限
     */
    public static final String notUIRight="com.vci.base.notUIRight";
    /**
     * è¿žæŽ¥corba服务失败
     */
    public static final String connectCorbaFail="com.vci.base.connectCorbaFail";
    /**
     * corba服务没有配置
     */
    public static final String corbaNotConfig="com.vci.base.corbaNotConfig ";
    /**
     * é”™è¯¯ç¼–码
     */
    private String code ;
    /**
     * é”™è¯¯å¯¹è±¡
     */
    private Object[] objs = new Object[0];
    /**
     * æž„造方法
     * @param code ç¼–码
     */
    public VciBaseException(String code){
        this.code = code;
    }
    /**
     * æž„造方法
     * @param code ç¼–码
     * @param objs é”™è¯¯å¯¹è±¡
     */
    public VciBaseException(String code, Object[] objs){
        this.code= code;
        this.objs = objs;
    }
    /**
     * æž„造方法
     * @param code é”™è¯¯ç¼–码
     * @param objs é”™è¯¯ä¿¡æ¯å¯¹è±¡
     * @param e å¼‚常对象
     */
    public VciBaseException(String code,Object[] objs,Throwable e){
        super(e);
        this.code= code;
        this.objs = objs;
    }
    public String getCode() {
        return code;
    }
    public void setCode(String code) {
        this.code = code;
    }
    public Object[] getObjs() {
        return objs;
    }
    public void setObjs(Object[] objs) {
        this.objs = objs;
    }
    /**
     * å°†å¼‚常的信息转换为本地化语言
     * @return è½¬æ¢åŽçš„æœ¬åœ°åŒ–信息
     */
    public String getErrorMsg(){
        if( this instanceof VciBaseException || this.getClass().getSuperclass().equals(VciBaseException.class)){
            if(StringUtils.isNotBlank(code)){
                code = MessageUtils.get(code,this.objs);
            }
            code = MessageFormat.format(code,this.objs);
            return code;
        }else if( this instanceof Exception){
            return getMessage();
        }else{
            return code;
        }
    }
    /**
     * èŽ·å–é”™è¯¯ä¿¡æ¯
     * @return é”™è¯¯ä¿¡æ¯
     */
    @Override
    public String getMessage(){
        return getCode() +"," + getErrorMsg();
    }
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/interceptor/VciLocaleInterceptor.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,82 @@
package com.vci.starter.web.interceptor;
import com.vci.starter.web.constant.TokenKeyConstant;
import com.vci.starter.web.enumpck.LangCodeEnum;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.lang.Nullable;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.support.RequestContextUtils;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Locale;
/**
 * æœ¬åœ°åŒ–控制拦截器
 * @author weidy
 * @date 2019/11/7 12:22 PM
 */
public class VciLocaleInterceptor implements HandlerInterceptor {
    /**
     * æ—¥å¿—对象
     */
    protected final Logger logger = LoggerFactory.getLogger(getClass());
    /**
     * æ‰§è¡Œæ‹¦æˆª
     * @param request è¯·æ±‚对象
     * @param response ç›¸åº”对象
     * @param handler å¤„理器
     * @return æ˜¯å¦æˆåŠŸ,false表示失败,其他的拦截器将不会执行
     * @throws Exception æ‰§è¡Œå‡ºé”™æ—¶ä¼šæŠ›å‡ºå¼‚常
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        //从参数或者头里获取
        String newLocale = request.getParameter(TokenKeyConstant.LANGUAGE_KEY);
        if(StringUtils.isBlank(newLocale)){
            newLocale = request.getHeader(TokenKeyConstant.LANGUAGE_KEY);
            if(logger.isDebugEnabled() && StringUtils.isNotBlank(newLocale)) {
                logger.debug("本地化参数在数据头中存放,当前是被调用的服务。{}", newLocale);
            }
//            if(StringUtils.isBlank(newLocale)){
//                newLocale = LangCodeEnum.ZH_CN.getValue();
//            }
        }
        //如果没有传递就不设置,因为多语言有默认值
        if (StringUtils.isNotBlank(newLocale)) {
            LocaleResolver localeResolver = RequestContextUtils.getLocaleResolver(request);
            if (localeResolver == null) {
                throw new IllegalStateException(
                        "No LocaleResolver found: not in a DispatcherServlet request?");
            }
            try {
                localeResolver.setLocale(request, response, parseLocaleValue(newLocale));
                if(logger.isDebugEnabled()) {
                    logger.debug("本地化为{}", newLocale);
                }
            }catch (IllegalArgumentException ex) {
                if(logger.isDebugEnabled()) {
                    logger.debug("Ignoring invalid locale value [{}]:{} " ,newLocale,ex.getMessage());
                }
            }
        }
        return true;
    }
    /**
     * æ ¹æ®è¯­è¨€çš„编码获取本地化对象
     * @param localeValue æœ¬åœ°åŒ–编码
     * @return æœ¬åœ°åŒ–对象
     */
    @Nullable
    protected Locale parseLocaleValue(String localeValue) {
        return org.springframework.util.StringUtils.parseLocale(localeValue);
    }
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/interceptor/VciLogAfterInterceptor.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,65 @@
package com.vci.starter.web.interceptor;
import com.vci.starter.web.constant.TokenKeyConstant;
import com.vci.starter.web.util.VciBaseUtil;
import com.vci.starter.web.util.WebThreadLocalUtil;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.MDC;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.lang.Nullable;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
 * æ—¥å¿—的链路拦截器,最后的拦截器
 * @author weidy
 * @date 2019/11/7 2:52 PM
 */
public class VciLogAfterInterceptor implements HandlerInterceptor {
    /**
     * æ—¥å¿—存储的接口
     */
    @Autowired(required = false)
    private VciLogStorageI logStorage;
    /**
     * æ‰§è¡Œæ‹¦æˆª
     *
     * @param request  è¯·æ±‚对象
     * @param response ç›¸åº”对象
     * @param handler  å¤„理器
     * @return æ˜¯å¦æˆåŠŸ, false表示失败,其他的拦截器将不会执行
     * @throws Exception æ‰§è¡Œå‡ºé”™æ—¶ä¼šæŠ›å‡ºå¼‚常
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        return true;
    }
    /**
     * åœ¨æ‹¦æˆªå™¨æ‰§è¡Œå®ŒæˆåŽ
     * @param request è¯·æ±‚对象
     * @param response ç›¸åº”对象
     * @param handler å¤„理器
     * @param exception å¼‚常
     * @throws Exception æ‰§è¡Œå‡ºé”™æ—¶ä¼šæŠ›å‡ºå¼‚常
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception exception) throws Exception {
        //这个拦截器结束时还有其他拦截器没有完成。所以这个不清除
        String traceId = MDC.get(TokenKeyConstant.TRACE_ID);
        //删除链路ID
        MDC.remove(TokenKeyConstant.TRACE_ID);
        //记录操作日志
        String traceIdInRequest = request.getHeader(TokenKeyConstant.LOG_TRACE_ID_KEY);
        if(StringUtils.isBlank(traceIdInRequest) && logStorage !=null ){
            //说明这个不是被服务所请求的,而是通过页面请求的,所以要记录操作日志
            logStorage.storageForMvc(traceId,request,response,handler,exception);
        }
    }
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/interceptor/VciLogBeforeInterceptor.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,75 @@
package com.vci.starter.web.interceptor;
import com.vci.starter.web.constant.TokenKeyConstant;
import com.vci.starter.web.util.VciBaseUtil;
import com.vci.starter.web.util.WebThreadLocalUtil;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.MDC;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.lang.Nullable;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
 * æ—¥å¿—的链路拦截器--所有拦截器之前
 * @author weidy
 * @date 2019/11/7 2:52 PM
 */
public class VciLogBeforeInterceptor implements HandlerInterceptor {
    /**
     * æ—¥å¿—存储的接口
     */
    @Autowired(required = false)
    private VciLogStorageI logStorage;
    /**
     * æ‰§è¡Œæ‹¦æˆª
     *
     * @param request  è¯·æ±‚对象
     * @param response ç›¸åº”对象
     * @param handler  å¤„理器
     * @return æ˜¯å¦æˆåŠŸ, false表示失败,其他的拦截器将不会执行
     * @throws Exception æ‰§è¡Œå‡ºé”™æ—¶ä¼šæŠ›å‡ºå¼‚常
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        //因为拦截器有顺序,所以设置traceId的时候需要在开始就执行
        request.setAttribute(TokenKeyConstant.REQUEST_TIMESTAMP,System.currentTimeMillis());
        //我们从头部获取看是否有日志的trackId
        //rpc的框架在其自己的拦截器(或者过滤器)中处理
        String traceId = request.getHeader(TokenKeyConstant.LOG_TRACE_ID_KEY);
        if (StringUtils.isBlank(traceId)) {
            //为空时,表示这个是浏览器请求的,所以直接生成一个新的ID
            traceId = VciBaseUtil.getPk();
        }
        MDC.put(TokenKeyConstant.TRACE_ID, traceId);
        return true;
    }
    /**
     * æ‹¦æˆªå™¨æ‰§è¡Œå®ŒæˆåŽ
     * @param request è¯·æ±‚对象
     * @param response ç›¸åº”对象
     * @param handler å¤„理器
     * @param exception å¼‚常
     * @throws Exception æ‰§è¡Œå‡ºé”™æ—¶ä¼šæŠ›å‡ºå¼‚常
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception exception) throws Exception {
       //这个拦截器结束时还有其他拦截器没有完成。所以这个不清除
        String traceId = MDC.get(TokenKeyConstant.TRACE_ID);
        //删除链路ID
        MDC.remove(TokenKeyConstant.TRACE_ID);
        //记录操作日志
        String traceIdInRequest = request.getHeader(TokenKeyConstant.LOG_TRACE_ID_KEY);
        if(StringUtils.isBlank(traceIdInRequest) && logStorage !=null ){
            //说明这个不是被服务所请求的,而是通过页面请求的,所以要记录操作日志
            logStorage.storageForMvc(traceId,request,response,handler,exception);
        }
    }
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/interceptor/VciLogStorageI.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,24 @@
package com.vci.starter.web.interceptor;
import org.springframework.lang.Nullable;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
 * æ—¥å¿—存储的接口
 * @author weidy
 * @date 2019/11/7 3:29 PM
 */
public interface VciLogStorageI {
    /**
     * æ ¹æ®mvc记录操作日志
     * @param traceId æœ¬æ¬¡æ—¥å¿—执行链路的id,方便以后追查
     * @param request è¯·æ±‚对象
     * @param response å“åº”对象
     * @param handler å¤„理对象
     * @param exception å¼‚常内容
     */
    void storageForMvc(String traceId, HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception exception);
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/interceptor/VciNoticePopLoginI.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,19 @@
package com.vci.starter.web.interceptor;
import com.vci.starter.web.pagemodel.SessionInfo;
import java.util.List;
/**
 * é€šçŸ¥ç™»å½•
 * @author weidy
 * @date 2020/2/27
 */
public interface VciNoticePopLoginI {
    /**
     * é€šçŸ¥ç”¨æˆ·è¢«è¸¢ä¸‹çº¿
     * @param sessionInfoList ç”¨æˆ·ä¼šè¯ä¿¡æ¯
     */
    void noticePopLogin(List<SessionInfo> sessionInfoList);
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/interceptor/VciSecurityInterceptor.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,198 @@
package com.vci.starter.web.interceptor;
import com.vci.starter.web.annotation.controller.VciUnCheckRight;
import com.vci.starter.web.autoconfigure.SpringMVCConfig;
import com.vci.starter.web.constant.TokenKeyConstant;
import com.vci.starter.web.enumpck.ResultCodeEnum;
import com.vci.starter.web.pagemodel.BaseResult;
import com.vci.starter.web.pagemodel.SessionInfo;
import com.vci.starter.web.util.LangBaseUtil;
import com.vci.starter.web.util.VciBaseUtil;
import com.vci.starter.web.util.WebThreadLocalUtil;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
/**
 * æƒé™æ‹¦æˆªå™¨
 * @author weidy
 * @date 2019/11/7 2:32 PM
 */
public class VciSecurityInterceptor implements HandlerInterceptor {
    /**
     * æ—¥å¿—对象
     */
    private Logger logger = LoggerFactory.getLogger(getClass());
    /**
     * å¼•入配置
     */
    @Autowired(required = false)
    private SpringMVCConfig springMVCConfig;
    /**
     * ä¼šè¯ï¼Œæƒé™ï¼Œtoken的接口
     */
    @Autowired(required = false)
    private VciSessionForLoginI sessionForLoginI;
    /**
     * æ‰§è¡Œæ‹¦æˆª
     * @param request è¯·æ±‚对象
     * @param response ç›¸åº”对象
     * @param handler å¤„理器
     * @return æ˜¯å¦æˆåŠŸ,false表示失败,其他的拦截器将不会执行
     * @throws ServletException
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        //从头中获取token,然后调用接口类,获取用户的信息,具体实现类可以是从redis里获取,也可以是通过其他的方式获取
        //如果头里面没有用户的token,那说明没有登录,
        String requestUri = request.getRequestURI();
        String contextPath = request.getContextPath();
        String url = requestUri.substring(contextPath.length());
        String userToken = request.getHeader(TokenKeyConstant.USER_TOKEN_KEY);
        if(StringUtils.isBlank(userToken)){
            userToken = request.getParameter(TokenKeyConstant.USER_TOKEN_KEY);
        }
        if(!(handler instanceof  HandlerMethod)){
            return true;
        }
        List<String> unCheckUrls = new ArrayList<>();
        if(springMVCConfig !=null && springMVCConfig.getUnCheckUrls() !=null){
            unCheckUrls = springMVCConfig.getUnCheckUrls();
        }
        SessionInfo sessionInfo = null;
        if(StringUtils.isNotBlank(userToken)){
            try{
                sessionInfo = sessionForLoginI.getSessionInfoByToken(userToken);
            }catch (Throwable e){
                logger.error("获取token出错",e);
                //sendErrorMsg(response,"获取token的信息出错," + userToken + "," + LangBaseUtil.getErrorMsg(e),1);
                //return false;
            }
            if(sessionInfo!=null){
                WebThreadLocalUtil.getCurrentUserSessionInfoInThread().set(sessionInfo);
            }
        }
        if(handler instanceof  HandlerMethod) {
            HandlerMethod hm = (HandlerMethod)handler;
            Method method = hm.getMethod();
            //设置了不校验的会直接返回true
            if (method.isAnnotationPresent(VciUnCheckRight.class)) {
                return true;
            }
            if (method.getDeclaringClass().isAnnotationPresent(VciUnCheckRight.class)) {
                return true;
            }
        }
        if(url.endsWith(".md")){
            return true;
        }
        if(StringUtils.isBlank(userToken) && !unCheckUrls.contains(url)){
            //说明是没有用户信息的,而且也必须要校验是否登录的情况
            //firefox上传文件依然使用头里存放token
            if(logger.isErrorEnabled()) {
                logger.error("请求" + url + ",但是没有登录");
            }
            sendErrorMsg(response,"没有登录系统,请先登录",1);
            return false;
            //被T下线由websocket直接提醒
        }else{
            if(sessionInfo == null){
                //也是说明不存在,被T下线时也获取不到session的信息了
                if(logger.isErrorEnabled()) {
                    logger.error("token值非法,或者用户已经被踢下线," + userToken);
                }
                sendErrorMsg(response,"token值非法,或者用户已经被踢下线," + userToken,1);
                return false;
            }else{
                if(!unCheckUrls.contains(url)){
                    if(sessionForLoginI == null){
                        //说明没办法校验
                        String msg = "请求路径"+ url +"没权限访问";
                        if(logger.isErrorEnabled()) {
                            logger.error(msg + userToken);
                        }
                        sendErrorMsg(response,msg,2);
                        return false;
                    }else{
                        String systemPrivateToken = request.getHeader(TokenKeyConstant.SYSTEM_PRIVATE_KEY);
                        try {
                            if (sessionForLoginI.checkRequestRights(request, systemPrivateToken, sessionInfo, handler)) {
                                updateRequestTime(url,userToken);
                            }else{
                                return false;
                            }
                        }catch (Throwable e){
                            String errorMsg = LangBaseUtil.getErrorMsg(e);
                            if(logger.isErrorEnabled()) {
                                logger.error("检查请求是否符合权限出现了错误," + errorMsg, e);
                            }
                            sendErrorMsg(response,errorMsg,1);
                            return false;
                        }
                    }
                }else{
                    updateRequestTime(url,userToken);
                }
            }
        }
        return true;
    }
    /**
     * è¿”回错误信息
     * @param response ç›¸åº”对象
     * @param errorMsg é”™è¯¯ä¿¡æ¯
     * @param innerErrorCode å†…部错误,1表示没有登录,2表示没有权限
     * @throws Exception
     */
    private void sendErrorMsg(HttpServletResponse response, String errorMsg, int innerErrorCode) throws Exception{
        BaseResult baseResult = BaseResult.fail(errorMsg);
        if(innerErrorCode ==1) {
            baseResult.setCode(ResultCodeEnum.UNAUTHORIZED.code);
        }else if(innerErrorCode == 2){
            baseResult.setCode(ResultCodeEnum.NOT_RIGHT.code);
        }
        response.setCharacterEncoding("UTF-8");
        response.getWriter().write(VciBaseUtil.getJSONStringWithDateFormat(baseResult));
    }
    /**
     * æ›´æ–°æœ€åŽè¯·æ±‚æ—¶é—´
     * @param url å½“前请求的路径
     * @param userToken ç”¨æˆ·çš„token
     */
    private void updateRequestTime(String url,String userToken){
        //记录最后访问的时间
        List<String> unStorageRequestTimeUrls = new ArrayList<>();
        if(springMVCConfig !=null && springMVCConfig.getUnStorageRequestTimeUrls() != null){
            unStorageRequestTimeUrls = springMVCConfig.getUnStorageRequestTimeUrls();
        }
        if(CollectionUtils.isEmpty(unStorageRequestTimeUrls)){
            unStorageRequestTimeUrls.add("smSessionController/checkIdleTime");
        }
        String url1 = url;
        while(url1.startsWith("/")){
            url1 = url1.substring(1);
        }
        if(sessionForLoginI != null && !unStorageRequestTimeUrls.contains(url1)){
            sessionForLoginI.updateRequestTime(userToken);
        }
    }
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/interceptor/VciSessionForLoginI.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,71 @@
package com.vci.starter.web.interceptor;
import com.vci.starter.web.exception.VciBaseException;
import com.vci.starter.web.pagemodel.SessionInfo;
import javax.servlet.http.HttpServletRequest;
/**
 * ä¼šè¯ä¿¡æ¯ç›¸å…³çš„æŽ¥å£
 * @author weidy
 * @date 2020/2/27
 */
public interface VciSessionForLoginI {
    /**
     * æ£€æŸ¥ç”¨æˆ·æ˜¯å¦ç™»å½•
     * @param userId ç”¨æˆ·å
     * @return ä¸ºç©ºè¡¨ç¤ºæ²¡æœ‰ç™»å½•
     */
    String checkIsLogined(String userId);
    /**
     * å¼ºåˆ¶ç”¨æˆ·ä¸‹çº¿
     * @param userId ç”¨æˆ·å
     */
    void popUser(String userId);
    /**
     * å°†ä¼šè¯ä¿¡æ¯å­˜å‚¨åˆ°Redis
     * @param sessionInfo ä¼šè¯ä¿¡æ¯
     */
    void saveSessionInfo(SessionInfo sessionInfo);
    /**
     * æ ¡éªŒè¯·æ±‚是否符合权限验证
     * åŒ…含1,系统是否可以访问当前服务或者接口
     *    2, ç”¨æˆ·æ˜¯å¦æœ‰æƒé™è®¿é—®å½“前服务
     *    3, ç”¨æˆ·æ˜¯å¦æœ‰æƒé™è®¿é—®å½“前数据
     * @param request è¯·æ±‚对象
     * @param systemPrivateToken ç³»ç»Ÿçš„许可码
     * @param sessionInfo å½“前用户会话对象
     * @param handler æ‰§è¡Œå¯¹è±¡
     * @return true表示有权限,false表示没权限
     * @throws VciBaseException æ²¡æœ‰æƒé™çš„æ—¶å€™ä¼šæŠ›å‡ºå¼‚常
     */
    boolean checkRequestRights(HttpServletRequest request, String systemPrivateToken, SessionInfo sessionInfo, Object handler) throws VciBaseException;
    /**
     * æ›´æ–°è¯·æ±‚æ—¶é—´
     * @param userToken ç”¨æˆ·token
     */
    void updateRequestTime(String userToken);
    /**
     * æ ¹æ®token获取用户的对象
     * @param userToken ç”¨æˆ·token
     * @return ç”¨æˆ·ä¼šè¯å¯¹è±¡
     */
    SessionInfo getSessionInfoByToken(String userToken);
    /**
     * é€€å‡ºç™»å½•
     * @param userToken ç”¨æˆ·çš„会话许可
     */
    void logout(String userToken);
    /**
     * æ ¹æ®token获取用户在系统中还可以存在的时间
     * @param userToken userToken ç”¨æˆ·çš„会话许可
     * @return ç”¨æˆ·åœ¨ç³»ç»Ÿä¸­è¿˜å¯ä»¥å­˜åœ¨çš„æ—¶é—´(毫秒)
     */
    long getCanAliveTime(String userToken);
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/model/BaseLinkModel.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,255 @@
package com.vci.starter.web.model;
import com.vci.starter.web.annotation.Column;
import com.vci.starter.web.annotation.Transient;
import com.vci.starter.web.annotation.VciFieldType;
import com.vci.starter.web.enumpck.VciFieldTypeEnum;
import java.util.Date;
import java.util.Map;
/**
 * é»˜è®¤çš„链接类型
 * @author weidy
 */
public class BaseLinkModel implements java.io.Serializable{
    /**
     * ä¸»é”®
     */
    @Column(nullable = false)
    private String oid;
    /**
     * åˆ›å»ºäºº
     */
    @Column(length = 50)
    private String creator;
    /**
     * åˆ›å»ºæ—¶é—´
     */
    @VciFieldType(VciFieldTypeEnum.VTDateTime)
    private Date createTime;
    /**
     * æœ€åŽä¿®æ”¹äºº
     */
    @Column(length = 50)
    private String lastModifier;
    /**
     * æœ€åŽä¿®æ”¹æ—¶é—´
     */
    @VciFieldType(VciFieldTypeEnum.VTDateTime)
    private Date lastModifyTime;
    /**
     * from端主键
     */
    @Column(name="f_oid",length = 50)
    private String foid;
    /**
     * from端版本主键
     */
    @Column(name="f_revisionoid",length = 50)
    private String frevisionoid;
    /**
     * from端对象主键
     */
    @Column(name="f_nameoid",length = 50)
    private String fnameoid;
    /**
     * from端业务类型
     */
    @Column(name="f_btmname",length = 30)
    private String fbtmname;
    /**
     * to端主键
     */
    @Column(name="t_oid",length = 50)
    private String toid;
    /**
     * to端版本主键
     */
    @Column(name="t_revisionoid",length = 50)
    private String trevisionoid;
    /**
     * to端对象主键
     */
    @Column(name="t_nameoid",length = 50)
    private String tnameoid;
    /**
     * to端业务类型
     */
    @Column(name="t_btmname",length = 30)
    private String tbtmname;
    /**
     * æ—¶é—´æˆ³
     */
    private Date ts;
    /**
     * æ‰©å±•的属性
     */
    @Transient
    private Map<String,String> data;
    public String getOid() {
        return oid;
    }
    public void setOid(String oid) {
        this.oid = oid;
    }
    public String getCreator() {
        return creator;
    }
    public void setCreator(String creator) {
        this.creator = creator;
    }
    public Date getCreateTime() {
        return createTime;
    }
    public void setCreateTime(Date createTime) {
        this.createTime = createTime;
    }
    public String getLastModifier() {
        return lastModifier;
    }
    public void setLastModifier(String lastModifier) {
        this.lastModifier = lastModifier;
    }
    public Date getLastModifytime() {
        return lastModifyTime;
    }
    public void setLastModifytime(Date lastModifytime) {
        this.lastModifyTime = lastModifytime;
    }
    public String getFoid() {
        return foid;
    }
    public void setFoid(String foid) {
        this.foid = foid;
    }
    public String getFrevisionoid() {
        return frevisionoid;
    }
    public void setFrevisionoid(String frevisionoid) {
        this.frevisionoid = frevisionoid;
    }
    public String getFnameoid() {
        return fnameoid;
    }
    public void setFnameoid(String fnameoid) {
        this.fnameoid = fnameoid;
    }
    public String getToid() {
        return toid;
    }
    public void setToid(String toid) {
        this.toid = toid;
    }
    public String getTrevisionoid() {
        return trevisionoid;
    }
    public void setTrevisionoid(String trevisionoid) {
        this.trevisionoid = trevisionoid;
    }
    public String getTnameoid() {
        return tnameoid;
    }
    public void setTnameoid(String tnameoid) {
        this.tnameoid = tnameoid;
    }
    public String getFbtmname() {
        return fbtmname;
    }
    public void setFbtmname(String fbtmname) {
        this.fbtmname = fbtmname;
    }
    public String getTbtmname() {
        return tbtmname;
    }
    public void setTbtmname(String tbtmname) {
        this.tbtmname = tbtmname;
    }
    public Date getTs() {
        return ts;
    }
    public void setTs(Date ts) {
        this.ts = ts;
    }
    public Date getLastModifyTime() {
        return lastModifyTime;
    }
    public void setLastModifyTime(Date lastModifyTime) {
        this.lastModifyTime = lastModifyTime;
    }
    public Map<String, String> getData() {
        return data;
    }
    public void setData(Map<String, String> data) {
        this.data = data;
    }
    @Override
    public String toString() {
        return "BaseLinkModel{" +
                "oid='" + oid + '\'' +
                ", creator='" + creator + '\'' +
                ", createTime=" + createTime +
                ", lastModifier='" + lastModifier + '\'' +
                ", lastModifyTime=" + lastModifyTime +
                ", foid='" + foid + '\'' +
                ", frevisionoid='" + frevisionoid + '\'' +
                ", fnameoid='" + fnameoid + '\'' +
                ", fbtmname='" + fbtmname + '\'' +
                ", toid='" + toid + '\'' +
                ", trevisionoid='" + trevisionoid + '\'' +
                ", tnameoid='" + tnameoid + '\'' +
                ", tbtmname='" + tbtmname + '\'' +
                ", ts=" + ts +
                ", data=" + data +
                '}';
    }
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/model/BaseModel.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,545 @@
package com.vci.starter.web.model;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.vci.starter.web.annotation.Column;
import com.vci.starter.web.annotation.Transient;
import com.vci.starter.web.annotation.VciFieldType;
import com.vci.starter.web.annotation.VciUseEnum;
import com.vci.starter.web.enumpck.VciFieldTypeEnum;
import com.vci.starter.web.util.VciDateUtil;
import java.util.Date;
import java.util.Map;
/**
 * å¹³å°çš„基本对象
 * @author weidy
 */
public class BaseModel implements java.io.Serializable{
    /**
     * ä¸»é”®ï¼Œå¦‚果自己的对象,不是oid作为主键的话,需要用id这个注解
     */
    @Column(nullable = false,length = 50)
    private String oid;
    /**
     * ä»£å·ï¼›å¯ä»¥è®¾ç½®å±žæ€§çš„æ˜ å°„,name表示在平台的业务类型中的属性名称,必须为小写;
     */
    @Column(length = 50)
    private String id;
    /**
     * åç§°ï¼›ä¹Ÿå¯ä»¥ä¸è®¾ç½®å±žæ€§æ˜ å°„,默认是字段名的小写
     */
    @Column(length = 50)
    private String name;
    /**
     * æè¿°
     */
    @Column(length = 250)
    private String description;
    /**
     * ç‰ˆæœ¬çš„主键
     */
    @Column(length = 50)
    private String revisionOid;
    /**
     * å¯¹è±¡çš„主键
     */
    @Column(length = 50)
    private String nameOid;
    /**
     * ä¸šåŠ¡ç±»åž‹çš„åç§°
     */
    @Column(length = 30)
    private String btmname;
    /**
     * æ˜¯å¦æœ€åŽç‰ˆæœ¬
     */
    @Column(length=1)
    private String lastR;
    /**
     * æ˜¯å¦æœ€åˆç‰ˆæœ¬
     */
    @Column(length=1)
    private String firstR;
    /**
     * æ˜¯å¦æœ€æ–°ç‰ˆæ¬¡
     */
    @Column(length=1)
    private String lastV;
    /**
     * æ˜¯å¦æœ€æ—©ç‰ˆæ¬¡
     */
    @Column(length=1)
    private String firstV;
    /**
     * åˆ›å»ºäºº
     */
    @Column(length = 50,nullable = false)
    private String creator;
    /**
     * åˆ›å»ºæ—¶é—´
     */
    @Column(nullable = false)
    @VciFieldType(VciFieldTypeEnum.VTDateTime)
    private Date createTime;
    /**
     * æœ€åŽä¿®æ”¹äºº
     */
    @Column(length = 50,nullable = false)
    private String lastModifier;
    /**
     * æœ€åŽä¿®æ”¹æ—¶é—´ï¼Œæ ¼å¼æ˜¯yyyy-MM-dd HH:mm:ss.SSS
     */
    @VciFieldType(VciFieldTypeEnum.VTDateTime)
    private Date lastModifyTime;
    /**
     * ç‰ˆæœ¬è§„则
     */
    @Column(length = 50)
    private String revisionRule;
    /**
     * ç‰ˆæœ¬åºå·
     */
    @VciFieldType(VciFieldTypeEnum.VTInteger)
    private int revisionSeq;
    /**
     * ç‰ˆæœ¬å€¼
     */
    @Column(length = 50)
    private String revisionValue;
    /**
     * ç‰ˆæ¬¡è§„则
     */
    @Column(length = 50)
    private String versionRule;
    /**
     * ç‰ˆæ¬¡æŽ’序
     */
    @VciFieldType(VciFieldTypeEnum.VTInteger)
    private int versionSeq;
    /**
     * ç‰ˆæ¬¡å€¼
     */
    @Column(length = 50)
    private String versionValue;
    /**
     * ç”Ÿå‘½å‘¨æœŸçš„编号
     */
    @Transient()
    private String lctid;
    /**
     * ç”Ÿå‘½å‘¨æœŸå€¼
     */
    @Column(length = 50)
    private String lcStatus;
    /**
     * ç”Ÿå‘½å‘¨æœŸæ˜¾ç¤ºæ–‡æœ¬
     */
    @Transient(referColumn="lcStatus_text")
    private String lcStatusText;
    /**
     * æ—¶é—´æˆ³ï¼Œæ ¼å¼æ˜¯yyyy-MM-dd HH:mm:ss.SSS
     */
    @JsonFormat(pattern = VciDateUtil.DateTimeMillFormat)
    private Date ts;
    /**
     * æ‹¥æœ‰è€…,与创建者有区别,常用于控制数据权限
     */
    @Column(length = 50)
    private String owner;
    /**
     * ç­¾å…¥äºº--签入和签出数据是互斥
     */
    @Column(length = 50)
    private String checkInBy;
    /**
     * ç­¾å…¥æ—¶é—´
     */
    @VciFieldType(VciFieldTypeEnum.VTDateTime)
    private Date checkInTime;
    /**
     * ç­¾å‡ºäºº
     */
    @Column(length = 50)
    private String checkOutBy;
    /**
     * ç­¾å‡ºæ—¶é—´
     */
    @VciFieldType(VciFieldTypeEnum.VTDateTime)
    private Date checkOutTime;
    /**
     * ä»Žå“ªä¸ªç‰ˆæœ¬æ‹·è´
     */
    @Column(length = 50)
    private String copyFromVersion;
    /**
     * å¯†çº§
     */
    @VciUseEnum(value = "Enumsecretgrade",showTextField = "secretGradeText" )
    private Integer secretGrade;
    /**
     * å¯†çº§æ˜¾ç¤ºæ–‡æœ¬
     */
    @Transient
    private String secretGradeText;
    /**
     * æ‰©å±•的属性
     */
    @Transient
    private Map<String,String> data;
    public String getOid() {
        return oid;
    }
    public void setOid(String oid) {
        this.oid = oid;
    }
    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getDescription() {
        return description;
    }
    public void setDescription(String description) {
        this.description = description;
    }
    public String getRevisionOid() {
        return revisionOid;
    }
    public void setRevisionOid(String revisionOid) {
        this.revisionOid = revisionOid;
    }
    public String getNameOid() {
        return nameOid;
    }
    public void setNameOid(String nameOid) {
        this.nameOid = nameOid;
    }
    public String getBtmname() {
        return btmname;
    }
    public void setBtmname(String btmname) {
        this.btmname = btmname;
    }
    public String getLastR() {
        return lastR;
    }
    public void setLastR(String lastR) {
        this.lastR = lastR;
    }
    public String getFirstR() {
        return firstR;
    }
    public void setFirstR(String firstR) {
        this.firstR = firstR;
    }
    public String getLastV() {
        return lastV;
    }
    public void setLastV(String lastV) {
        this.lastV = lastV;
    }
    public String getFirstV() {
        return firstV;
    }
    public void setFirstV(String firstV) {
        this.firstV = firstV;
    }
    public String getCreator() {
        return creator;
    }
    public void setCreator(String creator) {
        this.creator = creator;
    }
    public String getLastModifier() {
        return lastModifier;
    }
    public void setLastModifier(String lastModifier) {
        this.lastModifier = lastModifier;
    }
    public Date getLastModifyTime() {
        return lastModifyTime;
    }
    public void setLastModifyTime(Date lastModifyTime) {
        this.lastModifyTime = lastModifyTime;
    }
    public String getRevisionRule() {
        return revisionRule;
    }
    public void setRevisionRule(String revisionRule) {
        this.revisionRule = revisionRule;
    }
    public String getVersionRule() {
        return versionRule;
    }
    public void setVersionRule(String versionRule) {
        this.versionRule = versionRule;
    }
    public int getRevisionSeq() {
        return revisionSeq;
    }
    public void setRevisionSeq(int revisionSeq) {
        this.revisionSeq = revisionSeq;
    }
    public String getRevisionValue() {
        return revisionValue;
    }
    public void setRevisionValue(String revisionValue) {
        this.revisionValue = revisionValue;
    }
    public int getVersionSeq() {
        return versionSeq;
    }
    public void setVersionSeq(int versionSeq) {
        this.versionSeq = versionSeq;
    }
    public String getVersionValue() {
        return versionValue;
    }
    public void setVersionValue(String versionValue) {
        this.versionValue = versionValue;
    }
    public String getLcStatus() {
        return lcStatus;
    }
    public void setLcStatus(String lcStatus) {
        this.lcStatus = lcStatus;
    }
    public Date getTs() {
        return ts;
    }
    public void setTs(Date ts) {
        this.ts = ts;
    }
    public String getOwner() {
        return owner;
    }
    public void setOwner(String owner) {
        this.owner = owner;
    }
    public String getCheckInBy() {
        return checkInBy;
    }
    public void setCheckInBy(String checkInBy) {
        this.checkInBy = checkInBy;
    }
    public Date getCheckInTime() {
        return checkInTime;
    }
    public void setCheckInTime(Date checkInTime) {
        this.checkInTime = checkInTime;
    }
    public String getCheckOutBy() {
        return checkOutBy;
    }
    public void setCheckOutBy(String checkOutBy) {
        this.checkOutBy = checkOutBy;
    }
    public Date getCheckOutTime() {
        return checkOutTime;
    }
    public void setCheckOutTime(Date checkOutTime) {
        this.checkOutTime = checkOutTime;
    }
    public String getCopyFromVersion() {
        return copyFromVersion;
    }
    public void setCopyFromVersion(String copyFromVersion) {
        this.copyFromVersion = copyFromVersion;
    }
    public String getLcStatusText() {
        return lcStatusText;
    }
    public void setLcStatusText(String lcStatusText) {
        this.lcStatusText = lcStatusText;
    }
    public Date getCreateTime() {
        return createTime;
    }
    public void setCreateTime(Date createTime) {
        this.createTime = createTime;
    }
    public Integer getSecretGrade() {
        return secretGrade;
    }
    public void setSecretGrade(Integer secretGrade) {
        this.secretGrade = secretGrade;
    }
    public String getSecretGradeText() {
        return secretGradeText;
    }
    public void setSecretGradeText(String secretGradeText) {
        this.secretGradeText = secretGradeText;
    }
    public String getLctid() {
        return lctid;
    }
    public void setLctid(String lctid) {
        this.lctid = lctid;
    }
    public Map<String, String> getData() {
        return data;
    }
    public void setData(Map<String, String> data) {
        this.data = data;
    }
    @Override
    public String toString() {
        return "BaseModel{" +
                "oid='" + oid + '\'' +
                ", id='" + id + '\'' +
                ", name='" + name + '\'' +
                ", description='" + description + '\'' +
                ", revisionOid='" + revisionOid + '\'' +
                ", nameOid='" + nameOid + '\'' +
                ", btmname='" + btmname + '\'' +
                ", lastR='" + lastR + '\'' +
                ", firstR='" + firstR + '\'' +
                ", lastV='" + lastV + '\'' +
                ", firstV='" + firstV + '\'' +
                ", creator='" + creator + '\'' +
                ", createTime=" + createTime +
                ", lastModifier='" + lastModifier + '\'' +
                ", lastModifyTime=" + lastModifyTime +
                ", revisionRule='" + revisionRule + '\'' +
                ", revisionSeq=" + revisionSeq +
                ", revisionValue='" + revisionValue + '\'' +
                ", versionRule='" + versionRule + '\'' +
                ", versionSeq=" + versionSeq +
                ", versionValue='" + versionValue + '\'' +
                ", lctid='" + lctid + '\'' +
                ", lcStatus='" + lcStatus + '\'' +
                ", lcStatusText='" + lcStatusText + '\'' +
                ", ts=" + ts +
                ", owner='" + owner + '\'' +
                ", checkInBy='" + checkInBy + '\'' +
                ", checkInTime=" + checkInTime +
                ", checkOutBy='" + checkOutBy + '\'' +
                ", checkOutTime=" + checkOutTime +
                ", copyFromVersion='" + copyFromVersion + '\'' +
                ", secretGrade=" + secretGrade +
                ", secretGradeText='" + secretGradeText + '\'' +
                ", data=" + data +
                '}';
    }
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/pagemodel/BaseLinkModelVO.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,229 @@
package com.vci.starter.web.pagemodel;
import com.vci.starter.web.annotation.Transient;
import java.util.Date;
import java.util.Map;
/**
 * é“¾æŽ¥ç±»åž‹çš„æ˜¾ç¤ºå¯¹è±¡
 * @author weidy
 */
public class BaseLinkModelVO implements java.io.Serializable{
    /**
     * ä¸»é”®
     */
    private String oid;
    /**
     * åˆ›å»ºäºº
     */
    private String creator;
    /**
     * åˆ›å»ºæ—¶é—´
     */
    private Date createTime;
    /**
     * æœ€åŽä¿®æ”¹äºº
     */
    private String lastModifier;
    /**
     * æœ€åŽä¿®æ”¹æ—¶é—´
     */
    private Date lastModifyTime;
    /**
     * from端主键
     */
    private String foid;
    /**
     * from端版本主键
     */
    private String frevisionoid;
    /**
     * from端对象主键
     */
    private String fnameoid;
    /**
     * from端业务类型
     */
    private String fbtmname;
    /**
     * to端主键
     */
    private String toid;
    /**
     * to端版本主键
     */
    private String trevisionoid;
    /**
     * to端对象主键
     */
    private String tnameoid;
    /**
     * to端业务类型
     */
    private String tbtmname;
    /**
     * æ—¶é—´æˆ³
     */
    private Date ts;
    /**
     * æ‰©å±•的属性
     */
    @Transient
    private Map<String,String> data;
    public String getOid() {
        return oid;
    }
    public void setOid(String oid) {
        this.oid = oid;
    }
    public String getCreator() {
        return creator;
    }
    public void setCreator(String creator) {
        this.creator = creator;
    }
    public Date getCreateTime() {
        return createTime;
    }
    public void setCreateTime(Date createTime) {
        this.createTime = createTime;
    }
    public String getLastModifier() {
        return lastModifier;
    }
    public void setLastModifier(String lastModifier) {
        this.lastModifier = lastModifier;
    }
    public Date getLastModifyTime() {
        return lastModifyTime;
    }
    public void setLastModifyTime(Date lastModifyTime) {
        this.lastModifyTime = lastModifyTime;
    }
    public String getFoid() {
        return foid;
    }
    public void setFoid(String foid) {
        this.foid = foid;
    }
    public String getFrevisionoid() {
        return frevisionoid;
    }
    public void setFrevisionoid(String frevisionoid) {
        this.frevisionoid = frevisionoid;
    }
    public String getFnameoid() {
        return fnameoid;
    }
    public void setFnameoid(String fnameoid) {
        this.fnameoid = fnameoid;
    }
    public String getFbtmname() {
        return fbtmname;
    }
    public void setFbtmname(String fbtmname) {
        this.fbtmname = fbtmname;
    }
    public String getToid() {
        return toid;
    }
    public void setToid(String toid) {
        this.toid = toid;
    }
    public String getTrevisionoid() {
        return trevisionoid;
    }
    public void setTrevisionoid(String trevisionoid) {
        this.trevisionoid = trevisionoid;
    }
    public String getTnameoid() {
        return tnameoid;
    }
    public void setTnameoid(String tnameoid) {
        this.tnameoid = tnameoid;
    }
    public String getTbtmname() {
        return tbtmname;
    }
    public void setTbtmname(String tbtmname) {
        this.tbtmname = tbtmname;
    }
    public Date getTs() {
        return ts;
    }
    public void setTs(Date ts) {
        this.ts = ts;
    }
    public Map<String, String> getData() {
        return data;
    }
    public void setData(Map<String, String> data) {
        this.data = data;
    }
    @Override
    public String toString() {
        return "BaseLinkModelVO{" +
                "oid='" + oid + '\'' +
                ", creator='" + creator + '\'' +
                ", createTime=" + createTime +
                ", lastModifier='" + lastModifier + '\'' +
                ", lastModifyTime=" + lastModifyTime +
                ", foid='" + foid + '\'' +
                ", frevisionoid='" + frevisionoid + '\'' +
                ", fnameoid='" + fnameoid + '\'' +
                ", fbtmname='" + fbtmname + '\'' +
                ", toid='" + toid + '\'' +
                ", trevisionoid='" + trevisionoid + '\'' +
                ", tnameoid='" + tnameoid + '\'' +
                ", tbtmname='" + tbtmname + '\'' +
                ", ts=" + ts +
                ", data=" + data +
                '}';
    }
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/pagemodel/BaseModelVO.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,502 @@
package com.vci.starter.web.pagemodel;
import com.vci.starter.web.annotation.Transient;
import java.util.Date;
import java.util.Map;
/**
 * å¹³å°çš„基本显示对象
 * @author weidy
 */
public class BaseModelVO implements java.io.Serializable{
    /**
     * ä¸»é”®
     */
    private String oid;
    /**
     * ä»£å·
     */
    private String id;
    /**
     * åç§°
     */
    private String name;
    /**
     * æè¿°
     */
    private String description;
    /**
     * ç‰ˆæœ¬çš„主键
     */
    private String revisionOid;
    /**
     * åç§°çš„主键
     */
    private String nameOid;
    /**
     * ä¸šåŠ¡ç±»åž‹çš„åç§°
     */
    private String btmname;
    /**
     * æ˜¯å¦æœ€åŽç‰ˆæ¬¡
     */
    private String lastR;
    /**
     * æ˜¯å¦æœ€åˆç‰ˆæ¬¡
     */
    private String firstR;
    /**
     * æ˜¯å¦æœ€æ–°ç‰ˆæœ¬
     */
    private String lastV;
    /**
     * æ˜¯å¦æœ€æ—©ç‰ˆæœ¬
     */
    private String firstV;
    /**
     * åˆ›å»ºäºº
     */
    private String creator;
    /**
     * åˆ›å»ºæ—¶é—´
     */
    private Date createTime;
    /**
     * æœ€åŽä¿®æ”¹äºº
     */
    private String lastModifier;
    /**
     * æœ€åŽä¿®æ”¹æ—¶é—´ï¼Œæ ¼å¼æ˜¯yyyy-MM-dd HH:mm:ss.SSS
     */
    private Date lastModifyTime;
    /**
     * ç‰ˆæœ¬è§„则
     */
    private String revisionRule;
    /**
     * ç‰ˆæœ¬åºå·
     */
    private int revisionSeq;
    /**
     * ç‰ˆæœ¬å€¼
     */
    private String revisionValue;
    /**
     * ç‰ˆæ¬¡è§„则
     */
    private String versionRule;
    /**
     * ç‰ˆæ¬¡æŽ’序
     */
    private int versionSeq;
    /**
     * ç‰ˆæ¬¡å€¼
     */
    private String versionValue;
    /**
     * ç”Ÿå‘½å‘¨æœŸå€¼
     */
    private String lcStatus;
    /**
     * ç”Ÿå‘½å‘¨æœŸæ˜¾ç¤ºæ–‡æœ¬
     */
    private String lcStatusText;
    /**
     * æ—¶é—´æˆ³ï¼Œæ ¼å¼æ˜¯yyyy-MM-dd HH:mm:ss.SSS
     */
    private Date ts;
    /**
     * æ‹¥æœ‰è€…,与创建者有区别,常用于控制数据权限
     */
    private String owner;
    /**
     * ç­¾å…¥äºº--签入和签出数据是互斥
     */
    private String checkInBy;
    /**
     * ç­¾å…¥æ—¶é—´
     */
    private Date checkInTime;
    /**
     * ç­¾å‡ºäºº
     */
    private String checkOutBy;
    /**
     * ç­¾å‡ºæ—¶é—´
     */
    private Date checkOutTime;
    /**
     * ä»Žå“ªä¸ªç‰ˆæœ¬æ‹·è´
     */
    private String copyFromVersion;
    /**
     * å¯†çº§
     */
    private Integer secretGrade;
    /**
     * å¯†çº§æ˜¾ç¤ºæ–‡æœ¬
     */
    private String secretGradeText;
    /**
     * ç”Ÿå‘½å‘¨æœŸçš„名称
     */
    private String lctid;
    /**
     * æ‰©å±•的属性
     */
    @Transient
    private Map<String,String> data;
    public String getOid() {
        return oid;
    }
    public void setOid(String oid) {
        this.oid = oid;
    }
    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getDescription() {
        return description;
    }
    public void setDescription(String description) {
        this.description = description;
    }
    public String getRevisionOid() {
        return revisionOid;
    }
    public void setRevisionOid(String revisionOid) {
        this.revisionOid = revisionOid;
    }
    public String getNameOid() {
        return nameOid;
    }
    public void setNameOid(String nameOid) {
        this.nameOid = nameOid;
    }
    public String getBtmname() {
        return btmname;
    }
    public void setBtmname(String btmname) {
        this.btmname = btmname;
    }
    public String getLastR() {
        return lastR;
    }
    public void setLastR(String lastR) {
        this.lastR = lastR;
    }
    public String getFirstR() {
        return firstR;
    }
    public void setFirstR(String firstR) {
        this.firstR = firstR;
    }
    public String getLastV() {
        return lastV;
    }
    public void setLastV(String lastV) {
        this.lastV = lastV;
    }
    public String getFirstV() {
        return firstV;
    }
    public void setFirstV(String firstV) {
        this.firstV = firstV;
    }
    public String getCreator() {
        return creator;
    }
    public void setCreator(String creator) {
        this.creator = creator;
    }
    public String getLastModifier() {
        return lastModifier;
    }
    public void setLastModifier(String lastModifier) {
        this.lastModifier = lastModifier;
    }
    public Date getLastModifyTime() {
        return lastModifyTime;
    }
    public void setLastModifyTime(Date lastModifyTime) {
        this.lastModifyTime = lastModifyTime;
    }
    public String getRevisionRule() {
        return revisionRule;
    }
    public void setRevisionRule(String revisionRule) {
        this.revisionRule = revisionRule;
    }
    public String getVersionRule() {
        return versionRule;
    }
    public void setVersionRule(String versionRule) {
        this.versionRule = versionRule;
    }
    public int getRevisionSeq() {
        return revisionSeq;
    }
    public void setRevisionSeq(int revisionSeq) {
        this.revisionSeq = revisionSeq;
    }
    public String getRevisionValue() {
        return revisionValue;
    }
    public void setRevisionValue(String revisionValue) {
        this.revisionValue = revisionValue;
    }
    public int getVersionSeq() {
        return versionSeq;
    }
    public void setVersionSeq(int versionSeq) {
        this.versionSeq = versionSeq;
    }
    public String getVersionValue() {
        return versionValue;
    }
    public void setVersionValue(String versionValue) {
        this.versionValue = versionValue;
    }
    public String getLcStatus() {
        return lcStatus;
    }
    public void setLcStatus(String lcStatus) {
        this.lcStatus = lcStatus;
    }
    public Date getTs() {
        return ts;
    }
    public void setTs(Date ts) {
        this.ts = ts;
    }
    public String getOwner() {
        return owner;
    }
    public void setOwner(String owner) {
        this.owner = owner;
    }
    public String getCheckInBy() {
        return checkInBy;
    }
    public void setCheckInBy(String checkInBy) {
        this.checkInBy = checkInBy;
    }
    public Date getCheckInTime() {
        return checkInTime;
    }
    public void setCheckInTime(Date checkInTime) {
        this.checkInTime = checkInTime;
    }
    public String getCheckOutBy() {
        return checkOutBy;
    }
    public void setCheckOutBy(String checkOutBy) {
        this.checkOutBy = checkOutBy;
    }
    public Date getCheckOutTime() {
        return checkOutTime;
    }
    public void setCheckOutTime(Date checkOutTime) {
        this.checkOutTime = checkOutTime;
    }
    public String getCopyFromVersion() {
        return copyFromVersion;
    }
    public void setCopyFromVersion(String copyFromVersion) {
        this.copyFromVersion = copyFromVersion;
    }
    public String getLcStatusText() {
        return lcStatusText;
    }
    public void setLcStatusText(String lcStatusText) {
        this.lcStatusText = lcStatusText;
    }
    public Date getCreateTime() {
        return createTime;
    }
    public void setCreateTime(Date createTime) {
        this.createTime = createTime;
    }
    public Integer getSecretGrade() {
        return secretGrade;
    }
    public void setSecretGrade(Integer secretGrade) {
        this.secretGrade = secretGrade;
    }
    public String getSecretGradeText() {
        return secretGradeText;
    }
    public void setSecretGradeText(String secretGradeText) {
        this.secretGradeText = secretGradeText;
    }
    public String getLctid() {
        return lctid;
    }
    public void setLctid(String lctid) {
        this.lctid = lctid;
    }
    public Map<String, String> getData() {
        return data;
    }
    public void setData(Map<String, String> data) {
        this.data = data;
    }
    @Override
    public String toString() {
        return "BaseModelVO{" +
                "oid='" + oid + '\'' +
                ", id='" + id + '\'' +
                ", name='" + name + '\'' +
                ", description='" + description + '\'' +
                ", revisionOid='" + revisionOid + '\'' +
                ", nameOid='" + nameOid + '\'' +
                ", btmname='" + btmname + '\'' +
                ", lastR='" + lastR + '\'' +
                ", firstR='" + firstR + '\'' +
                ", lastV='" + lastV + '\'' +
                ", firstV='" + firstV + '\'' +
                ", creator='" + creator + '\'' +
                ", createTime=" + createTime +
                ", lastModifier='" + lastModifier + '\'' +
                ", lastModifyTime=" + lastModifyTime +
                ", revisionRule='" + revisionRule + '\'' +
                ", revisionSeq=" + revisionSeq +
                ", revisionValue='" + revisionValue + '\'' +
                ", versionRule='" + versionRule + '\'' +
                ", versionSeq=" + versionSeq +
                ", versionValue='" + versionValue + '\'' +
                ", lcStatus='" + lcStatus + '\'' +
                ", lcStatusText='" + lcStatusText + '\'' +
                ", ts=" + ts +
                ", owner='" + owner + '\'' +
                ", checkInBy='" + checkInBy + '\'' +
                ", checkInTime=" + checkInTime +
                ", checkOutBy='" + checkOutBy + '\'' +
                ", checkOutTime=" + checkOutTime +
                ", copyFromVersion='" + copyFromVersion + '\'' +
                ", secretGrade=" + secretGrade +
                ", secretGradeText='" + secretGradeText + '\'' +
                ", lctid='" + lctid + '\'' +
                ", data=" + data +
                '}';
    }
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/pagemodel/BaseQueryObject.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,239 @@
package com.vci.starter.web.pagemodel;
import com.alibaba.fastjson.annotation.JSONField;
import org.apache.commons.lang3.StringUtils;
import java.util.*;
/**
 * æŸ¥è¯¢æ¡ä»¶ ï¼Œç»å¸¸ç”¨äºŽcontroller的方法中,用于接收前端的请求参数
 * äº’联网产品上不推荐这样的方式,不方便维护
 * ä½†æ˜¯åœ¨ä¼ ç»Ÿè¡Œä¸šå› ä¸ºè€ƒè™‘到查询条件过多,查询的方式复杂多样化,因此建议使用这种方式
 * å‰ç«¯éœ€è¦ä¼ é€’的参数方式应该为‘conditionMap['xxxx']=yyy; xxx是属性的名称,yyy是查询条件的值
 * è¿™ä¸ªå¯¹è±¡é‡Œå·²ç»åŒ…含了分页信息
 */
public class BaseQueryObject implements java.io.Serializable{
    /**
     * é»˜è®¤æž„造函数
     */
    public BaseQueryObject(){
    }
    /**
     * æž„造函数,添加查询条件
     * @param conditionMap æŸ¥è¯¢æ¡ä»¶
     */
    public BaseQueryObject(Map<String,String> conditionMap){
        this.setConditionMap(conditionMap);
    }
    /**
     * æž„造函数,设置分页数
     * @param limit æ¯é¡µæ˜¾ç¤ºæœ€å¤§æ•°
     */
    public BaseQueryObject(int limit){
        this.setLimit(limit);
    }
    /**
     * æž„造函数,添加查询条件和分页数
     * @param conditionMap æŸ¥è¯¢æ¡ä»¶
     * @param limit æ¯é¡µæ˜¾ç¤ºæœ€å¤§æ•°
     */
    public BaseQueryObject(Map<String,String> conditionMap,int limit){
        this.setConditionMap(conditionMap);
        this.setLimit(limit);
    }
    /**
     * ç¦æ­¢ä¿®æ”¹è¿™ä¸ªå€¼
     */
    @JSONField(serialize = false,deserialize = false)
    private static final long serialVersionUID = 5608634730007623041L;
    /**
     * æŸ¥è¯¢æ¡ä»¶çš„æ˜ å°„关系
     */
    @JSONField()
    private Map<String,String> conditionMap = new HashMap<String, String>();
    /**
     * å½“前页
     */
    @JSONField()
    private int page = 1;
    // å½“前页
    /**
     * æŽ’序字段
     */
    @JSONField()
    private String sort;
    // æŽ’序字段  ---前端只支持使用一个字段来排序,但是后台实际可以使用多个字段来排序,所以可以使用逗号分割
    /**
     * æŽ’序类型
     */
    @JSONField()
    private String order;
    // asc/desc,如果有多个排序字段时,这里也需要用逗号分割,且与sort的位置对应
    /**
     * æ¯é¡µæ˜¾ç¤ºé¡µæ•°
     */
    @JSONField()
    private int limit = 25;//每页显示的条数
    /**
     * èŽ·å–æŸ¥è¯¢æ¡ä»¶
     * @return æŸ¥è¯¢æ¡ä»¶æ˜ å°„,key是字段英文名称,value是查询的值
     */
    public Map<String, String> getConditionMap() {
        return conditionMap;
    }
    /**
     * æ ¹æ®æ˜µç§°èŽ·å–æŸ¥è¯¢æ¡ä»¶
     * @param nick è¡¨æ ¼çš„æ˜µç§°
     * @return å¸¦æœ‰.的不添加表格昵称
     */
    public Map<String,String> getConditionMapByNick(String nick){
        if(conditionMap!=null){
            Map<String,String> conditionMapHasNick = new HashMap<>();
            conditionMap.forEach( (k,v) -> {
                if(!k.contains(".")){
                    conditionMapHasNick.put(nick + "." + k,v);
                }else{
                    conditionMapHasNick.put(k,v);
                }
            });
            return conditionMapHasNick;
        }
        return null;
    }
    /**
     * è®¾ç½®æŸ¥è¯¢æ¡ä»¶
     * @param conditionMap æŸ¥è¯¢æ¡ä»¶çš„æ˜ å°„关系
     */
    public void setConditionMap(Map<String, String> conditionMap) {
        this.conditionMap = conditionMap;
    }
    public int getPage() {
        return page;
    }
    public void setPage(int page) {
        this.page = page;
    }
    public String getSort() {
        return sort;
    }
    public void setSort(String sort) {
        this.sort = sort;
    }
    public String getOrder() {
        return order;
    }
    public void setOrder(String order) {
        this.order = order;
    }
    public int getLimit() {
        return limit;
    }
    public void setLimit(int limit) {
        this.limit = limit;
    }
    /**
     * èŽ·å–æŸ¥è¯¢å¯¹è±¡ä¸­çš„åˆ†é¡µå¯¹è±¡
     * @return åˆ†é¡µå¯¹è±¡
     */
    @JSONField(serialize = false,deserialize = false)
    public PageHelper getPageHelper(){
        PageHelper pageHelper = new PageHelper(limit);
        pageHelper.setPage(getPage());
        pageHelper.setSort(getSort());
        pageHelper.setOrder(getOrder());
        return pageHelper;
    }
    /**
     * å¢žåŠ æŽ’åº
     * @param sort æŽ’序字段
     * @param order æŽ’序方式
     * @return  å½“前对象
     */
    public BaseQueryObject addSort(String sort, String order){
        this.setSort(StringUtils.isBlank(this.getSort())?sort:(this.getSort() + "," + sort) );
        this.setOrder(StringUtils.isBlank(this.getOrder())?order:(this.getOrder() + "," + order));
        return this;
    }
    /**
     * å¢žåŠ æŸ¥è¯¢æŸ¥è¯¢æ¡ä»¶
     * @param key æŸ¥è¯¢æ¡ä»¶
     * @param value å€¼
     * @return  å½“前对象
     */
    public BaseQueryObject addCondition(String key,String value){
        if(this.getConditionMap() == null){
            this.conditionMap = new HashMap<>();
        }
        this.conditionMap.put(key,value);
        return this;
    }
    /**
     * è®¾ç½®åˆ†é¡µçš„信息
     * @param pageHelper åˆ†é¡µå¯¹è±¡
     * @return å½“前对象
     */
    public BaseQueryObject page(PageHelper pageHelper){
        this.setSort(pageHelper.getSort());
        this.setOrder(pageHelper.getOrder());
        this.setPage(pageHelper.getPage());
        this.setLimit(pageHelper.getLimit());
        return  this;
    }
    /**
     * èŽ·å–feign请求的参数映射,一般在get方法的时候才使用
     * @return æŸ¥è¯¢æ¡ä»¶ï¼Œåˆ†é¡µå’ŒæŽ’序等信息,key是参数的对象,value是参数的值
     */
    @JSONField(serialize = false,deserialize = false)
    public Map<String,String> getFeignRequestMap(){
        Map<String,String> feignRequestMap = new HashMap<>();
        //查询条件
        if(this.conditionMap!=null){
            this.getConditionMap().forEach( (k,v) -> {
                feignRequestMap.put( "conditionMap[\"" + k + "\"]",v);
            });
        }
        //分页
        feignRequestMap.put("page",this.getPage() + "");
        feignRequestMap.put("limit",this.getLimit() + "");
        //排序
        feignRequestMap.put("sort",this.getSort());
        feignRequestMap.put("order",this.getOrder());
        return feignRequestMap;
    }
    @Override
    public String toString() {
        return "BaseQueryObject{" +
                "conditionMap=" + conditionMap +
                ", page=" + page +
                ", sort='" + sort + '\'' +
                ", order='" + order + '\'' +
                ", limit=" + limit +
                '}';
    }
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/pagemodel/BaseResult.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,393 @@
package com.vci.starter.web.pagemodel;
import com.vci.starter.web.enumpck.ResultCodeEnum;
import org.apache.commons.lang3.StringUtils;
import java.util.Arrays;
import java.util.Collection;
/**
 * ç»Ÿä¸€çš„æ•°æ®è¿”回对象,保证feign、restTemplate或者其他rest请求客户端可以统一处理
 * @author weidy
 * @date 2019/12/3 6:57 PM
 */
public class BaseResult<T> implements java.io.Serializable{
    /**
     * ç¦æ­¢ä¿®æ”¹è¿™ä¸ªå€¼
     */
    private static final long serialVersionUID = 4746146117790499683L;
    /**
     * æ˜¯å¦æˆåŠŸ
     */
    private boolean success = false;
    /**
     * æç¤ºä¿¡æ¯
     */
    private String msg = "";
    /**
     * æç¤ºæ¶ˆæ¯å¤šè¯­
     */
    private Object[] msgObjs;
    /**
     * åŒ…含数据对象
     */
    private T obj = null;
    /**
     * ä¸šåŠ¡ç¼–ç 
     */
    private int code = ResultCodeEnum.FAIL.code;
    /**
     * é“¾è·¯çš„ID,用于追查错误信息
     */
    private String traceId;
    /**
     * è¯·æ±‚链路的ID,不是日志的链路,可以用于控制幂等性
     */
    private String requestTraceId;
    /**
     * å¼‚常的类名称
     */
    private String exceptionClassName;
    /**
     * å¼‚常的编号
     */
    private String exceptionCode;
    /**
     * å¼‚常的错误对象
     */
    private Object[] exceptionObjs;
    /**
     * å®Œæˆæ—¶é—´
     */
    private long finishTime;
    /**
     * åˆ—表总数,extjs和easyui使用total,layui使用count,这里统一为total,layui可以在table.js里修改源码,
     */
    private long total = 0;
    /**
     * æ•°æ®ï¼Œeasyui使用的rows, extjs和layui默认为data;easyui也可以修改为data,因此均使用data
     */
    private Collection<T> data ;
    /**
     * æ ‘的数据
     */
    private Collection<Tree> treeData;
    public Object[] getMsgObjs() {
        return msgObjs;
    }
    public void setMsgObjs(Object[] msgObjs) {
        this.msgObjs = msgObjs;
    }
    public boolean isSuccess() {
        return success;
    }
    public void setSuccess(boolean success) {
        this.success = success;
    }
    public String getMsg() {
        return msg;
    }
    public void setMsg(String msg) {
        this.msg = msg;
    }
    public T getObj() {
        return obj;
    }
    public void setObj(T obj) {
        this.obj = obj;
    }
    public int getCode() {
        return code;
    }
    public void setCode(int code) {
        this.code = code;
    }
    public String getTraceId() {
        return traceId;
    }
    public void setTraceId(String traceId) {
        this.traceId = traceId;
    }
    public String getRequestTraceId() {
        return requestTraceId;
    }
    public void setRequestTraceId(String requestTraceId) {
        this.requestTraceId = requestTraceId;
    }
    public String getExceptionClassName() {
        return exceptionClassName;
    }
    public void setExceptionClassName(String exceptionClassName) {
        this.exceptionClassName = exceptionClassName;
    }
    public String getExceptionCode() {
        return exceptionCode;
    }
    public void setExceptionCode(String exceptionCode) {
        this.exceptionCode = exceptionCode;
    }
    public Object[] getExceptionObjs() {
        return exceptionObjs;
    }
    public void setExceptionObjs(Object[] exceptionObjs) {
        this.exceptionObjs = exceptionObjs;
    }
    public long getFinishTime() {
        return finishTime;
    }
    public void setFinishTime(long finishTime) {
        this.finishTime = finishTime;
    }
    public long getTotal() {
        return total;
    }
    public void setTotal(long total) {
        this.total = total;
    }
    public Collection<T> getData() {
        return data;
    }
    public void setData(Collection<T> data) {
        this.data = data;
    }
    public Collection<Tree> getTreeData() {
        return treeData;
    }
    public void setTreeData(Collection<Tree> treeData) {
        this.treeData = treeData;
    }
    /**
     * æˆåŠŸï¼Œæ²¡æœ‰ä»»ä½•è¿”å›žä¿¡æ¯
     * @return è¿”回统一数据对象
     */
    public static BaseResult success(){
        return success(null);
    }
    /**
     * æˆåŠŸï¼Œæœ‰è¿”å›žæ•°æ®
     * @param obj è¿”回的数据
     * @param <T> æ•°æ®ç±»åž‹
     * @return è¿”回统一数据对象
     */
    public static <T> BaseResult<T> success(T obj){
        BaseResult<T> baseResult = new BaseResult<>();
        baseResult.setSuccess(true);
        baseResult.setCode(ResultCodeEnum.SUCCESS.code);
        baseResult.setObj(obj);
        return baseResult;
    }
    /**
     * æˆåŠŸï¼Œæœ‰è¿”å›žæ•°æ®
     * @param obj è¿”回的数据
     * @param <T> æ•°æ®ç±»åž‹
     * @param msg æç¤ºä¿¡æ¯
     * @return è¿”回统一数据对象
     */
    public static <T> BaseResult<T> success(T obj,String msg){
        BaseResult<T> baseResult = new BaseResult<>();
        baseResult.setSuccess(true);
        baseResult.setCode(ResultCodeEnum.SUCCESS.code);
        baseResult.setObj(obj);
        baseResult.setMsg(msg);
        return baseResult;
    }
    /**
     * æˆåŠŸï¼Œæœ‰è¿”å›žæ•°æ®
     * @param obj è¿”回的数据
     * @param <T> æ•°æ®ç±»åž‹
     * @param msg æç¤ºä¿¡æ¯
     * @param msgObjs ç”¨äºŽæ ¼å¼åŒ–消息用的对象
     * @return è¿”回统一数据对象
     */
    public static <T> BaseResult<T> success(T obj,String msg,Object...msgObjs){
        BaseResult<T> baseResult = new BaseResult<>();
        baseResult.setSuccess(true);
        baseResult.setCode(ResultCodeEnum.SUCCESS.code);
        baseResult.setObj(obj);
        baseResult.setMsg(msg);
        return baseResult;
    }
    /**
     * æˆåŠŸï¼Œè€Œä¸”æœ‰æç¤ºä¿¡æ¯
     * @param msg æç¤ºä¿¡æ¯
     * @return è¿”回统一数据对象
     */
    public static BaseResult successMsg(String msg){
        BaseResult baseResult = new BaseResult();
        baseResult.setSuccess(true);
        baseResult.setCode(ResultCodeEnum.SUCCESS.code);
        baseResult.setMsg(msg);
        return baseResult;
    }
    /**
     * æˆåŠŸï¼Œè€Œä¸”æœ‰æç¤ºä¿¡æ¯
     * @param msg æç¤ºä¿¡æ¯
     * @param msgObjs ç”¨äºŽæ ¼å¼åŒ–消息用的对象
     * @return è¿”回统一数据对象
     */
    public static BaseResult successMsg(String msg,Object...msgObjs){
        BaseResult baseResult = new BaseResult();
        baseResult.setSuccess(true);
        baseResult.setCode(ResultCodeEnum.SUCCESS.code);
        baseResult.setMsg(msg);
        baseResult.setMsgObjs(msgObjs);
        return baseResult;
    }
    /**
     * å¤±è´¥ï¼ŒåŒ…含错误信息
     * @param msg æ¶ˆæ¯å†…容
     * @return è¿”回统一数据对象
     */
    public static BaseResult fail(String msg){
        return makeResult(ResultCodeEnum.FAIL.code,msg,null);
    }
    /**
     * å¤±è´¥ï¼ŒåŒ…含错误信息,且包含用于格式化消息用的对象
     * @param msg æ¶ˆæ¯å†…容
     * @param msgObjs  ç”¨äºŽæ ¼å¼åŒ–消息用的对象
     * @return è¿”回统一数据对象
     */
    public static BaseResult fail(String msg,Object...msgObjs){
        BaseResult baseResult = makeResult(ResultCodeEnum.FAIL.code,msg,null);
        baseResult.setMsgObjs(msgObjs);
        return baseResult;
    }
    /**
     * é”™è¯¯ï¼ŒåŒ…含错误信息
     * @param msg é”™è¯¯æ¶ˆæ¯
     * @return è¿”回统一数据对象
     */
    public static BaseResult error(String msg){
        return makeResult(ResultCodeEnum.INTERNAL_SERVER_ERROR.code,msg,null);
    }
    /**
     * åˆ›å»ºè¿”回对象
     * @param code çŠ¶æ€ç 
     * @param msg é”™è¯¯æ¶ˆæ¯
     * @param obj æ•°æ®å¯¹è±¡
     * @param <T> æ•°æ®å¯¹è±¡çš„æ‰€å±žç±»åž‹
     * @return ç»Ÿä¸€æ•°æ®å¯¹è±¡
     */
    public static <T> BaseResult<T> makeResult(int code,String msg,T obj){
        BaseResult<T> baseResult = new BaseResult<>();
        baseResult.setSuccess(false);
        baseResult.setCode(code);
        baseResult.setMsg(msg);
        baseResult.setObj(obj);
        return baseResult;
    }
    /**
     * æ ¹æ®åˆ—表获取统一数据对象
     * @param dataGrid åˆ—表数据
     * @param <T> åˆ—表的元素类型
     * @return ç»Ÿä¸€æ•°æ®å¯¹è±¡
     */
    public static <T> BaseResult<T> dataGrid(DataGrid<T> dataGrid){
        BaseResult<T> baseResult = new BaseResult<>();
        if(dataGrid ==null){
            baseResult.setCode(ResultCodeEnum.SUCCESS.code);
            baseResult.setSuccess(true);
        }else{
            if(StringUtils.isNotBlank(dataGrid.getMsg())){
                baseResult.setCode(ResultCodeEnum.FAIL.code);
                baseResult.setSuccess(false);
                baseResult.setMsg(dataGrid.getMsg());
            }else{
                baseResult.setCode(ResultCodeEnum.SUCCESS.code);
                baseResult.setSuccess(true);
                baseResult.setData(dataGrid.getData());
                baseResult.setTotal(dataGrid.getTotal());
            }
        }
        return baseResult;
    }
    /**
     * æ ¹æ®åˆ—表获取统一数据对象
     * @param treeList æ ‘节点集合
     * @return ç»Ÿä¸€æ•°æ®å¯¹è±¡
     */
    public static BaseResult tree(Collection<Tree> treeList){
        BaseResult baseResult = new BaseResult<>();
        baseResult.setCode(ResultCodeEnum.SUCCESS.code);
        baseResult.setSuccess(true);
        baseResult.setTreeData(treeList);
        return baseResult;
    }
    @Override
    public String toString() {
        return "BaseResult{" +
                "success=" + success +
                ", msg='" + msg + '\'' +
                ", obj=" + obj +
                ", code='" + code + '\'' +
                ", traceId='" + traceId + '\'' +
                ", requestTraceId='" + requestTraceId + '\'' +
                ", exceptionClassName='" + exceptionClassName + '\'' +
                ", exceptionCode='" + exceptionCode + '\'' +
                ", exceptionObjs=" + Arrays.toString(exceptionObjs) +
                ", finishTime=" + finishTime +
                ", total=" + total +
                ", data=" + data +
                ", treeData=" + treeData +
                '}';
    }
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/pagemodel/DataGrid.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,177 @@
package com.vci.starter.web.pagemodel;
import java.util.ArrayList;
import java.util.List;
/**
 * åˆ—表返回数据模型
 *
 * @author weidy
 *
 */
public class DataGrid<T> implements java.io.Serializable {
    /**
     * ç¦æ­¢ä¿®æ”¹è¿™ä¸ªå€¼
     * @serial
     */
    private static final long serialVersionUID = -5909212697362510055L;
    /**
     * æž„造函数
     */
    public DataGrid(){
    }
    /**
     * æž„造函数
     * @param msg æ¶ˆæ¯
     */
    public DataGrid(String msg){
        this.msg = msg;
        this.code = 1;
    }
    /**
     * æ€»æ•°,extjs和easyui使用total,layui使用count,这里统一为total,layui可以在table.js里修改源码,
     */
    private long total = 0;
    /**
     * æ•°æ®ï¼Œeasyui使用的rows, extjs和layui默认为data;easyui也可以修改为data,因此均使用data
     */
    private List<T> data = new ArrayList<T>();
    /**
     * æ•°æ®å¼€å§‹çš„位置
     */
    private int start;
    /**
     * æ¯é¡µæ˜¾ç¤ºå¤šå°‘行
     */
    private int limit;
    /**
     * å½“前页数
     */
    private int page;
    /**
     * æŽ’序字段
     */
    private String sort;
    /**
     * æŽ’序方式
     */
    private String order;
    /**
     * è¿”回给前端的消息,
     */
    private String msg;
    /**
     * å®ŒæˆçŠ¶æ€ï¼Œlayui必须使用这个状态来判断是否执行成功,extjs和easyui可以不用,因此默认这个值为0(表示成功);
     * ä½†æ˜¯easyui和extjs可以使用code来传递特殊的数据
     */
    private int code = 0;
    /**
     * é“¾è·¯çš„id,用于追查日志信息
     */
    private String traceId;
    public long getTotal() {
        return total;
    }
    public void setTotal(long total) {
        this.total = total;
    }
    public List<T> getData() {
        return data;
    }
    public void setData(List<T> data) {
        this.data = data;
    }
    public int getStart() {
        return start;
    }
    public void setStart(int start) {
        this.start = start;
    }
    public int getLimit() {
        return limit;
    }
    public void setLimit(int limit) {
        this.limit = limit;
    }
    public int getPage() {
        return page;
    }
    public void setPage(int page) {
        this.page = page;
    }
    public String getSort() {
        return sort;
    }
    public void setSort(String sort) {
        this.sort = sort;
    }
    public String getOrder() {
        return order;
    }
    public void setOrder(String order) {
        this.order = order;
    }
    public String getMsg() {
        return msg;
    }
    public void setMsg(String msg) {
        this.msg = msg;
    }
    public int getCode() {
        return code;
    }
    public void setCode(int code) {
        this.code = code;
    }
    public String getTraceId() {
        return traceId;
    }
    public void setTraceId(String traceId) {
        this.traceId = traceId;
    }
    @Override
    public String toString() {
        return "DataGrid{" +
                "total=" + total +
                ", data=" + data +
                ", start=" + start +
                ", limit=" + limit +
                ", page=" + page +
                ", sort='" + sort + '\'' +
                ", order='" + order + '\'' +
                ", msg='" + msg + '\'' +
                ", code=" + code +
                ", traceId='" + traceId + '\'' +
                '}';
    }
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/pagemodel/ImportResult.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,163 @@
package com.vci.starter.web.pagemodel;
/**
 * excel导入结果
 * @author weidy
 */
public class ImportResult implements java.io.Serializable {
    /**
     * ç¦æ­¢ä¿®æ”¹è¿™ä¸ªå€¼
     */
    private static final long serialVersionUID = 9043151147701785650L;
    /**
     * æ–°å¢žæ•°æ®ä¸ªæ•°
     */
    private int addCount;
    /**
     * ä¿®æ”¹æ•°æ®çš„个数
     */
    private int editCount;
    /**
     * åˆ é™¤æ•°æ®çš„个数
     */
    private int deleteCount;
    /**
     * å¿½ç•¥æ•°æ®çš„个数
     */
    private int unDoCount;
    /**
     * æ˜¯å¦æˆåŠŸ
     */
    private boolean success;
    /**
     * é”™è¯¯ä¿¡æ¯
     */
    private String msg;
    /**
     * è¿”回结果代号
     */
    private String resultCode;
    /**
     * è¿”回结果对象
     */
    private Object returnObj;
    /**
     * é“¾è·¯çš„ID
     */
    private String traceId;
    /**
     * æž„造方法
     * @param msg æ¶ˆæ¯
     */
    public ImportResult(String msg){
        this.success = false;
        this.msg = msg;
    }
    /**
     * æž„造方法
     * @param success æ˜¯å¦æˆåŠŸ
     */
    public ImportResult(boolean success){
        this.success = success;
    }
    public int getAddCount() {
        return addCount;
    }
    public void setAddCount(int addCount) {
        this.addCount = addCount;
    }
    public int getEditCount() {
        return editCount;
    }
    public void setEditCount(int editCount) {
        this.editCount = editCount;
    }
    public int getDeleteCount() {
        return deleteCount;
    }
    public void setDeleteCount(int deleteCount) {
        this.deleteCount = deleteCount;
    }
    public int getUnDoCount() {
        return unDoCount;
    }
    public void setUnDoCount(int unDoCount) {
        this.unDoCount = unDoCount;
    }
    public boolean isSuccess() {
        return success;
    }
    public void setSuccess(boolean success) {
        this.success = success;
    }
    public String getMsg() {
        return msg;
    }
    public void setMsg(String msg) {
        this.msg = msg;
    }
    public String getResultCode() {
        return resultCode;
    }
    public void setResultCode(String resultCode) {
        this.resultCode = resultCode;
    }
    public Object getReturnObj() {
        return returnObj;
    }
    public void setReturnObj(Object returnObj) {
        this.returnObj = returnObj;
    }
    public String getTraceId() {
        return traceId;
    }
    public void setTraceId(String traceId) {
        this.traceId = traceId;
    }
    @Override
    public String toString() {
        return "ImportResult{" +
                "addCount=" + addCount +
                ", editCount=" + editCount +
                ", deleteCount=" + deleteCount +
                ", unDoCount=" + unDoCount +
                ", success=" + success +
                ", msg='" + msg + '\'' +
                ", resultCode='" + resultCode + '\'' +
                ", returnObj=" + returnObj +
                ", traceId='" + traceId + '\'' +
                '}';
    }
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/pagemodel/KeyValue.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,68 @@
package com.vci.starter.web.pagemodel;
import java.util.HashMap;
import java.util.Map;
/**
 * é”®å€¼å¯¹
 * @author weidy
 */
public class KeyValue implements java.io.Serializable {
    /**
     * ç¦æ­¢ä¿®æ”¹è¿™ä¸ªå€¼
     */
    private static final long serialVersionUID = 7708882804529442626L;
    /**
     * é”®
     */
    private String key;
    /**
     * å€¼
     */
    private String value;
    /**
     * å…¶ä»–属性
     */
    private Map<String,Object> attributes = new HashMap<String, Object>();
    public String getKey() {
        return key;
    }
    public void setKey(String key) {
        this.key = key;
    }
    public String getValue() {
        return value;
    }
    public void setValue(String value) {
        this.value = value;
    }
    public Map<String, Object> getAttributes() {
        return attributes;
    }
    public void setAttributes(Map<String, Object> attributes) {
        this.attributes = attributes;
    }
    public void addAttr(String attr, Object attrValue){
        this.attributes.put(attr, attrValue);
    }
    @Override
    public String toString() {
        return "KeyValue{" +
                "key='" + key + '\'' +
                ", value='" + value + '\'' +
                ", attributes=" + attributes +
                '}';
    }
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/pagemodel/PageHelper.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,416 @@
package com.vci.starter.web.pagemodel;
import org.apache.commons.lang3.StringUtils;
import java.util.HashSet;
import java.util.Set;
/**
 * ExtJs,easyui,layui åˆ†é¡µå¸®åŠ©ç±»
 *
 * @author weidy
 *
 */
public class PageHelper implements java.io.Serializable {
    /**
     * åºåˆ—化
     */
    private static final long serialVersionUID = -588765760880887850L;
    /**
     * å½“前页
     */
    private int page;
    // å½“前页
    /**
     * æŽ’序字段
     */
    private String sort;
    // æŽ’序字段  ---前端只支持使用一个字段来排序,但是后台实际可以使用多个字段来排序,所以可以使用逗号分割
    /**
     * æŽ’序类型
     */
    private String order;
    // asc/desc,如果有多个排序字段时,这里也需要用逗号分割,且与sort的位置对应
    /**
     * èµ·å§‹æ•°æ®è¡Œæ•°
     */
    private int start = 0;
    /**
     * æ¯é¡µæ˜¾ç¤ºé¡µæ•°
     */
    private int limit = 25;
    //每页显示的条数
    /**
     * æ˜¯å¦è¦æ”¯æŒæ˜¾ç¤ºæ€»é¡µæ•°å’Œæ€»æ¡æ•°----在数据量巨大的情况下,可以不查询总数
     */
    private boolean queryTotal = true;
    /**
     * æŽ’序的SQL
     */
    private String ordersql ;
    /**
     * è¡¨çš„æ˜µç§°
     */
    private String nick;
    /**
     * å‡åº
     */
    public final String asc = "asc";
    /**
     * é™åº
     */
    public final String desc = "desc";
    /**
     * ä¸ä½¿ç”¨è¡¨æ˜µç§°çš„字段
     */
    private Set<String> unNickField = new HashSet<>();
    /**
     * é»˜è®¤æž„造函数
     */
    public PageHelper(){
    }
    /**
     * æž„造函数,设置分页数
     * @param limit åˆ†é¡µæ•°
     */
    public PageHelper(int limit){
        this.limit = limit;
        this.page = 1;
    }
    /**
     * æž„造函数,设置分页数和是否查询总数
     * @param limit åˆ†é¡µæ•°
     * @param queryTotal æŸ¥è¯¢æ€»æ•°
     */
    public PageHelper(int limit,boolean queryTotal){
        this.limit = limit;
        this.queryTotal = queryTotal;
    }
    /**
     * æž„造函数,这种升序的排序字段
     * @param sort å‡åºçš„字段
     */
    public PageHelper(String sort){
        this.sort = sort;
        this.limit = -1;
        this.order = "asc";
    }
    /**
     * æž„造函数,设置排序字段和排序方式
     * @param sort æŽ’序字段
     * @param order æŽ’序方式
     */
    public PageHelper(String sort, String order){
        this.sort = sort;
        this.limit = -1;
        this.order = order;
    }
    /**
     * æž„造函数,设置分页,排序字段和排序方式
     * @param limit åˆ†é¡µæ•°
     * @param sort æŽ’序字段
     * @param order æŽ’序方式
     */
    public PageHelper(int limit, String sort, String order){
        this.limit = limit;
        this.sort = sort;
        this.order = order;
    }
    /**
     * æž„造函数,设置分页,排序字段和排序方式
     * @param limit åˆ†é¡µæ•°
     * @param page å½“前页
     * @param sort æŽ’序字段
     * @param order æŽ’序方式
     */
    public PageHelper(int limit, int page, String sort, String order){
        this.limit = limit;
        this.page = page;
        this.sort = sort;
        this.order = order;
    }
    /**
     * èŽ·å–å½“å‰é¡µ
     * @return å½“前页数
     */
    public int getPage() {
        return page;
    }
    /**
     * è®¾ç½®å½“前页,会自动计算数据起始行数
     * @param page å½“前页
     */
    public void setPage(int page) {
        this.page = page;
        if(page>0&&this.limit>0){
            start = (this.page-1)*this.limit;
        }
    }
    /**
     * è®¾ç½®æŽ’序字段
     * @param sort æŽ’序字段
     */
    public void setSort(String sort) {
        this.sort = sort;
    }
    /**
     * èŽ·å–æŽ’åºæ–¹å¼
     * @return æŽ’序方式
     */
    public String getOrder() {
        return order;
    }
    /**
     * è®¾ç½®æŽ’序方式
     * @param order æŽ’序方式
     */
    public void setOrder(String order) {
        this.order = order;
    }
    /**
     * èŽ·å–èµ·å§‹æ•°
     * @return è¡Œèµ·å§‹æ•°
     */
    public int getStart() {
        if(this.limit <=0){
            return 0;
        }else{
            return (this.page-1)*this.limit + 1;
        }
    }
    /**
     * æ˜¯å¦æŸ¥è¯¢æ€»æ•°
     * @return true表示查询,默认为true
     */
    public boolean isQueryTotal() {
        return queryTotal;
    }
    /**
     * æ˜¯å¦æŸ¥è¯¢æ€»æ•°
     * @param queryTotal æ˜¯å¦æŸ¥è¯¢æ€»æ•°
     */
    public void setQueryTotal(boolean queryTotal) {
        this.queryTotal = queryTotal;
    }
    /**
     * èŽ·å–æ¯é¡µæ˜¾ç¤ºå¤šå°‘è¡Œ
     * @return æ¯é¡µæ˜¾ç¤ºè¡Œæ•°
     */
    public int getLimit() {
        return limit;
    }
    /**
     * è®¾ç½®æ¯é¡µæ˜¾ç¤ºè¡Œæ•°
     * @param limit æ¯é¡µæ˜¾ç¤ºè¡Œæ•°
     */
    public void setLimit(int limit) {
        this.limit = limit;
        if(page>0&&this.limit>0){
            start = (this.page-1)*this.limit + 1;
        }
    }
    /**
     * å¢žåŠ æŽ’åº
     * @param sort æŽ’序字段
     * @param order æŽ’序方式
     */
    public void addSort(String sort, String order){
        this.setSort(StringUtils.isBlank(this.getSort())?sort:(this.getSort() + "," + sort) );
        this.setOrder(StringUtils.isBlank(this.getOrder())?order:(this.getOrder() + "," + order));
    }
    /**
     * å¢žåŠ å‡åº
     * @param field å‡åºçš„字段
     */
    public void addAsc(String field){
        this.addSort(field,asc);
    }
    /**
     * åœ¨æ²¡æœ‰æŽ’序的时候才添加默认的升序排列字段
     * @param field é»˜è®¤çš„升序的字段
     */
    public void addDefaultAsc(String field){
        if(StringUtils.isBlank(this.getSort()) && StringUtils.isBlank(this.getOrder())){
            this.addAsc(field);
        }
    }
    /**
     * åœ¨æ²¡æœ‰æŽ’序的时候才添加默认的降序排列字段
     * @param field é»˜è®¤çš„降序的字段
     */
    public void addDefaultDesc(String field){
        if(StringUtils.isBlank(this.getSort()) && StringUtils.isBlank(this.getOrder())){
            this.addDesc(field);
        }
    }
    /**
     * å¢žåŠ é™åº
     * @param field é™åºçš„字段
     */
    public void addDesc(String field){
        this.addSort(field,desc);
    }
    /**
     * èŽ·å–æŽ’åºå­—æ®µ
     * @return æŽ’序字段
     */
    public String getSort() {
        return sort;
    }
    /**
     * è®¾ç½®èµ·å§‹æ•°
     * @param start èµ·å§‹æ•°
     */
    public void setStart(int start) {
        this.start = start;
    }
    /**
     * èŽ·å–æŽ’åºçš„SQL语句,在Hibernate里使用
     * @return æŽ’序的SQL
     */
    public String getOrdersql() {
        if(ordersql == null || ordersql.trim().length() == 0){
            if(sort !=null && sort.trim().length() >0  && order !=null && order.trim().length() > 0){
                if(sort.indexOf(",") > -1){
                    String[] sortArray = sort.split(",");
                    String[] orderArray = order.split(",");
                    StringBuilder sb = new StringBuilder();
                    for(int i = 0 ; i < sortArray.length ; i ++){
                        if(StringUtils.isNotBlank(sortArray[i])
                                && orderArray.length > i
                                && StringUtils.isNotBlank(orderArray[i])) {
                            if(sortArray[i].indexOf(".")<0) {
                                //不是参照
                                if(!unNickField.contains(sortArray[i].toLowerCase())) {
                                    sb.append(StringUtils.isBlank(this.getNick()) ? "" : (this.getNick() + "."));
                                }
                            }
                            sb.append(sortArray[i].toLowerCase());
                            sb.append(" ");
                            sb.append(orderArray[i]);
                            sb.append(",");
                        }
                    }
                    ordersql = " order by " + sb.toString();
                    if(ordersql.endsWith(",")){
                        ordersql = ordersql.substring(0,ordersql.length()-1);
                    }
                }else {
                    ordersql = " order by " + sort + " " + order;
                }
            }
        }
        return ordersql;
    }
    /**
     * èŽ·å–æŽ’åºçš„SQL语句,在Hibernate里使用
     * @param nick æ˜µç§°
     * @return æŽ’序的SQL
     */
    public String getOrderSql(String nick){
        if(ordersql == null || ordersql.trim().length() == 0){
            if(sort !=null && sort.trim().length() >0  && order !=null && order.trim().length() > 0){
                if(sort.indexOf(",") > -1){
                    String[] sortArray = sort.split(",");
                    String[] orderArray = order.split(",");
                    StringBuilder sb = new StringBuilder();
                    for(int i = 0 ; i < sortArray.length ; i ++){
                        if(StringUtils.isNotBlank(sortArray[i])
                                && orderArray.length > i
                                && StringUtils.isNotBlank(orderArray[i])) {
                            if(sortArray[i].indexOf(".")<0) {
                                //不是参照
                                sb.append(StringUtils.isBlank(nick) ? "" : (nick + "."));
                            }
                            sb.append(sortArray[i].toLowerCase());
                            sb.append(" ");
                            sb.append(orderArray[i]);
                            sb.append(",");
                        }
                    }
                    ordersql = " order by " + sb.toString();
                    if(ordersql.endsWith(",")){
                        ordersql = ordersql.substring(0,ordersql.length()-1);
                    }
                }else {
                    ordersql = " order by " + nick + "." + sort + " " + order;
                }
            }
        }
        return ordersql;
    }
    public String getNick() {
        return nick;
    }
    public void setNick(String nick) {
        this.nick = nick;
    }
    /**
     * è®¾ç½®æŽ’序的字段
     * @param ordersql æŽ’序字段
     */
    public void setOrdersql(String ordersql) {
        this.ordersql = ordersql;
    }
    @Override
    public String toString() {
        return "PageHelper{" +
                "page=" + page +
                ", sort='" + sort + '\'' +
                ", order='" + order + '\'' +
                ", start=" + start +
                ", limit=" + limit +
                ", queryTotal=" + queryTotal +
                ", ordersql='" + ordersql + '\'' +
                ", nick='" + nick + '\'' +
                ", asc='" + asc + '\'' +
                ", desc='" + desc + '\'' +
                ", unNickField=" + unNickField +
                '}';
    }
    public Set<String> getUnNickField() {
        return unNickField;
    }
    public void setUnNickField(Set<String> unNickField) {
        this.unNickField = unNickField;
    }
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/pagemodel/RequestClientInfo.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,131 @@
package com.vci.starter.web.pagemodel;
/**
 * å®¢æˆ·ç«¯è¯·æ±‚信息
 * @author weidy
 */
public class RequestClientInfo implements java.io.Serializable{
    /**
     * ç¦æ­¢ä¿®æ”¹è¿™ä¸ª
     */
    private static final long serialVersionUID = -2574607667597721739L;
    /**
     * è¯·æ±‚访问方式,浏览器,APP,wap,
     */
    private String requestType = "browser";
    /**
     * æµè§ˆå™¨æ–¹å¼
     */
    private String browser = "";
    /**
     * æµè§ˆå™¨çš„版本
     */
    private String browserversion = "";
    /**
     * ç³»ç»Ÿçš„版本
     */
    private String osversion = "";
    /**
     * ip地址
     */
    private String ipaddress = "";
    /**
     * æ˜¯å¦å•点登录
     */
    private boolean sso;
    /**
     * å•点登录的名称
     */
    private String ssoSystemName;
    /**
     * å•点登录的token
     */
    private String ssoToken;
    public String getRequestType() {
        return requestType;
    }
    public void setRequestType(String requestType) {
        this.requestType = requestType;
    }
    public String getBrowser() {
        return browser;
    }
    public void setBrowser(String browser) {
        this.browser = browser;
    }
    public String getBrowserversion() {
        return browserversion;
    }
    public void setBrowserversion(String browserversion) {
        this.browserversion = browserversion;
    }
    public String getOsversion() {
        return osversion;
    }
    public void setOsversion(String osversion) {
        this.osversion = osversion;
    }
    public String getIpaddress() {
        return ipaddress;
    }
    public void setIpaddress(String ipaddress) {
        this.ipaddress = ipaddress;
    }
    public boolean isSso() {
        return sso;
    }
    public void setSso(boolean sso) {
        this.sso = sso;
    }
    public String getSsoSystemName() {
        return ssoSystemName;
    }
    public void setSsoSystemName(String ssoSystemName) {
        this.ssoSystemName = ssoSystemName;
    }
    public String getSsoToken() {
        return ssoToken;
    }
    public void setSsoToken(String ssoToken) {
        this.ssoToken = ssoToken;
    }
    @Override
    public String toString() {
        return "RequestClientInfo{" +
                "requestType='" + requestType + '\'' +
                ", browser='" + browser + '\'' +
                ", browserversion='" + browserversion + '\'' +
                ", osversion='" + osversion + '\'' +
                ", ipaddress='" + ipaddress + '\'' +
                ", sso=" + sso +
                ", ssoSystemName='" + ssoSystemName + '\'' +
                ", ssoToken='" + ssoToken + '\'' +
                '}';
    }
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/pagemodel/SessionInfo.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,669 @@
package com.vci.starter.web.pagemodel;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
 * session信息模型
 *
 * @author weidy
 *
 */
public class SessionInfo implements java.io.Serializable {
    /**
     *  ç¦æ­¢ä¿®æ”¹è¿™ä¸ªå€¼
     *  @serial
     */
    private static final long serialVersionUID = 7950268190988911233L;
    /**
     * ç”¨æˆ·æ‰€å±žç»„织主键
     */
    private String orgsOid;
    /**
     * ç”¨æˆ·æ‰€å±žç»„织名称
     */
    private String orgsName;
    /**
     * æ‰€å±žéƒ¨é—¨ä¸»é”®
     */
    private String deptOid;
    /**
     * æ‰€å±žéƒ¨é—¨åç§°
     */
    private String deptName;
    /**
     * æ‰€å±žç”¨æˆ·ä¸»é”®
     */
    private String userOid;
    /**
     * ç”¨æˆ·å
     */
    private String userId;
    /**
     * å§“名
     */
    private String userName;
    /**
     * ç”¨æˆ·èº«ä»½ä¸»é”®
     */
    private String personOid;
    /**
     * èº«ä»½ç¼–号(人员)
     */
    private String personId;
    /**
     * ç”¨æˆ·èº«ä»½åç§°
     */
    private String personName;
    /**
     * æ‰€å±žèŒåŠ¡
     */
    private String dutyOid;
    /**
     * æ‰€å±žèŒåŠ¡åç§°
     */
    private String dutyName;
    /**
     * æ‰€å±žäººå‘˜ç»„
     */
    private String workgroupOid;
    /**
     * æ‰€å±žäººå‘˜ç»„名称
     */
    private String workgroupName;
    /**
     * æ‰€å±žå·¥ç§
     */
    private String workTypeOid;
    /**
     * æ‰€å±žå·¥ç§åç§°
     */
    private String workTypeName;
    /**
     * ç”¨æˆ·ç±»åž‹
     */
    private String usertype;
    /**
     * ç”¨æˆ·ç±»åž‹æ–‡æœ¬
     */
    private String usertypeText;
    /**
     * æ€§åˆ«
     */
    private String sex;
    /**
     * æ€§åˆ«åç§°
     */
    private String sexText;
    /**
     * è§’色名称
     */
    private Map<String,String> rolesName;
    /**
     * æ‰€æœ‰çš„æƒé™åŠŸèƒ½ä¸»é”®
     */
    private List<String> functionOids;//当前用户的所有的权限的主键
    /**
     * æ‰€æœ‰çš„æƒé™åŠŸèƒ½æ“ä½œ
     */
    private Map<String, Integer> functionOperaMap;
    /**
     * å¤´åƒåœ°å€
     */
    private String photoUrl;
    /**
     * IP地址
     */
    private String ip;//ip地址
    /**
     * è¯­è¨€
     */
    private String language;//语种
    /**
     * ç”¨æˆ·å¯†çº§
     */
    private String userSecret;
    /**
     * ç”¨æˆ·å¯†çº§æ–‡æœ¬
     */
    private String userSecretText;
    /**
     * ip密级
     */
    private String ipSecret;
    /**
     * ip密级文本
     */
    private String ipSecretText;
    /**
     * ç™»å½•机器信息
     */
    private String machine;//机器信息
    /**
     * æ“ä½œç³»ç»Ÿ
     */
    private String os;//操作系统信息
    /**
     * æµè§ˆå™¨ç‰ˆæœ¬
     */
    private String browser;//浏览器信息
    /**
     * æ“ä½œç³»ç»Ÿç”¨æˆ·å
     */
    private String osUser;//操作系统用户信息
    /**
     * ç§»åŠ¨è®¾å¤‡çš„ä¿¡æ¯
     */
    private List<String> deviceInfo = new ArrayList<String>();
    /**
     * é‚®ä»¶
     */
    private String email;
    /**
     * ç”µè¯å·ç 
     */
    private String phoneNo;
    /**
     * RTX账户
     */
    private String rtxNo;
    /**
     * é—¨æˆ·ç³»ç»ŸID
     */
    private String portalId;
    /**
     * å³æ—¶é€šè®¯ID
     */
    private String IMId;
    /**
     * æ˜¯å¦å•点登录
     */
    private boolean sso;
    /**
     * å•点登录的来源系统名称
     */
    private String ssoServiceName;
    /**
     * è®¸å¯ç 
     */
    private String token;
    /**
     * å¯¹äºŽç”¨æˆ·çš„全局参数
     */
    private Map<String,String> globalAttributeMap = new HashMap<String, String>();
    /**
     * å·¥å·(短号)
     */
    private String workNo;
    /**
     * æ˜¯å¦å¿…须修改密码
     */
    private boolean isMustChangePassword = false;
    /**
     * å¯†ç ä¿¡æ¯
     */
    private String passwordInfo;
    public String getDutyOid() {
        return dutyOid;
    }
    public void setDutyOid(String dutyOid) {
        this.dutyOid = dutyOid;
    }
    public String getDutyName() {
        return dutyName;
    }
    public void setDutyName(String dutyName) {
        this.dutyName = dutyName;
    }
    public String getOrgsOid() {
        return orgsOid;
    }
    public void setOrgsOid(String orgsOid) {
        this.orgsOid = orgsOid;
    }
    public String getOrgsName() {
        return orgsName;
    }
    public void setOrgsName(String orgsName) {
        this.orgsName = orgsName;
    }
    public String getDeptOid() {
        return deptOid;
    }
    public void setDeptOid(String deptOid) {
        this.deptOid = deptOid;
    }
    public String getDeptName() {
        return deptName;
    }
    public void setDeptName(String deptName) {
        this.deptName = deptName;
    }
    public String getUserOid() {
        return userOid;
    }
    public void setUserOid(String userOid) {
        this.userOid = userOid;
    }
    public String getUserId() {
        return userId;
    }
    public void setUserId(String userId) {
        this.userId = userId;
    }
    public String getUserName() {
        return userName;
    }
    public void setUserName(String userName) {
        this.userName = userName;
    }
    public String getPersonOid() {
        return personOid;
    }
    public void setPersonOid(String personOid) {
        this.personOid = personOid;
    }
    public String getPersonName() {
        return personName;
    }
    public void setPersonName(String personName) {
        this.personName = personName;
    }
    public String getWorkgroupOid() {
        return workgroupOid;
    }
    public void setWorkgroupOid(String workgroupOid) {
        this.workgroupOid = workgroupOid;
    }
    public String getWorkgroupName() {
        return workgroupName;
    }
    public void setWorkgroupName(String workgroupName) {
        this.workgroupName = workgroupName;
    }
    public String getUsertype() {
        return usertype;
    }
    public void setUsertype(String usertype) {
        this.usertype = usertype;
    }
    public String getUsertypeText() {
        return usertypeText;
    }
    public void setUsertypeText(String usertypeText) {
        this.usertypeText = usertypeText;
    }
    public String getSex() {
        return sex;
    }
    public void setSex(String sex) {
        this.sex = sex;
    }
    public List<String> getFunctionOids() {
        return functionOids;
    }
    public void setFunctionOids(List<String> functionOids) {
        this.functionOids = functionOids;
    }
    public String getPhotoUrl() {
        return photoUrl;
    }
    public void setPhotoUrl(String photoUrl) {
        this.photoUrl = photoUrl;
    }
    public String getIp() {
        return ip;
    }
    public void setIp(String ip) {
        this.ip = ip;
    }
    public String getLanguage() {
        return language;
    }
    public void setLanguage(String language) {
        this.language = language;
    }
    public String getUserSecret() {
        return userSecret;
    }
    public void setUserSecret(String userSecret) {
        this.userSecret = userSecret;
    }
    public String getUserSecretText() {
        return userSecretText;
    }
    public void setUserSecretText(String userSecretText) {
        this.userSecretText = userSecretText;
    }
    public String getIpSecret() {
        return ipSecret;
    }
    public void setIpSecret(String ipSecret) {
        this.ipSecret = ipSecret;
    }
    public String getIpSecretText() {
        return ipSecretText;
    }
    public void setIpSecretText(String ipSecretText) {
        this.ipSecretText = ipSecretText;
    }
    public String getMachine() {
        return machine;
    }
    public void setMachine(String machine) {
        this.machine = machine;
    }
    public String getOs() {
        return os;
    }
    public void setOs(String os) {
        this.os = os;
    }
    public String getBrowser() {
        return browser;
    }
    public void setBrowser(String browser) {
        this.browser = browser;
    }
    public String getOsUser() {
        return osUser;
    }
    public void setOsUser(String osUser) {
        this.osUser = osUser;
    }
    public List<String> getDeviceInfo() {
        return deviceInfo;
    }
    public void setDeviceInfo(List<String> deviceInfo) {
        this.deviceInfo = deviceInfo;
    }
    public String getEmail() {
        return email;
    }
    public void setEmail(String email) {
        this.email = email;
    }
    public String getPhoneNo() {
        return phoneNo;
    }
    public void setPhoneNo(String phoneNo) {
        this.phoneNo = phoneNo;
    }
    public String getRtxNo() {
        return rtxNo;
    }
    public void setRtxNo(String rtxNo) {
        this.rtxNo = rtxNo;
    }
    public String getPortalId() {
        return portalId;
    }
    public void setPortalId(String portalId) {
        this.portalId = portalId;
    }
    public String getIMId() {
        return IMId;
    }
    public void setIMId(String IMId) {
        this.IMId = IMId;
    }
    public boolean isSso() {
        return sso;
    }
    public void setSso(boolean sso) {
        this.sso = sso;
    }
    public String getSsoServiceName() {
        return ssoServiceName;
    }
    public void setSsoServiceName(String ssoServiceName) {
        this.ssoServiceName = ssoServiceName;
    }
    public String getToken() {
        return token;
    }
    public void setToken(String token) {
        this.token = token;
    }
    public Map<String, String> getGlobalAttributeMap() {
        return globalAttributeMap;
    }
    public void setGlobalAttributeMap(Map<String, String> globalAttributeMap) {
        this.globalAttributeMap = globalAttributeMap;
    }
    public String getPersonId() {
        return personId;
    }
    public void setPersonId(String personId) {
        this.personId = personId;
    }
    public String getSexText() {
        return sexText;
    }
    public void setSexText(String sexText) {
        this.sexText = sexText;
    }
    public Map<String, String> getRolesName() {
        return rolesName;
    }
    public void setRolesName(Map<String, String> rolesName) {
        this.rolesName = rolesName;
    }
    public String getWorkNo() {
        return workNo;
    }
    public void setWorkNo(String workNo) {
        this.workNo = workNo;
    }
    public String getWorkTypeOid() {
        return workTypeOid;
    }
    public void setWorkTypeOid(String workTypeOid) {
        this.workTypeOid = workTypeOid;
    }
    public String getWorkTypeName() {
        return workTypeName;
    }
    public void setWorkTypeName(String workTypeName) {
        this.workTypeName = workTypeName;
    }
    public boolean isMustChangePassword() {
        return isMustChangePassword;
    }
    public void setMustChangePassword(boolean mustChangePassword) {
        isMustChangePassword = mustChangePassword;
    }
    public String getPasswordInfo() {
        return passwordInfo;
    }
    public void setPasswordInfo(String passwordInfo) {
        this.passwordInfo = passwordInfo;
    }
    public Map<String, Integer> getFunctionOperaMap() {
        return functionOperaMap;
    }
    public void setFunctionOperaMap(Map<String, Integer> functionOperaMap) {
        this.functionOperaMap = functionOperaMap;
    }
    @Override
    public String toString() {
        return "SessionInfo{" +
                "orgsOid='" + orgsOid + '\'' +
                ", orgsName='" + orgsName + '\'' +
                ", deptOid='" + deptOid + '\'' +
                ", deptName='" + deptName + '\'' +
                ", userOid='" + userOid + '\'' +
                ", userId='" + userId + '\'' +
                ", userName='" + userName + '\'' +
                ", personOid='" + personOid + '\'' +
                ", personId='" + personId + '\'' +
                ", personName='" + personName + '\'' +
                ", dutyOid='" + dutyOid + '\'' +
                ", dutyName='" + dutyName + '\'' +
                ", workgroupOid='" + workgroupOid + '\'' +
                ", workgroupName='" + workgroupName + '\'' +
                ", workTypeOid='" + workTypeOid + '\'' +
                ", workTypeName='" + workTypeName + '\'' +
                ", usertype='" + usertype + '\'' +
                ", usertypeText='" + usertypeText + '\'' +
                ", sex='" + sex + '\'' +
                ", sexText='" + sexText + '\'' +
                ", rolesName=" + rolesName +
                ", functionOids=" + functionOids +
                ", functionOperaMap=" + functionOperaMap +
                ", photoUrl='" + photoUrl + '\'' +
                ", ip='" + ip + '\'' +
                ", language='" + language + '\'' +
                ", userSecret='" + userSecret + '\'' +
                ", userSecretText='" + userSecretText + '\'' +
                ", ipSecret='" + ipSecret + '\'' +
                ", ipSecretText='" + ipSecretText + '\'' +
                ", machine='" + machine + '\'' +
                ", os='" + os + '\'' +
                ", browser='" + browser + '\'' +
                ", osUser='" + osUser + '\'' +
                ", deviceInfo=" + deviceInfo +
                ", email='" + email + '\'' +
                ", phoneNo='" + phoneNo + '\'' +
                ", rtxNo='" + rtxNo + '\'' +
                ", portalId='" + portalId + '\'' +
                ", IMId='" + IMId + '\'' +
                ", sso=" + sso +
                ", ssoServiceName='" + ssoServiceName + '\'' +
                ", token='" + token + '\'' +
                ", globalAttributeMap=" + globalAttributeMap +
                ", workNo='" + workNo + '\'' +
                ", isMustChangePassword=" + isMustChangePassword +
                ", passwordInfo='" + passwordInfo + '\'' +
                '}';
    }
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/pagemodel/Tree.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,406 @@
package com.vci.starter.web.pagemodel;
import org.apache.commons.lang3.StringUtils;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
 * æ ‘型数据,easyui,extjs,layui通用
 * @author weidy
 *
 */
public class Tree implements java.io.Serializable{
    /**
     * ç¦æ­¢ä¿®æ”¹è¿™ä¸ªå€¼
     * @serial åºåˆ—化值
     */
    private static final long serialVersionUID = 6886695271635257882L;
    /**
     * æž„造函数
     */
    public Tree(){
    }
    /**
     * æž„造函数
     * @param oid ä¸»é”®
     * @param text æ ‘节点文本
     */
    public Tree(String oid, String text){
        setOid(oid);
        setText(text);
    }
    /**
     * ä¸»é”®
     */
    private String oid;
    /**
     * æ˜¾ç¤ºæ–‡æœ¬
     */
    private String text;
    /**
     * æ˜¯å¦å¶å­
     */
    private boolean leaf = false;
    /**
     * æ˜¯å¦æ˜¾ç¤ºå¤é€‰æ¡†
     */
    private boolean showCheckbox = false;
    /**
     * æ˜¯å¦é»˜è®¤é€‰ä¸­
     */
    private boolean checked = false;
    /**
     * å­èŠ‚ç‚¹
     */
    private List<Tree> children = new ArrayList<Tree>();
    /**
     * å›¾æ ‡
     */
    private String icon;
    /**
     * å›¾æ ‡æ ·å¼
     */
    private String iconCls;
    /**
     * ä¸Šçº§èŠ‚ç‚¹
     */
    private String parentId;
    /**
     * ä¸Šçº§èŠ‚ç‚¹çš„åç§°
     */
    private String parentName;
    /**
     * ä¸Šçº§èŠ‚ç‚¹çš„ä¸šåŠ¡ç±»åž‹
     */
    private String parentBtmName;
    /**
     * æ˜¯å¦å±•å¼€
     */
    private boolean expanded = false;
    /**
     * é“¾æŽ¥
     */
    private String href;//layui和extjs使用href,easyui使用url,统一href
    /**
     * æŽ’序索引
     */
    private String index;//排序索引
    /**
     * å…¶ä»–的属性
     */
    private Map<String,String> attributes = new HashMap<String, String>();//使用平台的话,所有的属性都是String的
    /**
     * èŽ·å–ä¸»é”®
     * @return ä¸»é”®çš„值
     */
    public String getOid() {
        return oid;
    }
    /**
     * è®¾ç½®ä¸»é”®
     * @param oid ä¸»é”®çš„值
      */
    public void setOid(String oid) {
        this.oid = oid;
    }
    /**
     * èŽ·å–æ ‘èŠ‚ç‚¹æ–‡æœ¬
     * @return æ ‘节点文本
     */
    public String getText() {
        return text;
    }
    /**
     * è®¾ç½®æ ‘节点文本
     * @param text æ ‘节点文本
     */
    public void setText(String text) {
        this.text = text;
    }
    /**
     * æ˜¯å¦å¶å­èŠ‚ç‚¹
     * @return true è¡¨ç¤ºå¶å­èŠ‚ç‚¹
     */
    public boolean isLeaf() {
        return leaf;
    }
    /**
     * è®¾ç½®å¶å­èŠ‚ç‚¹
     * @param leaf æ˜¯å¦å¶å­èŠ‚ç‚¹
     */
    public void setLeaf(boolean leaf) {
        this.leaf = leaf;
    }
    /**
     * æ˜¯å¦æ˜¾ç¤ºå¤é€‰æ¡†
     * @return true表示显示
     */
    public boolean isShowCheckbox() {
        return showCheckbox;
    }
    /**
     * è®¾ç½®æ˜¯å¦æ˜¾ç¤ºå¤é€‰æ¡†
     * @param showCheckbox æ˜¯å¦æ˜¾ç¤ºå¤é€‰æ¡†
     */
    public void setShowCheckbox(boolean showCheckbox) {
        this.showCheckbox = showCheckbox;
    }
    /**
     * æ˜¯å¦è‡ªåŠ¨å‹¾é€‰ä¸Š
     * @return true表示需要自动勾选
     */
    public boolean isChecked() {
        return checked;
    }
    /**
     * è®¾ç½®æ˜¯å¦å‹¾é€‰
     * @param checked æ˜¯å¦è‡ªåЍ勾选
     */
    public void setChecked(boolean checked) {
        this.checked = checked;
    }
    /**
     * èŽ·å–å­èŠ‚ç‚¹
     * @return å­èŠ‚ç‚¹åˆ—è¡¨
     */
    public List<Tree> getChildren() {
        return children;
    }
    /**
     * è®¾ç½®å­èŠ‚ç‚¹
     * @param children å­èŠ‚ç‚¹åˆ—è¡¨
     */
    public void setChildren(List<Tree> children) {
        this.children = children;
    }
    /**
     * èŽ·å–å›¾æ ‡
     * @return å›¾æ ‡
     */
    public String getIcon() {
        return icon;
    }
    /**
     * è®¾ç½®å›¾æ ‡
     * @param icon å›¾æ ‡
     */
    public void setIcon(String icon) {
        this.icon = icon;
    }
    /**
     * èŽ·å–å›¾æ ‡çš„æ˜¾ç¤ºcssç±»
     * @return css类的名称
     */
    public String getIconCls() {
        return iconCls;
    }
    /**
     * è®¾ç½®å›¾æ ‡çš„æ˜¾ç¤ºcssç±»
     * @param iconCls css类的名称
     */
    public void setIconCls(String iconCls) {
        this.iconCls = iconCls;
    }
    /**
     * èŽ·å–ä¸Šçº§ä¸»é”®
     * @return ä¸Šçº§èŠ‚ç‚¹çš„oid
     */
    public String getParentId() {
        return parentId;
    }
    /**
     * è®¾ç½®ä¸Šçº§ä¸»é”®
     * @param parentId ä¸Šçº§èŠ‚ç‚¹çš„oid
     */
    public void setParentId(String parentId) {
        this.parentId = parentId;
    }
    /**
     * æ˜¯å¦è‡ªåЍ展开
     * @return true表示自动展开
     */
    public boolean isExpanded() {
        return expanded;
    }
    /**
     * è®¾ç½®æ˜¯å¦è‡ªåЍ展开
     * @param expanded æ˜¯å¦è‡ªåЍ展开
     */
    public void setExpanded(boolean expanded) {
        this.expanded = expanded;
    }
    /**
     * èŽ·å–é“¾æŽ¥åœ°å€
     * @return é“¾æŽ¥åœ°å€
     */
    public String getHref() {
        return href;
    }
    /**
     * è®¾ç½®é“¾æŽ¥åœ°å€
     * @param href é“¾æŽ¥åœ°å€
     */
    public void setHref(String href) {
        this.href = href;
    }
    /**
     * èŽ·å–æŽ’åºå·
     * @return æŽ’序号
     */
    public String getIndex() {
        return index;
    }
    /**
     * è®¾ç½®æŽ’序号
     * @param index æŽ’序号
     */
    public void setIndex(String index) {
        this.index = index;
    }
    /**
     * èŽ·å–æ ‘èŠ‚ç‚¹æŒ‡ä»£çš„ä¸šåŠ¡æ•°æ®çš„æ‰€æœ‰å±žæ€§æ˜ å°„
     * @return key表示属性的名称,value表示属性的值
     */
    public Map<String, String> getAttributes() {
        return attributes;
    }
    /**
     * è®¾ç½®æ ‘节点指代的业务数据的所有属性映射
     * @param attributes key表示属性的名称,value表示属性的值
     */
    public void setAttributes(Map<String, String> attributes) {
        this.attributes = attributes;
    }
    /**
     * èŽ·å–ä¸Šçº§çš„èŠ‚ç‚¹çš„åç§°
     * @return ä¸Šçº§çš„名称
     */
    public String getParentName() {
        return parentName;
    }
    /**
     * è®¾ç½®ä¸Šçº§èŠ‚ç‚¹çš„åç§°
     * @param parentName ä¸Šçº§çš„名称
     */
    public void setParentName(String parentName) {
        this.parentName = parentName;
    }
    public String getParentBtmName() {
        return parentBtmName;
    }
    public void setParentBtmName(String parentBtmName) {
        this.parentBtmName = parentBtmName;
    }
    /**
     * åˆ©ç”¨é€’归将树转换为上下级关系
     * @param rootTree é¡¶å±‚节点
     * @param children å­èŠ‚ç‚¹
     * @return å«æœ‰ä¸Šä¸‹çº§å…³ç³»çš„æ ‘
     */
    public static List<Tree> getChildList(List<Tree> rootTree, List<Tree> children){
        if(rootTree == null ||rootTree.size() == 0){
            if(children !=null && children.size()>0){
                rootTree = children.subList(0, children.size());
            }else{
                return null;
            }
        }
        Tree bt = new Tree();
        bt.findChild(rootTree, children);
        return rootTree;
    }
    /**
     * æŸ¥è¯¢æ ‘的下级
     * @param treenode å½“前节点
     * @param children å…¶ä»–的节点
     */
    public void findChild(List<Tree> treenode, List<Tree> children){
        for (Tree node : treenode) {
            for (Tree childnode : children) {
                if (node.getOid().equalsIgnoreCase(childnode.getParentId())) {
                    childnode.setParentName(node.getText());
                    if(StringUtils.isBlank(childnode.getParentBtmName())){
                        childnode.setParentBtmName(node.getAttributes().getOrDefault("btmname",""));
                    }
                    node.getChildren().add(childnode);
                }
            }
            if (node.getChildren().size()>0) {
                findChild(node.getChildren(), children);
                node.setLeaf(false);
            }else {
                node.setLeaf(true);
            }
            this.getChildren().add(node);
        }
    }
    @Override
    public String toString() {
        return "Tree{" +
                "oid='" + oid + '\'' +
                ", text='" + text + '\'' +
                ", leaf=" + leaf +
                ", showCheckbox=" + showCheckbox +
                ", checked=" + checked +
                ", children=" + children +
                ", icon='" + icon + '\'' +
                ", iconCls='" + iconCls + '\'' +
                ", parentId='" + parentId + '\'' +
                ", parentName='" + parentName + '\'' +
                ", parentBtmName='" + parentBtmName + '\'' +
                ", expanded=" + expanded +
                ", href='" + href + '\'' +
                ", index='" + index + '\'' +
                ", attributes=" + attributes +
                '}';
    }
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/pagemodel/TreeGrid.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,86 @@
package com.vci.starter.web.pagemodel;
import java.util.List;
/**
 * æ ‘表的展示对象,目前适配layui,请在数据量小的时候使用,数据量太大时不建议使用
 * @author weidy
 */
public class TreeGrid implements java.io.Serializable {
    private static final long serialVersionUID = 5593300788850918425L;
    /**
     * ä»£å·
     */
    private int code = 0;
    /**
     * é”™è¯¯æ¶ˆæ¯
     */
    private String msg;
    /**
     * æ•°æ®æè¿°ï¼Œå…¶ä¸­å¿…须要有treelevel,其中最顶级是-1,然后逐级增加,数据必须注意顺序
     */
    private List data;
    /**
     * æ€»æ•°
     */
    private int total = 0;
    /**
     * æè¿°ä¿¡æ¯
     */
    private String description;
    public TreeGrid(){
    }
    public TreeGrid(String msg){
        this.setMsg(msg);
        this.setCode(1);
    }
    public int getCode() {
        return code;
    }
    public void setCode(int code) {
        this.code = code;
    }
    public String getMsg() {
        return msg;
    }
    public void setMsg(String msg) {
        this.msg = msg;
    }
    public List getData() {
        return data;
    }
    public int getTotal() {
        return total;
    }
    public void setTotal(int total) {
        this.total = total;
    }
    public String getDescription() {
        return description;
    }
    public void setDescription(String description) {
        this.description = description;
    }
    public void setData(List data) {
        this.data = data;
    }
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/pagemodel/TreeQueryObject.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,203 @@
package com.vci.starter.web.pagemodel;
import java.util.Map;
/**
 * æ ‘形数据查询对象
 * @author weidy
 * @date 2019/10/11 6:42 PM
 */
public class TreeQueryObject implements java.io.Serializable{
    /**
     * ç¦æ­¢ä¿®æ”¹è¿™ä¸ªå€¼
     */
    private static final long serialVersionUID = -7570704940199743059L;
    /**
     * æŸ¥è¯¢æ¡ä»¶
     */
    private Map<String,String> conditionMap;
    /**
     * æ˜¯å¦å¤šé€‰
     */
    private boolean multipleSelect;
    /**
     * æ˜¯å¦æ˜¾ç¤ºå¤é€‰æ¡†
     */
    private boolean showCheckBox;
    /**
     * æŸ¥è¯¢æ‰€æœ‰çš„层级
     */
    private boolean queryAllLevel;
    /**
     * ä¸Šçº§ä¸šåŠ¡æ•°æ®ä¸»é”®
     */
    private String parentOid;
    /**
     * ä¸Šçº§ä¸šåŠ¡ç±»åž‹
     */
    private String parentBtmName;
    /**
     * å€¼çš„字段
     */
    private String valueField = "oid";
    /**
     * æ ‘节点的表达式
     */
    private String textField = "name";
    /**
     * ä¸Šçº§çš„字段的表达式
     */
    private String parentFieldName;
    /**
     * æ‰©å±•参数
     */
    private Map<String,String> extandParamsMap;
    /**
     * æŸ¥è¯¢æ‰€æœ‰çš„版本
     */
    private boolean queryAllRev;
    /**
     * æŽ’序的字段
     */
    private String sort;
    /**
     * æŽ’序的类型
     */
    private String order;
    public String getValueField() {
        return valueField;
    }
    public void setValueField(String valueField) {
        this.valueField = valueField;
    }
    public String getTextField() {
        return textField;
    }
    public void setTextField(String textField) {
        this.textField = textField;
    }
    public String getParentFieldName() {
        return parentFieldName;
    }
    public void setParentFieldName(String parentFieldName) {
        this.parentFieldName = parentFieldName;
    }
    public Map<String, String> getConditionMap() {
        return conditionMap;
    }
    public void setConditionMap(Map<String, String> conditionMap) {
        this.conditionMap = conditionMap;
    }
    public boolean isMultipleSelect() {
        return multipleSelect;
    }
    public void setMultipleSelect(boolean multipleSelect) {
        this.multipleSelect = multipleSelect;
    }
    public boolean isShowCheckBox() {
        return showCheckBox;
    }
    public void setShowCheckBox(boolean showCheckBox) {
        this.showCheckBox = showCheckBox;
    }
    public String getParentOid() {
        return parentOid;
    }
    public void setParentOid(String parentOid) {
        this.parentOid = parentOid;
    }
    public String getParentBtmName() {
        return parentBtmName;
    }
    public void setParentBtmName(String parentBtmName) {
        this.parentBtmName = parentBtmName;
    }
    public Map<String, String> getExtandParamsMap() {
        return extandParamsMap;
    }
    public void setExtandParamsMap(Map<String, String> extandParamsMap) {
        this.extandParamsMap = extandParamsMap;
    }
    public boolean isQueryAllLevel() {
        return queryAllLevel;
    }
    public void setQueryAllLevel(boolean queryAllLevel) {
        this.queryAllLevel = queryAllLevel;
    }
    public boolean isQueryAllRev() {
        return queryAllRev;
    }
    public void setQueryAllRev(boolean queryAllRev) {
        this.queryAllRev = queryAllRev;
    }
    public String getSort() {
        return sort;
    }
    public void setSort(String sort) {
        this.sort = sort;
    }
    public String getOrder() {
        return order;
    }
    public void setOrder(String order) {
        this.order = order;
    }
    @Override
    public String toString() {
        return "TreeQueryObject{" +
                "conditionMap=" + conditionMap +
                ", multipleSelect=" + multipleSelect +
                ", showCheckBox=" + showCheckBox +
                ", queryAllLevel=" + queryAllLevel +
                ", parentOid='" + parentOid + '\'' +
                ", parentBtmName='" + parentBtmName + '\'' +
                ", valueField='" + valueField + '\'' +
                ", textField='" + textField + '\'' +
                ", parentFieldName='" + parentFieldName + '\'' +
                ", extandParamsMap=" + extandParamsMap +
                ", queryAllRev=" + queryAllRev +
                ", sort='" + sort + '\'' +
                ", order='" + order + '\'' +
                '}';
    }
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/properties/CorsProperties.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,130 @@
package com.vci.starter.web.properties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import java.util.Arrays;
/**
 * è·¨åŸŸé…ç½®çš„属性
 * @author weidy
 */
@Component
@ConfigurationProperties(prefix = "cors")
public class CorsProperties {
    /**
     * å¼€å…³
     */
    private String enabled;
    /**
     * å…è®¸çš„域名
     */
    private String[] allowedOrigins;
    /**
     * å…è®¸çš„æ–¹æ³•
     */
    private String[] allowedMethods;
    /**
     * å…è®¸çš„头
     */
    private String[] allowedHeaders;
    /**
     * æš´éœ²çš„头
     */
    private String[] exposedHeaders;
    /**
     * å…è®¸çš„证书
     */
    private Boolean allowCredentials;
    /**
     * æ˜ å°„
     */
    private String mappings;
    /**
     * æœ€å¤§é‡
     */
    private Long maxAge;
    public String getEnabled() {
        return enabled;
    }
    public void setEnabled(String enabled) {
        this.enabled = enabled;
    }
    public String[] getAllowedOrigins() {
        return allowedOrigins;
    }
    public void setAllowedOrigins(String[] allowedOrigins) {
        this.allowedOrigins = allowedOrigins;
    }
    public String[] getAllowedMethods() {
        return allowedMethods;
    }
    public void setAllowedMethods(String[] allowedMethods) {
        this.allowedMethods = allowedMethods;
    }
    public String[] getAllowedHeaders() {
        return allowedHeaders;
    }
    public void setAllowedHeaders(String[] allowedHeaders) {
        this.allowedHeaders = allowedHeaders;
    }
    public String[] getExposedHeaders() {
        return exposedHeaders;
    }
    public void setExposedHeaders(String[] exposedHeaders) {
        this.exposedHeaders = exposedHeaders;
    }
    public Boolean getAllowCredentials() {
        return allowCredentials;
    }
    public void setAllowCredentials(Boolean allowCredentials) {
        this.allowCredentials = allowCredentials;
    }
    public String getMappings() {
        return mappings;
    }
    public void setMappings(String mappings) {
        this.mappings = mappings;
    }
    public Long getMaxAge() {
        return maxAge;
    }
    public void setMaxAge(Long maxAge) {
        this.maxAge = maxAge;
    }
    @Override
    public String toString() {
        return "CorsProperties{" +
                "enabled='" + enabled + '\'' +
                ", allowedOrigins=" + Arrays.toString(allowedOrigins) +
                ", allowedMethods=" + Arrays.toString(allowedMethods) +
                ", allowedHeaders=" + Arrays.toString(allowedHeaders) +
                ", exposedHeaders=" + Arrays.toString(exposedHeaders) +
                ", allowCredentials=" + allowCredentials +
                ", mappings='" + mappings + '\'' +
                ", maxAge=" + maxAge +
                '}';
    }
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/properties/VciSessionProperties.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,148 @@
package com.vci.starter.web.properties;
import com.vci.starter.web.annotation.config.VciConfigField;
import com.vci.starter.web.enumpck.DataBaseEnum;
import com.vci.starter.web.enumpck.LangCodeEnum;
import com.vci.starter.web.enumpck.SessionStorageTypeEnum;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
/**
 * ä¼šè¯ç›¸å…³çš„配置
 * @author weidy
 * @date 2020/2/27
 */
@Configuration
@ConfigurationProperties(prefix = "session")
public class VciSessionProperties {
    /**
     * ç³»ç»Ÿç©ºé—²æ—¶é—´ï¼Œæ ¹æ®ä¿å¯†è¦æ±‚默认是10分钟
     */
    private int sessionIdlTime = 10;
    /**
     * ä¼šè¯ä¿¡æ¯å­˜å‚¨çš„æ–¹å¼
     */
    private String sessionInfoStorageType = SessionStorageTypeEnum.REDIS.getValue();
    /**
     * æ•°æ®åº“的类型,是在ObjectService中设置的,
     */
    @VciConfigField(name = "databasePlatform",title = "数据库的类型",model = "public")
    private String databasePlatform = DataBaseEnum.ORACLE.getValue();
    /**
     * å¯åŠ¨æœåŠ¡æ—¶æ˜¯å¦æ¸…ç©ºä¼šè¯ä¿¡æ¯ï¼Œç™»å½•ä¸ºå½“å‰å¹³å°æŽ§åˆ¶æ—¶éœ€è¦æ·»åŠ ä¸ºtrue,登录是其他系统控制时设置为false
     */
    private Boolean clearSessionOnStart = false;
    /**
     * é»˜è®¤çš„语言编码
     */
    private String defaultLangCode = LangCodeEnum.ZH_CN.getValue();
    /**
     * æ˜¯å¦å¼€å¯å®¢æˆ·ç«¯æ£€æŸ¥
     */
    private boolean checkSessionTimeout;
    /**
     * å®¢æˆ·ç«¯åˆ¤æ–­è¶…时轮询时间,单位为秒
     */
    private int sessionInterval;
    /**
     * è¶…时提醒时间,单位为分钟
     */
    private int sessionRemind;
    /**
     * å®šæ—¶å™¨é‡Œæ˜¯å¦æ¸…除会话
     */
    private boolean deleteSessionInTimer = false;
    public int getSessionIdlTime() {
        return sessionIdlTime;
    }
    public void setSessionIdlTime(int sessionIdlTime) {
        this.sessionIdlTime = sessionIdlTime;
    }
    public String getSessionInfoStorageType() {
        return sessionInfoStorageType;
    }
    public void setSessionInfoStorageType(String sessionInfoStorageType) {
        this.sessionInfoStorageType = sessionInfoStorageType;
    }
    public String getDatabasePlatform() {
        return databasePlatform;
    }
    public void setDatabasePlatform(String databasePlatform) {
        this.databasePlatform = databasePlatform;
    }
    public String getDefaultLangCode() {
        return defaultLangCode;
    }
    public void setDefaultLangCode(String defaultLangCode) {
        this.defaultLangCode = defaultLangCode;
    }
    public boolean isClearSessionOnStart() {
        return clearSessionOnStart;
    }
    public void setClearSessionOnStart(boolean clearSessionOnStart) {
        this.clearSessionOnStart = clearSessionOnStart;
    }
    public boolean isCheckSessionTimeout() {
        return checkSessionTimeout;
    }
    public void setCheckSessionTimeout(boolean checkSessionTimeout) {
        this.checkSessionTimeout = checkSessionTimeout;
    }
    public int getSessionInterval() {
        return sessionInterval;
    }
    public void setSessionInterval(int sessionInterval) {
        this.sessionInterval = sessionInterval;
    }
    public int getSessionRemind() {
        return sessionRemind;
    }
    public void setSessionRemind(int sessionRemind) {
        this.sessionRemind = sessionRemind;
    }
    public boolean isDeleteSessionInTimer() {
        return deleteSessionInTimer;
    }
    public void setDeleteSessionInTimer(boolean deleteSessionInTimer) {
        this.deleteSessionInTimer = deleteSessionInTimer;
    }
    @Override
    public String toString() {
        return "VciSessionProperties{" +
                "sessionIdlTime=" + sessionIdlTime +
                ", sessionInfoStorageType='" + sessionInfoStorageType + '\'' +
                ", databasePlatform='" + databasePlatform + '\'' +
                ", clearSessionOnStart=" + clearSessionOnStart +
                ", defaultLangCode='" + defaultLangCode + '\'' +
                '}';
    }
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/service/BaseService.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,10 @@
package com.vci.starter.web.service;
/**
 * åŸºç¡€çš„æœåŠ¡
 * @author weidy
 * @date 2019/12/10 6:17 PM
 */
public class BaseService<T> {
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/service/LanguageServiceI.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,27 @@
package com.vci.starter.web.service;
/**
 * å¤šè¯­è¨€çš„æœåŠ¡æŽ¥å£
 * @author weidy
 * @date 2020/1/29
 */
public interface LanguageServiceI {
    /**
     * èŽ·å–å¤šè¯­è¨€çš„å‰ç¼€
     * @return ä¸ºå½“前类所在的包的名称
     */
    default String getMsgPrefix(){
        return getClass().getPackage().getName();
    }
    /**
     * èŽ·å–å¤šè¯­è¨€ã€‚é»˜è®¤ä¸ºåŒ…å.后缀的方式,比如com.vci.xxx
     * @param subfix åŽç¼€
     * @return åŒ…名.后缀的方式,比如com.vci.xxx
     */
    default String getMsg(String subfix){
        return getMsgPrefix() + "." + subfix;
    }
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/service/VciSecretServiceI.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,43 @@
package com.vci.starter.web.service;
import com.vci.starter.web.enumpck.UserSecretEnum;
import com.vci.starter.web.pagemodel.SessionInfo;
import com.vci.starter.web.util.VciBaseUtil;
import org.apache.commons.lang3.StringUtils;
/**
 * å¯†çº§æœåŠ¡
 * @author weidy
 * @date 2020/3/11
 */
public interface VciSecretServiceI {
    /**
     * æŸ¥è¯¢æ•°æ®æ—¶çš„密级过滤sql
     * @return é»˜è®¤å°äºŽç­‰äºŽå½“前用户的密级值
     */
    default String getLessThanUserSecretSql(){
        SessionInfo sessionInfo = VciBaseUtil.getCurrentUserSessionInfoNotException();
        if(sessionInfo!=null) {
            return sessionInfo.getUserSecret();
        }
        return "";
    }
    /**
     * æ ¡éªŒç”¨æˆ·çš„密级是否有权限查看当前的数据密级
     * @param dataSecret æ•°æ®å¯†çº§çš„值
     * @return é»˜è®¤å°äºŽç­‰äºŽå½“前用户的密级值即可
     */
    default boolean checkUserSecret(int dataSecret){
        SessionInfo sessionInfo = VciBaseUtil.getCurrentUserSessionInfoNotException();
        if(sessionInfo!=null) {
            if(StringUtils.isBlank(sessionInfo.getUserSecret())){
                sessionInfo.setUserSecret(UserSecretEnum.NONE.getValue() +"");
            }
            return VciBaseUtil.getInt(sessionInfo.getUserSecret())>= dataSecret;
        }
        return false;
    }
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/toolmodel/DateConverter.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,307 @@
package com.vci.starter.web.toolmodel;
import com.vci.starter.web.constant.RegExpConstant;
import com.vci.starter.web.exception.VciBaseException;
import com.vci.starter.web.util.VciDateUtil;
import org.apache.commons.lang3.StringUtils;
import java.beans.PropertyEditorSupport;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
 * æ—¶é—´å¤„理,前台json传输过来的内容的时候
 * @author weidy
 */
public class DateConverter extends PropertyEditorSupport {
    /**
     *时间格式
     */
    private DateFormat dateFormat;
     /**
     *时间内容的长度
     */
    private  int exactDateLength;
    /**
     * å…·ä½“的值
     */
    private Date value;
    public DateFormat getDateFormat() {
        return dateFormat;
    }
    public void setDateFormat(DateFormat dateFormat) {
        this.dateFormat = dateFormat;
    }
    public int getExactDateLength() {
        return exactDateLength;
    }
    public void setExactDateLength(int exactDateLength) {
        this.exactDateLength = exactDateLength;
    }
    public Date getValue() {
        return value;
    }
    public void setValue(Date value) {
        this.value = value;
    }
    /**
     *将字符串转换为日期格式
     * @param text å­—符串
     * @throws VciBaseException è½¬æ¢å‡ºé”™çš„æ—¶å€™æŠ›å‡ºå¼‚常
     */
    public void setAsText(String text) throws VciBaseException {
        if (StringUtils.isBlank(text)) {
            setValue(null);
        }else {
            text = text.trim();
            //防止有中文的情况
            text = text.replace("å¹´","-").replace("月","-").replace("日","").replace("时",":").replace("分",":");
            String pattern="\\d{2,4}([^\\d]?)\\d{1,2}\\1\\d{1,2}( \\d{1,2}([^\\d])\\d{1,2})?";
            Pattern r = Pattern.compile(pattern);
            Matcher m = r.matcher(text);
            if(m.find()){
                //说明是符合要求的
                String dateSplit = m.group(1);
                //中间的空格是第二部分
                String timeSplit = m.group(3);
                String formateStr = String.format("yyyy%sMM%sdd",dateSplit,dateSplit);
                if(StringUtils.isNotBlank(timeSplit)){
                    //有时间
                    String timeStr = text.substring(text.indexOf(" "));
                    String[] split = timeStr.split(timeSplit);
                    if(split.length == 2){
                        formateStr += String.format(" HH%smm",timeSplit);
                    }
                    if(split.length>2){
                        formateStr += String.format(" HH%smm%sss",timeSplit,timeSplit);
                    }
                    if(timeStr.contains(".")){
                        //毫秒
                        formateStr += ".SSS";
                    }
                }
                String yearMD = text.contains(" ")?text.substring(0, text.indexOf(" ")):text;
                if(StringUtils.isNotBlank(dateSplit)){
                    //说明有日期的分割符
                    String year = text.substring(0, text.indexOf(dateSplit));
                    if(StringUtils.isNotBlank(year) && year.length()==2){
                        formateStr = formateStr.replace("yyyy","yy");
                    }
                    String[] split = yearMD.split(dateSplit);
                    if(split.length == 2){
                        formateStr = formateStr.replace("dd","");
                    }
                }else{
                    if(!text.matches(RegExpConstant.NUMBER)){
                        //说明还是有符号,但是不符合要求而已
                        if(text.length() == 5){
                            formateStr = formateStr.replace("yyyyMMdd","yy"+text.substring(2,3) + "MM");
                        }
                        if(text.length() == 7){
                            formateStr = formateStr.replace("yyyyMMdd","yyyy"+text.substring(4,5) + "MM");
                        }
                    }else {
                        //如果只有日期
                        if (text.length() == 2 && text.matches(RegExpConstant.NUMBER)) {
                            formateStr = "yy";
                        } else if (text.length() == 4 && text.matches(RegExpConstant.NUMBER)) {
                            formateStr = "yyyy";
                        } else if (text.length() == 6 && text.matches(RegExpConstant.NUMBER)) {
                            formateStr = "yyyyMM";
                        } else {
                            if (StringUtils.isNotBlank(yearMD) && yearMD.length() < 6) {
                                formateStr = formateStr.replace("yyyy", "yy");
                            }
                        }
                    }
                }
                //只有时间,我们是没办法转换的
                SimpleDateFormat simpleDateFormat = new SimpleDateFormat(formateStr);
                try {
                    setValue(simpleDateFormat.parse(text));
                } catch (ParseException e) {
                    //是看看短年份
                    formateStr= formateStr.replace("yyyy","yy");
                    simpleDateFormat = new SimpleDateFormat(formateStr);
                    try {
                        setValue(simpleDateFormat.parse(text));
                    } catch (ParseException ex) {
                        //如果只有日期
                        if(text.length() == 2 && text.matches(RegExpConstant.NUMBER)){
                            formateStr = "yy";
                        }
                        throw new VciBaseException("不能格式化日期: {0}", new String[]{text}, e);
                    }
                }
            }else{
                throw new VciBaseException("不是合格的时间格式字符串,{0}", new String[]{text});
            }
//            if(text.contains("å¹´") || text.contains("月") || text.contains("日")
//            ||text.contains("时") || text.contains("分") || text.contains("秒") || text.contains("毫秒")
//            ||text.contains("周") || text.contains("礼拜") || text.contains("天")){
//                //1. åªæœ‰å¹´
//                if(text.indexOf("å¹´") == text.length()-1){
//                    this.exactDateLength = text.length();
//                    if(text.length() ==3) {
//                        this.dateFormat = new SimpleDateFormat("yyå¹´");
//                    }
//                }
//            }
//            if(text.contains("/")) {
//                if ( text.trim().length() == 19) {
//                    this.exactDateLength = 19;
//                    this.dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
//                } else if (text.indexOf(".") > -1 && text.length() > 20) {
//                    this.exactDateLength = 23;
//                    text = fillNano(text);
//                    this.dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss.SSS");
//                } else if (text.length() == 17) {
//                    this.exactDateLength = 17;
//                    this.dateFormat = new SimpleDateFormat("yy/MM/dd HH:mm:ss");
//                } else if ( text.indexOf(".") > -1 && text.length() > 17) {
//                    this.exactDateLength = 21;
//                    text = fillNano(text);
//                    this.dateFormat = new SimpleDateFormat("yy/MM/dd HH:mm:ss.SSS");
//                } else if (text.length() == 10) {
//                    this.exactDateLength = 10;
//                    this.dateFormat = new SimpleDateFormat("yyyy/MM/dd");
//                } else if (text.length() >=8 && text.length() < 10 ) {
//                    //2018/1/1  æˆ–者18/01/01,18/1/1
//                    if(text.substring(0,text.indexOf("/")).length() == 4){
//                        this.dateFormat = new SimpleDateFormat("yyyy/MM/dd");
//                    }else{
//                        this.dateFormat = new SimpleDateFormat("yy/MM/dd");
//                    }
//                    this.exactDateLength = text.length();
//                }else{
//                    this.dateFormat = new SimpleDateFormat("yy/MM/dd");
//                    this.exactDateLength = text.length();
//                }
//            }else if(text.contains("-")) {
//                if (text.length() == 19) {
//                    this.exactDateLength = 19;
//                    this.dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//                } else if ( text.indexOf(".") > -1 && text.length() > 20) {
//                    this.exactDateLength = 23;
//                    text = fillNano(text);
//                    this.dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
//                } else if (text.length() == 17) {
//                    this.exactDateLength = 17;
//                    this.dateFormat = new SimpleDateFormat("yy-MM-dd HH:mm:ss");
//                } else if ( text.length() == 8) {
//                    this.exactDateLength = 8;
//                    this.dateFormat = new SimpleDateFormat("yy-MM-dd");
//                } else if (text.length() == 10) {
//                    this.exactDateLength = 10;
//                    this.dateFormat = new SimpleDateFormat("yyyy-MM-dd");
//                }else if (text.length() >=8 && text.length() < 10 ) {
//                    //2018-1-1  æˆ–者18-01-01,18/1/1
//                    if(text.substring(0,text.indexOf("-")).length() == 4){
//                        this.dateFormat = new SimpleDateFormat("yyyy-MM-dd");
//                    }else{
//                        this.dateFormat = new SimpleDateFormat("yy-MM-dd");
//                    }
//                    this.exactDateLength = text.length();
//                }else{
//                    this.dateFormat = new SimpleDateFormat("yy-MM-dd");
//                    this.exactDateLength = text.length();
//                }//先弄这么多,不够再添加
//            }else if(text.matches(RegExpConstant.NUMBER)){
//
//            }else{
//                this.exactDateLength = 19;
//                this.dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//            }
//            //if ((text != null) && (this.exactDateLength >= 0)&& (text.length() != this.exactDateLength)) {
//            //    throw new IllegalArgumentException("不能初始化时间,因为内容不到" + this.exactDateLength + "长度");
//        //    }
//            try {
//                setValue(VciDateUtil.str2Date(VciDateUtil.date2Str(this.dateFormat.parse(text),VciDateUtil.DateTimeMillFormat),VciDateUtil.DateTimeMillFormat));
//                //无论界面是什么格式,我们都转化为"yyyy-MM-dd HH:mm:ss.SSS"这样可以统一后台的内容
//            } catch (ParseException ex) {
//                throw new VciBaseException("不能格式化日期: "+ ex.getMessage(), new Object[0],ex);
//            } catch (Exception e) {
//                throw new VciBaseException("不能格式化日期: "+ e.getMessage(), new Object[0], e);
//            }
        }
    }
    /**
     * æŠ›å¼ƒæ¯«ç§’
     * @param text å­—符串
     * @return æ²¡æœ‰æ¯«ç§’的时间值
     */
    private String fillNano(String text){
        String nano = text.substring(text.lastIndexOf(".") + 1);
        if(nano.length() < 3){
            for(int i = 0 ; i < (3-nano.length()) ; i ++){
                nano += "0";
            }
        }
        return text.substring(0,text.lastIndexOf(".")) + "." + nano;
    }
    public static void main(String[] args) {
        List<String> list = new ArrayList<String>(){{
            add("2020-11-12 12:12:03");
            add("2020-1-2 2:2:3");
            add("2020-11-12 12:12:03.232");
            add("2020/11/12 12:12:03");
            add("2020/1/2 2:2:3");
            add("2020/11/12 12:12:03.232");
            add("20/11/12 12:12:03");
            add("20/1/2 2:2:3");
            add("20/11/12 12:12:03.232");
            add("2020");
            add("2020-11");
            add("202011");
            add("12:02:12");
            add("2:2:3");
            add("20201112");
            add("202012");
            add("202012");
            add("2020å¹´11月12日 12时12分03秒");
            add("2020å¹´1月2日 2:2:3");
            add("2020å¹´11月12日 12时12分03秒232毫秒");
        }};
        list.stream().forEach(t->{
            try {
                DateConverter dateConverter = new DateConverter();
                dateConverter.setAsText(t);
                System.out.println("转换前:" + t + "; è½¬æ¢åŽ:" + VciDateUtil.date2Str(dateConverter.getValue(), VciDateUtil.DateTimeMillFormat));
            }catch (Throwable e){
                e.printStackTrace();
            }
        });
    }
    /**
     * èŽ·å–æ—¥æœŸè½¬æ¢ä¸ºå­—ç¬¦ä¸²çš„å€¼
     * @return å­—符串
     */
    public String getAsText(String dateFormat) {
        Date value = (Date) getValue();
        if(StringUtils.isEmpty(dateFormat)){
            dateFormat= VciDateUtil.DateTimeMillFormat;
        }
        return value != null ? new SimpleDateFormat(dateFormat).format(value) : "";
    }
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/toolmodel/String2DateConverterForSpringMvc.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,26 @@
package com.vci.starter.web.toolmodel;
import org.springframework.core.convert.converter.Converter;
import org.springframework.lang.Nullable;
import java.util.Date;
/**
 * é’ˆå¯¹springmvc设置的日期的转换器
 * @author weidy
 * @date 2019/12/3 4:17 PM
 */
public class String2DateConverterForSpringMvc implements Converter<String, Date> {
    /**
     * è½¬æ¢å­—符串到日期类型
     * @param source å­—符串
     * @return æ—¥æœŸå¯¹è±¡
     */
    @Nullable
    @Override
    public Date convert(String source) {
        DateConverter dateConverter = new DateConverter();
        dateConverter.setAsText(source);
        return dateConverter.getValue();
    }
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/toolmodel/StringEscapeEditor.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,75 @@
package com.vci.starter.web.toolmodel;
import org.springframework.web.util.HtmlUtils;
import org.springframework.web.util.JavaScriptUtils;
import java.beans.PropertyEditorSupport;
/**
 * ä¸Žspring mvc的@InitBinder结合
 * ç”¨äºŽé˜²æ­¢XSS攻击
 * å°†Html中包含的js等相关的内容转换
 * @author weidy
 *
 */
public class StringEscapeEditor extends PropertyEditorSupport {
    /**
     * è¦ç¼–码的HTML内容
     */
    private boolean escapeHTML;// ç¼–码HTML
    /**
     * è¦ç¼–码的js
     */
    private boolean escapeJavaScript;// ç¼–码javascript
    /**
     * æž„造方法
     */
    public StringEscapeEditor() {
        super();
    }
    /**
     * æž„造方法
     * @param escapeHTML è¦ç¼–码的html
     * @param escapeJavaScript è¦ç¼–码的JS
     */
    public StringEscapeEditor(boolean escapeHTML, boolean escapeJavaScript) {
        super();
        this.escapeHTML = escapeHTML;
        this.escapeJavaScript = escapeJavaScript;
    }
    /**
     * æ‰§è¡Œè½¬æ¢
     * @return ç¼–码后的内容
     */
    @Override
    public String getAsText() {
        Object value = getValue();
        return value != null ? value.toString() : "";
    }
    /**
     * æ‰§è¡Œä¸“å®¶
     * @param text è½¬æ¢é’±çš„值
     * @throws IllegalArgumentException è½¬æ¢çš„过程出现了错误会抛出异常
     */
    @Override
    public void setAsText(String text) throws IllegalArgumentException {
        if (text == null) {
            setValue(null);
        } else {
            String value = text;
            if (escapeHTML) {
                value = HtmlUtils.htmlEscape(value);
            }
            if (escapeJavaScript) {
                value = JavaScriptUtils.javaScriptEscape(value);
            }
            setValue(value);
        }
    }
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/util/ApplicationContextProvider.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,107 @@
package com.vci.starter.web.util;
import com.vci.starter.web.annotation.controller.VciUnCheckRight;
import com.vci.starter.web.annotation.log.VciUnLog;
import com.vci.starter.web.autoconfigure.AppAutoConfigure;
import com.vci.starter.web.pagemodel.BaseResult;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
 * spring的上下文工具,
 * æ³¨æ„springmvc中的controller不应该在这里获取,因为springmvc只应该被前端调用
 * æ²¡æœ‰ä½¿ç”¨springboot的main函数里设置并获取是因为可能会让多个服务合并到一起启动
 * @author weidy
 * @date 2019/10/31 9:02 AM
 */
@RestController
@RequestMapping("/application")
public class ApplicationContextProvider implements ApplicationContextAware {
    /**
     * æœåŠ¡çš„é…ç½®
     */
    @Autowired
    private AppAutoConfigure appAutoConfigure;
    /**
     * åº”用的上下文
     */
    private static ApplicationContext applicationContext ;
    /**
     * è®¾ç½®åº”用的上下文
     * @param applicationContext ä¸Šä¸‹æ–‡
     * @throws BeansException å‡ºçŽ°é”™è¯¯æ—¶éœ€è¦æŠ›å‡ºå¼‚å¸¸ç»™spring容器
     */
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        ApplicationContextProvider.applicationContext = applicationContext;
    }
    /**
     * èŽ·å–åº”ç”¨çš„ä¸Šä¸‹æ–‡
     * @return ä¸Šä¸‹æ–‡
     */
    public static ApplicationContext getApplicationContext() {
        return applicationContext;
    }
    /**
     * èŽ·å–å¯¹è±¡
     * @param name bean的名称
     * @return Object bean的对象
     * @throws BeansException å¦‚果不存在会抛出异常
     */
    public static Object getBean(String name) throws BeansException {
        return applicationContext.getBean(name);
    }
    /**
     * èŽ·å–å¯¹è±¡
     * @param c bean的接口类
     * @param <T> bean所属类的类型
     * @return bean对象
     * @throws BeansException å¦‚果不存在会抛出异常
     */
    public static <T> T getBean(Class<T> c) throws BeansException{
        return applicationContext.getBean(c);
    }
    /**
     * å…³æœº
     * @return æ‰§è¡Œå®Œæˆ
     */
    @PostMapping("/shutDownContext")
    @VciUnLog
    @VciUnCheckRight
    public BaseResult shutDownContext(String privateKey){
        if( appAutoConfigure.getPrivateTokenKey().equalsIgnoreCase(privateKey)) {
            ConfigurableApplicationContext ctx = (ConfigurableApplicationContext) applicationContext;
            ctx.close();
            return BaseResult.success("关闭服务成功");
        }else{
            return BaseResult.fail("您没有权限关闭服务");
        }
    }
    /**
     * æ£€æŸ¥æ˜¯å¦å®Œæˆ
     * @return è°ƒç”¨å°±è¯´æ˜ŽæˆåŠŸäº†
     */
    @PostMapping("/checkOnline")
    @VciUnLog
    @VciUnCheckRight
    public BaseResult checkOnline(){
        return BaseResult.success("启动完成");
    }
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/util/BeanUtil.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,222 @@
package com.vci.starter.web.util;
import com.vci.starter.web.toolmodel.DateConverter;
import org.springframework.cglib.beans.BeanCopier;
import org.springframework.cglib.core.Converter;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
/**
 * å¯¹è±¡æ‹·è´å·¥å…·ç±»
 * ä½¿ç”¨çš„cglib的beancopier,因为使用了转换器,所以性能比没有使用转换器的要低一些
 * ä¼šè‡ªåŠ¨åˆ¤æ–­æ˜¯å¦éœ€è¦è½¬æ¢å™¨ï¼Œå½“æœ‰å±žæ€§ç›¸åŒï¼Œç±»åž‹ä¸åŒï¼Œå’Œæœ‰å¯¹è±¡ç±»åž‹ï¼Œmap,list等集合类型时才需要转换器
 * @author weidy
 * @date 2019/11/23 9:22 AM
 */
public class BeanUtil {
    /**
     * å­˜æ”¾æ‹·è´å¯¹è±¡çš„缓存
     */
    private static final ConcurrentMap<String,BeanCopier> beanCopierMap = new ConcurrentHashMap<>();
    /**
     * èŽ·å–ç±»æ‹·è´çš„å¯¹è±¡
     * @param source æºå¯¹è±¡ç±»
     * @param target ç›®æ ‡å¯¹è±¡ç±»
     * @param useConverter æ˜¯å¦ä½¿ç”¨è½¬æ¢å™¨
     * @return æ‹·è´å¯¹è±¡
     */
    public static BeanCopier getBeanCopier(Class<?> source, Class<?> target,boolean useConverter) {
        String beanCopierKey = generateBeanKey(source, target);
        if (beanCopierMap.containsKey(beanCopierKey)) {
            return beanCopierMap.get(beanCopierKey);
        } else {
            BeanCopier beanCopier = BeanCopier.create(source, target, useConverter);
            beanCopierMap.putIfAbsent(beanCopierKey, beanCopier);
        }
        return beanCopierMap.get(beanCopierKey);
    }
    /**
     * ç”Ÿæˆä¸¤ä¸ªç±»çš„key,用于存放到缓存之中
     * @param source æºå¯¹è±¡ç±»åž‹
     * @param target ç›®æ ‡å¯¹è±¡ç±»
     * @return ä¸¤ä¸ªç±»çš„名称连接到一起后的名字
     */
    public static String generateBeanKey(Class<?> source, Class<?> target) {
        return source.getName() + "@" + target.getName();
    }
    /**
     * ä¸¤ä¸ªå¯¹è±¡ä¹‹é—´è½¬æ¢
     * @param source æºå¯¹è±¡
     * @param target ç›®æ ‡å¯¹è±¡
     * @param useConvert æ˜¯å¦ä½¿ç”¨é»˜è®¤çš„转换器,请在出现属性名称相同而类型不同,或者有对象类型,集合属性时才转换
     */
    public static void convert(Object source,Object target,boolean useConvert){
        if(source != null && target !=null){
            BeanCopier beanCopier = getBeanCopier(source.getClass(),target.getClass(),useConvert);
            beanCopier.copy(source,target,useConvert?new DeepCopyConverter(target):null);
        }
    }
    /**
     * ä¸¤ä¸ªå¯¹è±¡ä¹‹é—´è½¬æ¢
     * @param source æºå¯¹è±¡
     * @param target ç›®æ ‡å¯¹è±¡
     * @return ç›®æ ‡å¯¹è±¡
     */
    public static void convert(Object source,Object target){
        convert(source,target,true);
    }
    /**
     * æ·±åº¦æ‹·è´è½¬æ¢å™¨
     */
    public static class DeepCopyConverter implements Converter {
        /**
         * ç›®æ ‡å¯¹è±¡
         */
        private Object target;
        /**
         * æž„造方法
         * @param target ç›®æ ‡å¯¹è±¡
         */
        public DeepCopyConverter(Object target) {
            this.target = target;
        }
        /**
         * æ‰§è¡Œæ‹·è´
         * @param value æºå¯¹è±¡çš„属性的值
         * @param targetClazz ç›®æ ‡å¯¹è±¡çš„属性的类
         * @param methodName set方法的名字
         * @return è½¬æ¢åŽçš„值
         */
        @Override
        public Object convert(Object value, Class targetClazz, Object methodName) {
            if (value instanceof List) {
                List values = (List) value;
                List retList = new ArrayList<>(values.size());
                copyForCollection(values,retList,methodName);
                return retList;
            } else if(value instanceof Set){
                Set values = (Set) value;
                Set retSet = new HashSet<>();
                copyForCollection(values,retSet,methodName);
            } else if(value instanceof Vector){
                Vector values = (Vector)value;
                Vector retVector = new Vector();
                copyForCollection(values,retVector,methodName);
            }else if (value instanceof Map) {
                Map values = (Map)value;
                Map retMap = new HashMap();
                for (final Object key : values.keySet()) {
                    Object mapValue = values.get(key);
                    String tempFieldName = methodName.toString().replace("set",
                            "");
                    String fieldName = tempFieldName.substring(0, 1)
                            .toLowerCase() + tempFieldName.substring(1);
                    Class clazz = ClassUtil.getElementType(target.getClass(), fieldName);
                    Object targetAttr = null;
                    try{
                        targetAttr = clazz.newInstance();
                    }catch (Throwable e){
                        //新的对象的属性初始化出错
                    }
                    BeanUtil.convert(mapValue, targetAttr);
                    retMap.put(key,targetAttr);
                }
            } else if (!ClassUtil.isPrimitive(targetClazz)) {
                //这个是对象类型
                Object targetAttr = null;
                try{
                    targetAttr = targetClazz.newInstance();
                }catch (Throwable e){
                    //新的对象属性初始化出错
                }
                BeanUtil.convert(value, targetAttr);
                return targetAttr;
            }
            if(value instanceof Boolean && targetClazz.equals(String.class)){
                //从boolean拷贝到string
                return String.valueOf(value);
            }
            if(value instanceof String && (targetClazz.equals(Boolean.class)
                    || targetClazz.equals(boolean.class))){
                //从String拷贝到boolean
                if("true".equalsIgnoreCase((String)value)){
                    return true;
                }else{
                    return false;
                }
            }
            if(value instanceof Date && targetClazz.equals(String.class)){
                //时间格式
                return VciDateUtil.date2Str((Date)value,VciDateUtil.DateTimeMillFormat);
            }
            if(value instanceof String && targetClazz.equals(Date.class)){
                //转换
                DateConverter dateConverter = new DateConverter();
                dateConverter.setAsText((String)value);
                return dateConverter.getValue();
            }
            return value;
        }
        /**
         * å¤„理集合属性
         * @param sourceCollection æºå¯¹è±¡ä¸­é›†åˆå±žæ€§çš„的值
         * @param targetCollection ç›®æ ‡å¯¹è±¡çš„集合属性的值
         * @param methodName setter方法
         */
        private void copyForCollection(Collection<?> sourceCollection,Collection targetCollection,Object methodName){
            for (final Object source : sourceCollection) {
                if(source instanceof Collection){
                    List<Object> targetValues = new ArrayList<>();
                    copyForCollection((Collection<?>)source,targetValues,methodName);
                    targetCollection.add(targetValues);
                }else if(source instanceof Map){
                    String tempFieldName = methodName.toString().replace("set",
                            "");
                    String fieldName = tempFieldName.substring(0, 1)
                            .toLowerCase() + tempFieldName.substring(1);
                    Class clazz = ClassUtil.getElementType(target.getClass(), fieldName);
                    Object targetAttr = null;
                    try {
                        targetAttr = clazz.newInstance();
                    } catch (Throwable e) {
                        //新的对象的属性初始化出错
                    }
                    Map map = (Map) source;
                    for(Object key : map.keySet()){
                        VciBaseUtil.setValueForField(key.toString(),targetAttr,VciBaseUtil.getStringValueFromObject(map.get(key)));
                    }
                    targetCollection.add(targetAttr);
                }else  {
                    String tempFieldName = methodName.toString().replace("set",
                            "");
                    String fieldName = tempFieldName.substring(0, 1)
                            .toLowerCase() + tempFieldName.substring(1);
                    Class clazz = ClassUtil.getElementType(target.getClass(), fieldName);
                    Object targetAttr = null;
                    try {
                        targetAttr = clazz.newInstance();
                    } catch (Throwable e) {
                        //新的对象的属性初始化出错
                    }
                    BeanUtil.convert(source, targetAttr);
                    targetCollection.add(targetAttr);
                }
            }
        }
    }
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/util/BeanUtilForVCI.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,258 @@
package com.vci.starter.web.util;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.CollectionUtils;
import java.lang.reflect.Field;
import java.util.*;
/**
 * ä¸šåŠ¡ç±»åž‹ä¸“ç”¨çš„æ‹·è´å·¥å…·ï¼Œè¿™ä¸ªæ˜¯æµ…æ‹·è´ï¼Œ
 * @author weidy
 * @date 2022-1-18
 */
public class BeanUtilForVCI {
    /**
     * æ—¥å¿—
     */
    private static Logger logger = LoggerFactory.getLogger(BeanUtilForVCI.class);
    /**
     * æ‹·è´æ•°æ®
     * å¤§å°å†™å¯ä»¥å¿½ç•¥
     * ä¸‹åˆ’线 _ è¢«å¿½ç•¥
     * null和空字符串的也会被覆盖
     * @param source æ¥æºå±žæ€§
     * @param target ç›®æ ‡å±žæ€§
     */
    public static void copyPropertiesIgnoreCase(Object source, Object target) {
        copyPropertiesIgnoreCase(source,target,false);
    }
    /**
     * æ‹·è´å±žæ€§
     * @param source æºå¯¹è±¡
     * @param target ç›®æ ‡å¯¹è±¡
     * @param fieldMap å±žæ€§çš„æ˜ å°„
     */
    public static void copyPropertiesIgnoreCase(Object source,Object target,Map<String/**原对象的属性名字**/,String/**目标对象的属性名称**/> fieldMap){
        copyPropertiesIgnoreCase(source,target,false,fieldMap);
    }
    /**
     * æ‹·è´æ•°æ®
     * å¤§å°å†™å¯ä»¥å¿½ç•¥
     * ä¸‹åˆ’线 _ è¢«å¿½ç•¥
     * @param source æ¥æºå±žæ€§
     * @param target ç›®æ ‡å±žæ€§
     * @param ignoreNull æ˜¯å¦å¿½ç•¥æŽ§åˆ¶
     */
    public static void copyPropertiesIgnoreCase(Object source,Object target,boolean ignoreNull){
        copyPropertiesIgnoreCase(source, target, ignoreNull,null);
    }
    /**
     * æ‹·è´æœ¬ä½“的属性内容
     * @param source æ¥æºå¯¹è±¡
     * @param target ç›®æ ‡å¯¹è±¡
     */
    public static void copyDeclaredIgnoreCase(Object source,Object target){
        copyDeclaredIgnoreCase(source,target,false);
    }
    /**
     * æ‹·è´æœ¬ä½“的属性内容
     * @param source æ¥æºå¯¹è±¡
     * @param target ç›®æ ‡å¯¹è±¡
     * @param ignoreNull  å¿½ç•¥ç©ºå€¼çš„属性
     */
    public static void copyDeclaredIgnoreCase(Object source,Object target,boolean ignoreNull){
        copyDeclaredIgnoreCase(source,target,ignoreNull,null);
    }
    /**
     * æ‹·è´æœ¬ä½“的属性内容
     * @param source æ¥æºå¯¹è±¡
     * @param target ç›®æ ‡å¯¹è±¡
     * @param ignoreNull å¿½ç•¥ç©ºå€¼çš„属性
     * @param fieldMap å­—段的映射
     */
    public static void copyDeclaredIgnoreCase(Object source,Object target,boolean ignoreNull,Map<String/**原对象的属性名字**/,String/**目标对象的属性名称**/> fieldMap){
        copyDeclaredIgnoreCase(source,target,ignoreNull,fieldMap,null);
    }
    /**
     * æ‹·è´æœ¬ä½“的属性内容
     * @param source æ¥æºå¯¹è±¡
     * @param target ç›®æ ‡å¯¹è±¡
     * @param ignoreNull å¿½ç•¥ç©ºå€¼çš„属性
     * @param fieldMap å­—段的映射
     * @param ignoreField å¿½ç•¥å­—段
     */
    public static void copyDeclaredIgnoreCase(Object source,Object target,boolean ignoreNull,Map<String/**原对象的属性名字**/,String/**目标对象的属性名称**/> fieldMap,Collection<String> ignoreField){
        Map<String, Field> sourceMap = CacheFieldMap.getDeclaredFieldMap(source.getClass());
        Map<String, Field> targetMap = CacheFieldMap.getDeclaredFieldMap(target.getClass());
        copyPropertiesIgnoreCase(source,target,ignoreNull,fieldMap,ignoreField,sourceMap,targetMap);
    }
    /**
     * æ‹·è´æ•°æ®
     * å¤§å°å†™å¯ä»¥å¿½ç•¥
     * ä¸‹åˆ’线 _ è¢«å¿½ç•¥
     * @param source æ¥æºå±žæ€§
     * @param target ç›®æ ‡å±žæ€§
     * @param ignoreNull æ˜¯å¦å¿½ç•¥æŽ§åˆ¶
     */
    public static void copyPropertiesIgnoreCase(Object source, Object target, boolean ignoreNull, Map<String/**原对象的属性名字**/,String/**目标对象的属性名称**/> fieldMap, Collection<String> ignoreField) {
        Map<String, Field> sourceMap = CacheFieldMap.getFieldMap(source.getClass());
        Map<String, Field> targetMap = CacheFieldMap.getFieldMap(target.getClass());
        copyPropertiesIgnoreCase(source,target,ignoreNull,fieldMap,ignoreField,sourceMap,targetMap);
    }
    /**
     * æ‹·è´æ•°æ®
     * å¤§å°å†™å¯ä»¥å¿½ç•¥
     * ä¸‹åˆ’线 _ è¢«å¿½ç•¥
     * @param source æ¥æºå±žæ€§
     * @param target ç›®æ ‡å±žæ€§
     * @param ignoreNull æ˜¯å¦å¿½ç•¥æŽ§åˆ¶
     */
    public static void copyPropertiesIgnoreCase(Object source, Object target, boolean ignoreNull,
                                                Map<String/**原对象的属性名字**/,String/**目标对象的属性名称**/> fieldMap, Collection<String> ignoreField,
                                                Map<String, Field> sourceMap,Map<String, Field> targetMap ) {
        if(fieldMap == null){
            fieldMap = new HashMap<>();
        }
        Map<String, String> finalFieldMap = fieldMap;
        targetMap.values().forEach((it) -> {
            boolean not = false;
            if(ignoreField!=null &&  ignoreField.contains(it.getName())){
                not = true;
            }
            if(!not) {
                String itFieldName = it.getName().toLowerCase().replace("_", "");
                itFieldName = finalFieldMap.getOrDefault(itFieldName, itFieldName);
                Field field = sourceMap.getOrDefault(itFieldName, null);
                if (field != null) {
                    it.setAccessible(true);
                    field.setAccessible(true);
                    try {
                        //忽略null和空字符串
                        //处理boolean和String
                        String sourceClassName = field.getClass().getName();
                        String targetClassName = it.getClass().getName();
                        if (((sourceClassName.equalsIgnoreCase(Boolean.class.getName())
                                || sourceClassName.equalsIgnoreCase(boolean.class.getName())
                        ) && targetClassName.equalsIgnoreCase(String.class.getName()))
                                || ((targetClassName.equalsIgnoreCase(Boolean.class.getName())
                                || targetClassName.equalsIgnoreCase(boolean.class.getName()))
                                && sourceClassName.equalsIgnoreCase(String.class.getName()))) {
                            if (targetClassName.equalsIgnoreCase(String.class.getName())) {
                                it.set(target, String.valueOf((Boolean) field.get(source)));
                            } else {
                                it.set(target, Boolean.valueOf((String) field.get(source)));
                            }
                        } else {
                            if (!ignoreNull) {
                                it.set(target, field.get(source));
                            } else {
                                //需要判断是否为空
                                Object sourceValue = field.get(source);
                                if (sourceValue != null && StringUtils.isNotBlank(sourceValue.toString())) {
                                    it.set(target, sourceValue);
                                }
                            }
                        }
                    } catch (IllegalAccessException e) {
                        if (logger.isErrorEnabled()) {
                            logger.error("拷贝属性出错" + e);
                        }
                    }
                }
            }
        });
    }
        /**
         * æ‹·è´æ•°æ®
         * å¤§å°å†™å¯ä»¥å¿½ç•¥
         * ä¸‹åˆ’线 _ è¢«å¿½ç•¥
         * @param source æ¥æºå±žæ€§
         * @param target ç›®æ ‡å±žæ€§
         * @param ignoreNull æ˜¯å¦å¿½ç•¥æŽ§åˆ¶
         */
    public static void copyPropertiesIgnoreCase(Object source,Object target,boolean ignoreNull,Map<String/**原对象的属性名字**/,String/**目标对象的属性名称**/> fieldMap){
        copyPropertiesIgnoreCase(source,target,ignoreNull,fieldMap,null);
    }
    /**
     * ç¼“存对象的属性
     */
    private static class CacheFieldMap {
        /**
         * å¯¹è±¡å±žæ€§çš„缓存
         */
        private static Map<String/**类的名字**/, Map<String/**属性的名称小写**/, Field/**属性的对象**/>> cacheMap = new HashMap<>();
        /**
         * å¯¹è±¡çš„自己类的环境,不包括父类
         */
        private static Map<String/**类的名称**/,Map<String/**属性的名称小写**/,Field/**属性的对象**/>> declaredCacheMap = new HashMap<>();
        /**
         * èŽ·å–å±žæ€§çš„æ˜ å°„
         * @param clazz ç±»
         * @return å±žæ€§åç§°å°å†™å’Œå±žæ€§çš„æ˜ å°„
         */
        private static Map<String/**属性名称**/, Field> getFieldMap(Class clazz) {
            Map<String, Field> result = cacheMap.get(clazz.getName());
            if (result == null) {
                synchronized (CacheFieldMap.class) {
                    if (result == null) {
                        Map<String, Field> fieldMap = new HashMap<>();
                        List<Field> allFields = VciBaseUtil.getAllFieldForObj(clazz);
                        if(!CollectionUtils.isEmpty(allFields)){
                            allFields.stream().forEach(field -> {
                                fieldMap.put(field.getName().toLowerCase().replace("_", ""), field);
                            });
                        }
                        cacheMap.put(clazz.getName(), fieldMap);
                        result = cacheMap.get(clazz.getName());
                    }
                }
            }
            return result;
        }
        /**
         * èŽ·å–å±žæ€§çš„æ˜ å°„ï¼ˆä¸åŒ…å«çˆ¶ç±»ï¼‰
         * @param clazz ç±»
         * @return å±žæ€§åç§°å°å†™å’Œå±žæ€§çš„æ˜ å°„
         */
        private static Map<String/**属性名称**/,Field> getDeclaredFieldMap(Class clazz){
            Map<String, Field> result = declaredCacheMap.get(clazz.getName());
            if(result == null){
                synchronized(CacheFieldMap.class){
                    if (result == null) {
                        Map<String, Field> fieldMap = new HashMap<>();
                        Field[] allFields = clazz.getDeclaredFields();
                        if(allFields!=null && allFields.length>0){
                            Arrays.stream(allFields).forEach(field -> {
                                fieldMap.put(field.getName().toLowerCase().replace("_", ""), field);
                            });
                        }
                        declaredCacheMap.put(clazz.getName(), fieldMap);
                        result = declaredCacheMap.get(clazz.getName());
                    }
                }
            }
            return result;
        }
    }
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/util/BusAnnotationUtil.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,52 @@
package com.vci.starter.web.util;
import com.vci.starter.web.exception.VciBaseException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.CollectionUtils;
import java.lang.reflect.Method;
import java.util.Map;
/**
 * ä¸šåŠ¡çš„æ³¨è§£å·¥å…·ç±»
 * @author weidy
 * @date 2022-04-12
 */
public class BusAnnotationUtil {
    /**
     * æ—¥å¿—
     */
    private static Logger logger = LoggerFactory.getLogger(BusAnnotationUtil.class);
    /**
     * é€šè¿‡æ³¨è§£åŽ»è°ƒç”¨å¯¹åº”çš„æ–¹æ³•
     * @param classAnnotation ç±»çš„æ³¨è§£
     * @param methodAnnotation æ–¹æ³•的注解
     * @param args å‚æ•°
     */
    public static void callForAnnotation(Class classAnnotation,Class methodAnnotation,Object ... args){
        //在登录之前,看看是否有插件
        Map<String, Object> beanMap = ApplicationContextProvider.getApplicationContext().getBeansWithAnnotation(classAnnotation);
        if (!CollectionUtils.isEmpty(beanMap)) {
            beanMap.forEach((k, v) -> {
                Method[] methods = v.getClass().getSuperclass().getDeclaredMethods();
                if (methods != null && methods.length > 0) {
                    for (Method method : methods) {
                        if (method.isAnnotationPresent(methodAnnotation)) {
                            try {
                                method.invoke(v, args);
                            } catch (Throwable e) {
                                if (logger.isErrorEnabled()) {
                                    logger.error("调用插件出错", e);
                                }
                                throw new VciBaseException("调用插件出错,{0},{1}", new String[]{v.getClass().getName(), method.getName()}, e);
                            }
                        }
                    }
                }
            });
        }
    }
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/util/ClassUtil.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,85 @@
package com.vci.starter.web.util;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
/**
 * ç±»çš„æ“ä½œå·¥å…·
 * @author weidy
 * @date 2019/11/23 10:18 AM
 */
public class ClassUtil {
    /**
     * åŸºæœ¬ç±»åž‹çš„æ˜ å°„
     */
    private static final Map<Class<?>, Class<?>> primitiveMap = new HashMap<>(9);
    /**
     * åˆå§‹åŒ–的时候,将基础类型添加进去
     */
    static {
        primitiveMap.put(String.class, String.class);
        primitiveMap.put(Boolean.class, boolean.class);
        primitiveMap.put(Byte.class, byte.class);
        primitiveMap.put(Character.class, char.class);
        primitiveMap.put(Double.class, double.class);
        primitiveMap.put(Float.class, float.class);
        primitiveMap.put(Integer.class, int.class);
        primitiveMap.put(Long.class, long.class);
        primitiveMap.put(Short.class, short.class);
        primitiveMap.put(Date.class, Date.class);
    }
    /**
     * åˆ¤æ–­åŸºæœ¬ç±»åž‹
     * @see     java.lang.String
     * @see     java.lang.Boolean#TYPE
     * @see     java.lang.Character#TYPE
     * @see     java.lang.Byte#TYPE
     * @see     java.lang.Short#TYPE
     * @see     java.lang.Integer#TYPE
     * @see     java.lang.Long#TYPE
     * @see     java.lang.Float#TYPE
     * @see     java.lang.Double#TYPE
     * @see     java.lang.Boolean#TYPE
     * @see     byte
     * @see     short
     * @see     int
     * @see     long
     * @see     float
     * @see     double
     * @param clazz ç±»
     * @return boolean true表示为基本类型
     */
    public static boolean isPrimitive(Class<?> clazz) {
        if (primitiveMap.containsKey(clazz)) {
            return true;
        }
        return clazz.isPrimitive();
    }
    /**
     * èŽ·å–æ–¹æ³•è¿”å›žå€¼ç±»åž‹
     * @param tartget ç›®æ ‡å¯¹è±¡çš„ç±»
     * @param fieldName å±žæ€§çš„名称
     * @return Class<?> è¿”回值类型
     */
    public static Class<?> getElementType(Class<?> tartget, String fieldName) {
        Class<?> elementTypeClass = null;
        try {
            Type type = VciBaseUtil.getFieldForObject(fieldName,tartget).getGenericType();
            ParameterizedType t = (ParameterizedType) type;
            String classStr = t.getActualTypeArguments()[0].toString().replace("class ", "");
            if(classStr.contains("<")){
                classStr = classStr.substring(classStr.lastIndexOf("<") + 1 ,classStr.indexOf(">"));
            }
            elementTypeClass = Thread.currentThread().getContextClassLoader().loadClass(classStr);
        } catch (ClassNotFoundException | SecurityException e) {
            throw new RuntimeException("get fieldName[" + fieldName + "] error", e);
        }
        return elementTypeClass;
    }
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/util/ControllerUtil.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,326 @@
package com.vci.starter.web.util;
import com.vci.starter.web.pagemodel.PageHelper;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.MediaType;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
 * åœ¨controller层使用的工具
 * @author weidy
 * @date 2020/2/19
 */
public class ControllerUtil {
    /**
     * æ—¥å¿—对象
     */
    private static Logger logger = LoggerFactory.getLogger(ControllerUtil.class);
    /**
     * å°†æ–‡ä»¶å†™å…¥åˆ°è¿”回流中
     * @param response å“åº”对象
     * @param fileName æ–‡ä»¶åç§°
     * @throws FileNotFoundException æ–‡ä»¶æ²¡æœ‰æ‰¾åˆ°
     * @throws IOException è¯»å–文件出错,或者写数据出错
     */
    public static void writeFileToResponse(HttpServletResponse response,String fileName) throws FileNotFoundException,IOException{
        writeFileToResponse(response,fileName,true);
    }
    /**
     * å°†æ–‡ä»¶å†™å…¥åˆ°è¿”回流中
     * @param response å“åº”对象
     * @param fileName æ–‡ä»¶åç§°
     * @param deleteFile ä¸‹è½½å®ŒæˆåŽæ˜¯å¦åˆ é™¤æ–‡ä»¶ï¼Œtrue表示删除,另外这个文件的上级文件夹也会被删除,因此临时文件夹一般都添加了随机名称的文件夹
     * @throws FileNotFoundException æ–‡ä»¶æ²¡æœ‰æ‰¾åˆ°
     * @throws IOException è¯»å–文件出错,或者写数据出错
     */
    public static void writeFileToResponse(HttpServletResponse response,String fileName,boolean deleteFile) throws FileNotFoundException,IOException{
        writeFileToResponse(response,fileName,null,deleteFile);
    }
    /**
     * å°†æ–‡ä»¶å†™å…¥åˆ°è¿”回流中
     * @param response å“åº”对象
     * @param fileName æ–‡ä»¶åç§°
     * @param deleteFile ä¸‹è½½å®ŒæˆåŽæ˜¯å¦åˆ é™¤æ–‡ä»¶ï¼Œtrue表示删除,另外这个文件的上级文件夹也会被删除,因此临时文件夹一般都添加了随机名称的文件夹
     * @param showName æ˜¾ç¤ºæ–‡ä»¶åï¼Œå³ç”¨æˆ·çœ‹åˆ°çš„名称,否则直接为原文件的名称
     * @throws FileNotFoundException æ–‡ä»¶æ²¡æœ‰æ‰¾åˆ°
     * @throws IOException è¯»å–文件出错,或者写数据出错
     */
    public static void writeFileToResponse(HttpServletResponse response,String fileName,String showName,boolean deleteFile) throws FileNotFoundException,IOException {
        File file = new File(fileName);
        if(!file.exists()){
            throw new FileNotFoundException(fileName);
        }
        writeFileToResponse(response,file,showName,deleteFile);
    }
    /**
     * å°†æ–‡ä»¶å†™å…¥åˆ°è¿”回流中
     * @param response å“åº”对象
     * @param file æ–‡ä»¶å¯¹è±¡
     * @throws FileNotFoundException æ–‡ä»¶æ²¡æœ‰æ‰¾åˆ°
     * @throws IOException è¯»å–文件出错,或者写数据出错
     */
    public static void writeFileToResponse(HttpServletResponse response, File file) throws FileNotFoundException,IOException{
        writeFileToResponse(response,file,true);
    }
    /**
     * å°†æ–‡ä»¶å†™å…¥åˆ°è¿”回流中
     * @param response å“åº”对象
     * @param file æ–‡ä»¶å¯¹è±¡
     * @param deleteFile ä¸‹è½½å®ŒæˆåŽæ˜¯å¦åˆ é™¤æ–‡ä»¶ï¼Œtrue表示删除,另外这个文件的上级文件夹也会被删除,因此临时文件夹一般都添加了随机名称的文件夹
     * @throws FileNotFoundException æ–‡ä»¶æ²¡æœ‰æ‰¾åˆ°
     * @throws IOException è¯»å–文件出错,或者写数据出错
     */
    public static void writeFileToResponse(HttpServletResponse response,File file,boolean deleteFile) throws FileNotFoundException,IOException{
        writeFileToResponse(response,file,null,deleteFile);
    }
    /**
     * å°†æ–‡ä»¶å†™å…¥åˆ°è¿”回流中
     * @param response å“åº”对象
     * @param file æ–‡ä»¶å¯¹è±¡
     * @param deleteFile ä¸‹è½½å®ŒæˆåŽæ˜¯å¦åˆ é™¤æ–‡ä»¶ï¼Œtrue表示删除,另外这个文件的上级文件夹也会被删除,因此临时文件夹一般都添加了随机名称的文件夹
     * @param showName æ˜¾ç¤ºæ–‡ä»¶åï¼Œå³ç”¨æˆ·çœ‹åˆ°çš„名称,否则直接为原文件的名称
     * @throws FileNotFoundException æ–‡ä»¶æ²¡æœ‰æ‰¾åˆ°
     * @throws IOException è¯»å–文件出错,或者写数据出错
     */
    public static void writeFileToResponse(HttpServletResponse response,File file,String showName,boolean deleteFile) throws FileNotFoundException,IOException {
        writeFileToResponse(response,file,showName,deleteFile,null);
    }
    /**
     * å°†æ–‡ä»¶å†™å…¥åˆ°è¿”回流中
     * @param response å“åº”对象
     * @param file æ–‡ä»¶å¯¹è±¡
     * @param deleteFile ä¸‹è½½å®ŒæˆåŽæ˜¯å¦åˆ é™¤æ–‡ä»¶ï¼Œtrue表示删除,另外这个文件的上级文件夹也会被删除,因此临时文件夹一般都添加了随机名称的文件夹
     * @param showName æ˜¾ç¤ºæ–‡ä»¶åï¼Œå³ç”¨æˆ·çœ‹åˆ°çš„名称,否则直接为原文件的名称
     * @throws FileNotFoundException æ–‡ä»¶æ²¡æœ‰æ‰¾åˆ°
     * @throws IOException è¯»å–文件出错,或者写数据出错
     */
    public static void writeFileToResponse(HttpServletResponse response,File file,String showName,boolean deleteFile,String contentType) throws FileNotFoundException,IOException {
        VciBaseUtil.alertNotNull(file, "文件对象");
        if (!file.exists()) {
            throw new FileNotFoundException(file.getName());
        }
        if (StringUtils.isBlank(showName)) {
            showName = file.getName();
        }
        InputStream in = null;
        try {
            in = new FileInputStream(file);
            writeFileToResponse(response, in, showName, contentType);
        } catch (IOException e) {
            //有可能客户端的链接
            if (logger.isErrorEnabled()) {
                logger.error("写入文件到响应流出错", e);
            }
        } finally {
            IOUtils.closeQuietly(in);
            if (deleteFile) {
                File parentFile = file.getParentFile();
                file.delete();
                parentFile.delete();
            }
        }
    }
    /**
     * å°†è¾“入流写入到返回流中
     * @param response  å“åº”对象
     * @param ins è¾“入流
     * @param showName åç§°
     * @throws IOException æ‹·è´å‡ºé”™çš„æ—¶å€™ä¼šæŠ›å‡ºå¼‚常
     */
    public static void writeFileToResponse(HttpServletResponse response,InputStream ins,String showName) throws IOException{
        writeFileToResponse(response,ins,showName,null);
    }
    /**
     * å°†è¾“入流写入到返回流中
     * @param response  å“åº”对象
     * @param ins è¾“入流
     * @param showName åç§°
     * @throws IOException æ‹·è´å‡ºé”™çš„æ—¶å€™ä¼šæŠ›å‡ºå¼‚常
     */
    public static void writeFileToResponse(HttpServletResponse response,InputStream ins,String showName,String contentType ) throws IOException{
        if(StringUtils.isBlank(contentType)) {
            contentType = "application/force-download";
        }
        if(StringUtils.isBlank(showName)){
            showName = "下载文件";
        }
        // è®¾ç½®å¼ºåˆ¶ä¸‹è½½ä¸æ‰“å¼€
        response.setContentType(contentType);
        try{
            String fileName = URLEncoder.encode(showName, "UTF8");
            response.addHeader("Content-Disposition", "attachment; filename="+ fileName+ ";filename*=utf-8''" + fileName);
        }catch(Exception e){
            if(logger.isErrorEnabled()){
                logger.error("设置文件的名称到响应流的时候出错",e);
            }
        }
        response.setCharacterEncoding("UTF-8");
        Cookie cookie = new Cookie("fileDownload", "true");
        cookie.setPath("/");
        response.addCookie(cookie);
        try{
            IOUtils.copy(ins,response.getOutputStream());
        } catch (IOException e) {
            //有可能客户端的链接
            if(logger.isErrorEnabled()){
                logger.error("写入文件到响应流出错",e);
            }
            throw e;
        }finally {
            IOUtils.closeQuietly(ins);
        }
    }
    /**
     * å°†è¾“入流写入到返回流中
     * @param response  å“åº”对象
     * @param data æ•°æ®çš„信息
     * @throws IOException æ‹·è´å‡ºé”™çš„æ—¶å€™ä¼šæŠ›å‡ºå¼‚常
     */
    public static void writeDataToResponse(HttpServletResponse response,byte[] data,String contentType) throws IOException {
        if (StringUtils.isBlank(contentType)) {
            contentType = "application/force-download";
        }
        response.setContentType(contentType);
        response.setCharacterEncoding("UTF-8");
        Cookie cookie = new Cookie("fileDownload", "true");
        cookie.setPath("/");
        response.addCookie(cookie);
        try {
            response.getOutputStream().write(data);
        } catch (IOException e) {
            //有可能客户端的链接
            if (logger.isErrorEnabled()) {
                logger.error("写入文件到响应流出错", e);
            }
            throw e;
        }
    }
    /**
     * å°†çŽ¯å¢ƒå˜é‡ä¸­çš„æŸä¸ªæ–‡ä»¶å†™åˆ°è¿”å›žæµä¸­
     * @param response å“åº”对象
     * @param classPathFileName åœ¨çŽ¯å¢ƒå˜é‡é‡Œçš„æ–‡ä»¶åç§°
     * @throws FileNotFoundException æ–‡ä»¶æ²¡æœ‰æ‰¾åˆ°
     * @throws IOException è¯»å–文件出错,或者写数据出错
     */
    public static void writeClasspathFileToResponse(HttpServletResponse response,String classPathFileName) throws FileNotFoundException,IOException{
        writeClasspathFileToResponse(response,classPathFileName,null);
    }
    /**
     * å°†çŽ¯å¢ƒå˜é‡ä¸­çš„æŸä¸ªæ–‡ä»¶å†™åˆ°è¿”å›žæµä¸­
     * @param response å“åº”对象
     * @param classPathFileName åœ¨çŽ¯å¢ƒå˜é‡é‡Œçš„æ–‡ä»¶åç§°
     * @param showName æ˜¾ç¤ºåç§°
     * @throws FileNotFoundException æ–‡ä»¶æ²¡æœ‰æ‰¾åˆ°
     * @throws IOException è¯»å–文件出错,或者写数据出错
     */
    public static void writeClasspathFileToResponse(HttpServletResponse response,String classPathFileName,String showName) throws FileNotFoundException,IOException{
        InputStream in = Thread.currentThread().getContextClassLoader().getResourceAsStream(classPathFileName);
        if(StringUtils.isBlank(showName)){
            showName = classPathFileName.contains("/")?classPathFileName.substring(classPathFileName.lastIndexOf("/") + 1):classPathFileName;
        }
        try {
            writeFileToResponse(response, in, showName);
        }catch (IOException e){
            throw e;
        }finally {
            IOUtils.closeQuietly(in);
        }
    }
    /**
     * èŽ·å–IP地址,通过request
     * @param request http请求对象
     * @return ip地址
     */
    public static String getClientInfo(HttpServletRequest request){
        String ip = request.getHeader("X-Forwarded-For");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_CLIENT_IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_X_FORWARDED_FOR");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        if (ip == null || ip.length() == 0 || ip.indexOf("0:0:0:0:0:0:0:1") >-1) {//0:0:0:0:0:0:0:1是本机在访问
            ip = "127.0.0.1";
        }
        return ip;
    }
    /**
     * ä¸‹è½½é”™è¯¯æ–‡ä»¶çš„æ˜ å°„内容
     */
    public static final Map<String/**主键**/,String/**文件路径**/> tempFileForDownloadMap = new ConcurrentHashMap<>();
    /**
     * è®¾ç½®æŸ¥è¯¢æ€»æ•°
     * @param request è¯·æ±‚对象
     * @param isQueryTotal æ˜¯å¦æŸ¥è¯¢æ€»æ•°
     */
    public static void setQueryTotal(HttpServletRequest request, boolean isQueryTotal){
        WebThreadLocalUtil.getNeedQueryTotalInThread().set(isQueryTotal?"true":"false");
        //request.setAttribute(webProperties.getQueryTotalSessionName(), isQueryTotal);
    }
    /**
     * æ”¾ç½®é”™è¯¯çš„æ–‡ä»¶
     * @param errorFile é”™è¯¯çš„æ–‡ä»¶
     * @return å”¯ä¸€æ ‡è¯†
     */
    public static String putErrorFile(String errorFile){
        String uuid = VciBaseUtil.getPk();
        tempFileForDownloadMap.put(uuid,errorFile);
        return uuid;
    }
    /**
     * ä¸‹è½½é”™è¯¯çš„æ–‡ä»¶(仅限于excel)
     * @param response å“åº”对象
     * @param uuid å”¯ä¸€çš„æ ‡è¯†
     * @throws IOException å†™å…¥æ–‡ä»¶å‡ºé”™çš„æ—¶å€™æŠ›å‡ºå¼‚常
     */
    public static void downloadErrorFile(HttpServletResponse response,String uuid) throws IOException{
        String errorFile = tempFileForDownloadMap.getOrDefault(uuid, "");
        try {
            if (StringUtils.isNotBlank(errorFile)) {
                ControllerUtil.writeFileToResponse(response, new File(errorFile), null, true, "application/msexcel");
            }
        }finally {
            tempFileForDownloadMap.remove(uuid);
        }
    }
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/util/LangBaseUtil.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,41 @@
package com.vci.starter.web.util;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
 * å¤šè¯­ç›¸å…³çš„工具类
 * @author weidy
 */
public class LangBaseUtil {
    /**
     * èŽ·å–å¼‚å¸¸ä¿¡æ¯
     * @param e å¼‚常对象
     * @return å¼‚常对象上的所有内容
     */
    public static String getErrorMsg(Throwable e){
        if(e == null){
            return "未知错误";
        }
        if( e.getClass()!= null && e.getClass().getSuperclass()!= null &&
                (e.getClass().getSuperclass().equals(RuntimeException.class)
                        || e.getClass().getSuperclass().getName().endsWith(".VciBaseException")
                        || e.getClass().getName().endsWith(".VciBaseException"))){
            //说明是我们自定义的异常类
            try {
                Method errorMethod = e.getClass().getMethod("getErrorMsg");
                if(errorMethod != null ){
                    return (String)errorMethod.invoke(e);
                }
            } catch (NoSuchMethodException e1) {
                return e.getMessage();
            } catch (IllegalAccessException e1) {
                return e.getMessage();
            } catch (InvocationTargetException e1) {
                return e.getMessage();
            }
        }
        return e.getMessage();
    }
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/util/LocalFileUtil.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,386 @@
package com.vci.starter.web.util;
import com.vci.starter.web.exception.VciBaseException;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.boot.system.ApplicationHome;
import org.springframework.core.io.ClassPathResource;
import org.springframework.util.ResourceUtils;
import java.io.*;
import java.nio.channels.FileChannel;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.UUID;
/**
 * æœ¬åœ°æ–‡ä»¶æ“ä½œç±»
 * @author weidy
 */
public class LocalFileUtil {
    /**
     * ä¸»ç±»
     */
    public static Class mainClass = null;
    /**
     * åˆ é™¤æ–‡ä»¶å¤¹
     * @param file è¦åˆ é™¤çš„æ–‡ä»¶æˆ–者文件夹
     */
    public static void deleteFile(File file) {
        if(file == null || !file.exists()){
            return;
        }
        if (file.isDirectory()) {
            File[] files = file.listFiles();
            for (int i = 0; i < files.length; i++) {
                deleteFile(files[i]);
            }
        }
        file.delete();
    }
    /**
     * æ‹·è´æ–‡ä»¶
     * @param source æºæ–‡ä»¶
     * @param target ç›®æ ‡æ–‡ä»¶
     * @throws VciBaseException æ‹·è´æ–‡ä»¶å‡ºé”™çš„æ—¶å€™ä¼šæŠ›å‡ºå¼‚常
     */
    public static void copyFile(File source, File target) throws VciBaseException {
        FileInputStream is = null;
        FileOutputStream os = null;
        try{
            is = new FileInputStream(source);
            os = new FileOutputStream(target);
            FileChannel sourceChannel = is.getChannel();
            FileChannel targetChannel = os.getChannel();
            int i=0;
            int length=2097152;
            while(true){
                if(sourceChannel.position()==sourceChannel.size()){
                    sourceChannel.close();
                    targetChannel.close();
                    break;
                }
                if((sourceChannel.size()-sourceChannel.position())<20971520) {
                    length = (int) (sourceChannel.size() - sourceChannel.position());
                }else {
                    length = 20971520;
                }
                sourceChannel.transferTo(sourceChannel.position(),length,targetChannel);
                sourceChannel.position(sourceChannel.position()+length);
                i++;
            }
        }catch(Throwable e){
            throw new VciBaseException("拷贝文件出错",new String[0],e);
        }finally {
            IOUtils.closeQuietly(is);
            IOUtils.closeQuietly(os);
        }
    }
    /**
     * èŽ·å–é»˜è®¤çš„ä¸´æ—¶æ–‡ä»¶å¤¹
     * @return ä¸´æ—¶æ–‡ä»¶å¤¹ï¼Œé»˜è®¤ä¸ºå½“前项目的运行路径下的tempFolder下的随机值
     */
    public static String getDefaultTempFolder() throws VciBaseException{
        String path = getProjectFolder();
        path = path + File.separator + "tempFolder" + File.separator + UUID.randomUUID().toString();
        File folder = new File(path);
        if(!folder.exists()){
            folder.mkdirs();
        }
        return path;
    }
    /**
     * èŽ·å–é¡¹ç›®çš„è·¯å¾„
     * @return é¡¹ç›®çš„路径
     * @throws VciBaseException èŽ·å–è·¯å¾„å‡ºçŽ°äº†é”™è¯¯ä¼šæŠ›å‡ºå¼‚å¸¸
     */
    public static String getProjectFolder() throws VciBaseException{
        return getProjectFolder(LocalFileUtil.class);
    }
    /**
     * èŽ·å–æŸä¸ªclass所在项目的路径
     * @param classObj æŸä¸ªclass
     * @return é¡¹ç›®çš„路径
     * @throws VciBaseException èŽ·å–è·¯å¾„å‡ºçŽ°äº†é”™è¯¯ä¼šæŠ›å‡ºå¼‚å¸¸
     */
    public static String getProjectFolder(Class classObj) throws VciBaseException{
        String path = "";
        try {
            ApplicationHome h = new ApplicationHome(classObj == null?(mainClass ==null?LocalFileUtil.class:mainClass):classObj);
            File jarF = h.getSource();
            if(jarF == null){
                //针对测试的时候
                jarF = h.getDir();
            }
            path =  jarF.getParentFile().toString();
            if(path.contains("!")){
                path = new File(path).getParentFile().getParent();
            }
        }catch (Throwable e){
            e.printStackTrace();
            throw new VciBaseException("获取当前服务所在的文件夹出现了错误",new String[0],e);
        }
        if(path.startsWith("file:\\")){
            path = path.substring(6);
        }
        if (System.getProperty("os.name").toLowerCase().startsWith("win") && path.startsWith("/")) {
            path = path.substring(path.indexOf("/") + 1);
        }
        System.out.println("项目的路径是:" + path);
        return path;
    }
    /**
     * åˆ é™¤ä¸´æ—¶æ–‡ä»¶
     * @param tempFile ä¸´æ—¶æ–‡ä»¶
     * @param deleteRandomFolder æ˜¯å¦åˆ é™¤éšæœºçš„那个文件夹
     * @throws VciBaseException åˆ é™¤å‡ºé”™çš„æ—¶å€™æŠ›å‡ºå¼‚常
     */
    public static void deleteTempFile(File tempFile,boolean deleteRandomFolder) throws VciBaseException{
        if(tempFile!=null){
            tempFile.delete();
            if(deleteRandomFolder){
                tempFile.getParentFile().delete();
            }
        }
    }
    /**
     * åˆ¤æ–­å‚数是否为空
     * @param s å‚数,第一个为参数,第二个为提示信息
     * @throws VciBaseException ä¸ºç©ºæ—¶æŠ›å‡ºè¿™ä¸ªå¼‚常
     */
    public static void alertNotNull(Object... s) throws VciBaseException{
        if(s!=null && s.length>0){
            for(int i = 0 ; i < s.length ; i ++){
                Object obj = s[i];
                if(obj==null ||StringUtils.isBlank(obj.toString())){
                    String param = "";
                    try{
                        i++;
                        param = s[i].toString();
                    }catch(Exception e){
                    }
                    throw new VciBaseException("参数[" + param + "]不能为空");
                }
            }
        }
    }
    /**
     * èŽ·å–æ–‡ä»¶çš„åŽç¼€å
     * @param file æ–‡ä»¶å¯¹è±¡
     * @return åŽç¼€åï¼Œä¸åŒ…含.;如果文件不存在或者没有后缀名返回""
     */
    public static String getFileExtension(File file){
        if(file!=null){
            return getFileExtensionByName(file.getName());
        }
        return "";
    }
    /**
     * èŽ·å–æ–‡ä»¶çš„åŽç¼€å
     * @param name æ–‡ä»¶åç§°
     * @return åŽç¼€åï¼Œä¸åŒ…含.;没有后缀名返回""
     */
    public static String getFileExtensionByName(String name){
        if(StringUtils.isNotBlank(name)){
            if(name.contains(".")){
                return name.substring(name.lastIndexOf(".")+1);
            }
        }
        return "";
    }
    /**
     * èŽ·å–ä¸Šä¼ æ–‡ä»¶çš„åç§°ï¼Œåœ¨IE浏览器上,上传会把全路径带过来
     * @param name æ–‡ä»¶çš„名称
     * @return æ›¿æ¢åŽçš„值
     */
    public static String getFileNameForIE(String name){
        if(StringUtils.isBlank(name)){
            return name;
        }
        if(name.contains(File.separator)){
            return name.substring(name.lastIndexOf(File.separator)+1);
        }
        if(name.contains("\\")){
            return name.substring(name.lastIndexOf("\\") + 1);
        }
        return name;
    }
    /**
     * ä»Žå·¥ç¨‹ä¸­è¯»å–文件的内容
     * @param fileName æ–‡ä»¶çš„名称
     * @return æ–‡ä»¶çš„内容
     * @throws VciBaseException è¯»å–出错的时候会抛出异常
     */
    public static String readContentForFileInJar(String fileName) throws VciBaseException{
        if(StringUtils.isBlank(fileName)){
            throw new VciBaseException("文件名为空");
        }
        if(!fileName.startsWith("/")){
            fileName = "/" + fileName;
        }
        InputStream in = null;
        ByteArrayOutputStream os = null;
        try{
            in = LocalFileUtil.class.getResourceAsStream( fileName);
            if(in ==null){
                in=Thread.currentThread().getContextClassLoader().getResourceAsStream(fileName);
            }
            os = new ByteArrayOutputStream();
            IOUtils.copy(in,os);
            return new String(os.toByteArray(),"UTF-8");
        }catch (Throwable e){
            throw new VciBaseException("读取文件的内容出现了错误",new String[0],e);
        }finally {
            IOUtils.closeQuietly(in);
            IOUtils.closeQuietly(os);
        }
    }
    /**
     * è¯»å–文件的内容,文件不能是jar里的
     * @param fileName æ–‡ä»¶çš„名称
     * @return æ–‡ä»¶çš„内容,是UTF-8的字符集
     * @throws VciBaseException æ–‡ä»¶ä¸å­˜åœ¨ï¼Œå’Œè¯»å–出错的时候会抛出异常
     */
    public static String readContentForFile(String fileName) throws VciBaseException{
        File file = new File(fileName);
        if(!file.exists()){
            throw new VciBaseException("文件未找到,{0}",new String[]{fileName});
        }
        InputStream in = null;
        ByteArrayOutputStream os = null;
        try{
            in = new FileInputStream( file);
            os = new ByteArrayOutputStream();
            IOUtils.copy(in,os);
            return new String(os.toByteArray(),"UTF-8");
        }catch (Throwable e){
            throw new VciBaseException("读取文件的内容出现了错误",new String[0],e);
        }finally {
            IOUtils.closeQuietly(in);
            IOUtils.closeQuietly(os);
        }
    }
    /**
     * å†™å…¥å­—符串到文件
     * @param content å­—符串
     * @param fileName æ–‡ä»¶çš„名称
     * @throws VciBaseException å†™å…¥å‡ºé”™çš„æ—¶å€™ä¼šæŠ›å‡ºå¼‚常
     */
    public static void writeContentToFile(String content,String fileName) throws VciBaseException{
        File file = new File(fileName);
        if(!file.exists()){
            File parentFile = file.getParentFile();
            if(!parentFile.exists()){
                parentFile.mkdirs();
            }
            try {
                file.createNewFile();
            } catch (IOException e) {
                throw new VciBaseException("写入文件的内容时候出现了创建文件失败的问题,{}",new String[]{fileName},e);
            }
        }
        if(content == null){
            content = "";
        }
        OutputStream os = null;
        try{
            os = new FileOutputStream(file);
            os.write(content.getBytes(StandardCharsets.UTF_8));
            os.flush();
        }catch(Throwable e){
            throw new VciBaseException("写入文件的内容时候出现了创错误,{}",new String[]{fileName},e);
        }finally {
            IOUtils.closeQuietly(os);
        }
    }
    /**
     * ä»Žé¡¹ç›®é‡Œæˆ–者jar的文件到目标文件
     * @param fileInJar jar或者项目里的文件名称
     * @param target ç›®æ ‡æ–‡ä»¶
     * @throws VciBaseException æ‹·è´æ–‡ä»¶å‡ºçŽ°é”™è¯¯çš„æ—¶å€™ä¼šæŠ›å‡ºå¼‚å¸¸
     */
    public static void copyFileInJar(String fileInJar,String target) throws  VciBaseException{
        VciBaseUtil.alertNotNull(fileInJar,"源文件",target,"目标文件");
        File targetFile = new File(target);
        File folder = targetFile.getParentFile();
        if(!folder.exists()){
            folder.mkdirs();
        }
        if(!targetFile.exists()){
            try {
                targetFile.createNewFile();
            } catch (IOException e) {
                throw new VciBaseException("创建目标文件的出现了错误",new String[0],e);
            }
        }
        if(!fileInJar.startsWith("/")){
            fileInJar = "/" + fileInJar;
        }
        InputStream in = null;
        FileOutputStream os = null;
        try{
            in =  LocalFileUtil.class.getResourceAsStream( fileInJar);
            if(in ==null){
                in=Thread.currentThread().getContextClassLoader().getResourceAsStream(fileInJar);
            }
            os = new FileOutputStream(target);
            IOUtils.copy(in,os);
        }catch (Throwable e){
            throw new VciBaseException("拷贝文件的内容出现了错误.{0},{1}",new String[]{fileInJar,target},e);
        }finally {
            IOUtils.closeQuietly(in);
            IOUtils.closeQuietly(os);
        }
    }
    /**
     * æ–‡ä»¶è½¬æ¢ä¸ºè·¯å¾„
     * @param fileList æ–‡ä»¶åˆ—表
     * @return è·¯å¾„列表
     * @throws VciBaseException å‚数为空和文件不存在会抛出异常
     */
    public static List<String> fileToPatch(Collection<File> fileList) throws VciBaseException  {
        VciBaseUtil.alertNotNull("文件列表",fileList);
        List<String> filePath = new ArrayList<>();
        for(File file : fileList){
            if(!file.exists()){
                throw new VciBaseException(file.getAbsolutePath() + "文件没有找到",new String[0]);
            }
            filePath.add(file.getAbsolutePath());
        }
        return filePath;
    }
    /**
     * èŽ·å–å›¾ç‰‡ä¸“ç”¨çš„ä¸´æ—¶è·¯å¾„
     * @return è·¯å¾„
     * @throws VciBaseException èŽ·å–å‡ºé”™ä¼šæŠ¥é”™
     */
    public static String getDefaultPicTempFolder() throws VciBaseException{
        String path = LocalFileUtil.getProjectFolder();
        path = path + File.separator + "tempFolder" + File.separator + "picFolder" + File.separator ;
        File folder = new File(path);
        if(!folder.exists()){
            folder.mkdirs();
        }
        return path;
    }
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/util/Lunar.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,282 @@
package com.vci.starter.web.util;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
/**
 * å†œåŽ†è½¬æ¢
 * @author weidy
 * @date
 */
public class Lunar {
    /**
     * å¹´
     */
    private int year;
    /**
     * æœˆä»½
     */
    private int month;
    /**
     * å¤©æ•°
     */
    private int day;
    /**
     *
     */
    private boolean leap;
    /**
     * æœˆä»½
     */
    final static String chineseNumber[] = { "一", "二", "三", "四", "五", "六", "七",
            "八", "九", "十", "十一", "十二" };
    /**
     * æ—¶é—´æ ¼å¼
     */
    static SimpleDateFormat chineseDateFormat = new SimpleDateFormat(
            "yyyyå¹´MM月dd日");
    /**
     * å†œåŽ†çš„ä¿¡æ¯
     */
    final static long[] lunarInfo = new long[] { 0x04bd8, 0x04ae0, 0x0a570,
            0x054d5, 0x0d260, 0x0d950, 0x16554, 0x056a0, 0x09ad0, 0x055d2,
            0x04ae0, 0x0a5b6, 0x0a4d0, 0x0d250, 0x1d255, 0x0b540, 0x0d6a0,
            0x0ada2, 0x095b0, 0x14977, 0x04970, 0x0a4b0, 0x0b4b5, 0x06a50,
            0x06d40, 0x1ab54, 0x02b60, 0x09570, 0x052f2, 0x04970, 0x06566,
            0x0d4a0, 0x0ea50, 0x06e95, 0x05ad0, 0x02b60, 0x186e3, 0x092e0,
            0x1c8d7, 0x0c950, 0x0d4a0, 0x1d8a6, 0x0b550, 0x056a0, 0x1a5b4,
            0x025d0, 0x092d0, 0x0d2b2, 0x0a950, 0x0b557, 0x06ca0, 0x0b550,
            0x15355, 0x04da0, 0x0a5d0, 0x14573, 0x052d0, 0x0a9a8, 0x0e950,
            0x06aa0, 0x0aea6, 0x0ab50, 0x04b60, 0x0aae4, 0x0a570, 0x05260,
            0x0f263, 0x0d950, 0x05b57, 0x056a0, 0x096d0, 0x04dd5, 0x04ad0,
            0x0a4d0, 0x0d4d4, 0x0d250, 0x0d558, 0x0b540, 0x0b5a0, 0x195a6,
            0x095b0, 0x049b0, 0x0a974, 0x0a4b0, 0x0b27a, 0x06a50, 0x06d40,
            0x0af46, 0x0ab60, 0x09570, 0x04af5, 0x04970, 0x064b0, 0x074a3,
            0x0ea50, 0x06b58, 0x055c0, 0x0ab60, 0x096d5, 0x092e0, 0x0c960,
            0x0d954, 0x0d4a0, 0x0da50, 0x07552, 0x056a0, 0x0abb7, 0x025d0,
            0x092d0, 0x0cab5, 0x0a950, 0x0b4a0, 0x0baa4, 0x0ad50, 0x055d9,
            0x04ba0, 0x0a5b0, 0x15176, 0x052b0, 0x0a930, 0x07954, 0x06aa0,
            0x0ad50, 0x05b52, 0x04b60, 0x0a6e6, 0x0a4e0, 0x0d260, 0x0ea65,
            0x0d530, 0x05aa0, 0x076a3, 0x096d0, 0x04bd7, 0x04ad0, 0x0a4d0,
            0x1d0b6, 0x0d250, 0x0d520, 0x0dd45, 0x0b5a0, 0x056d0, 0x055b2,
            0x049b0, 0x0a577, 0x0a4b0, 0x0aa50, 0x1b255, 0x06d20, 0x0ada0 };
    /**
     *     ====== ä¼ å›žå†œåކ y年的总天数
     */
    final private static int yearDays(int y) {
        int i, sum = 348;
        for (i = 0x8000; i > 0x8; i >>= 1) {
            if ((lunarInfo[y - 1900] & i) != 0) {
                sum += 1;
            }
        }
        return (sum + leapDays(y));
    }
    /**
     *     ====== ä¼ å›žå†œåކ y年闰月的天数
     */
    final private static int leapDays(int y) {
        if (leapMonth(y) != 0) {
            if ((lunarInfo[y - 1900] & 0x10000) != 0) {
                return 30;
            }
            else {
                return 29;
            }
        } else {
            return 0;
        }
    }
    /**
     *  ====== ä¼ å›žå†œåކ y年闰哪个月 1-12 , æ²¡é—°ä¼ å›ž 0
     *
     */
    final private static int leapMonth(int y) {
        return (int) (lunarInfo[y - 1900] & 0xf);
    }
    /**
     * ====== ä¼ å›žå†œåކ yå¹´m月的总天数
     *
     * @param y
     * @param m
     * @return
     */
    final private static int monthDays(int y, int m) {
        if ((lunarInfo[y - 1900] & (0x10000 >> m)) == 0) {
            return 29;
        }
        else {
            return 30;
        }
    }
    // ====== ä¼ å›žå†œåކ y年的生肖
    final public String animalsYear() {
        final String[] Animals = new String[] { "é¼ ", "牛", "虎", "兔", "龙", "蛇",
                "马", "羊", "猴", "鸡", "狗", "猪" };
        return Animals[(year - 4) % 12];
    }
    // ====== ä¼ å…¥ æœˆæ—¥çš„offset ä¼ å›žå¹²æ”¯, 0=甲子
    final private static String cyclicalm(int num) {
        final String[] Gan = new String[] { "甲", "乙", "丙", "丁", "戊", "å·±", "庚",
                "辛", "壬", "癸" };
        final String[] Zhi = new String[] { "子", "丑", "寅", "卯", "è¾°", "å·³", "午",
                "未", "申", "酉", "戌", "亥" };
        return (Gan[num % 10] + Zhi[num % 12]);
    }
    // ====== ä¼ å…¥ offset ä¼ å›žå¹²æ”¯, 0=甲子
    final public String cyclical() {
        int num = year - 1900 + 36;
        return (cyclicalm(num));
    }
    /**
     * ä¼ å‡ºyå¹´m月d日对应的农历. yearCyl3:农历年与1864的相差数 ? monCyl4:从1900å¹´1月31日以来,闰月数
     * dayCyl5:与1900å¹´1月31日相差的天数,再加40 ?
     *
     * @param cal
     * @return
     */
    public Lunar(Calendar cal) {
        @SuppressWarnings("unused")
        int yearCyl, monCyl, dayCyl;
        int leapMonth = 0;
        Date baseDate = null;
        try {
            baseDate = chineseDateFormat.parse("1900å¹´1月31日");
        } catch (ParseException e) {
            e.printStackTrace(); // To change body of catch statement use
                                    // Options | File Templates.
        }
        // æ±‚出和1900å¹´1月31日相差的天数
        int offset = (int) ((cal.getTime().getTime() - baseDate.getTime()) / 86400000L);
        dayCyl = offset + 40;
        monCyl = 14;
        // ç”¨offset减去每农历年的天数
        // è®¡ç®—当天是农历第几天
        // i最终结果是农历的年份
        // offset是当年的第几天
        int iYear, daysOfYear = 0;
        for (iYear = 1900; iYear < 2050 && offset > 0; iYear++) {
            daysOfYear = yearDays(iYear);
            offset -= daysOfYear;
            monCyl += 12;
        }
        if (offset < 0) {
            offset += daysOfYear;
            iYear--;
            monCyl -= 12;
        }
        // å†œåކ年份
        year = iYear;
        yearCyl = iYear - 1864;
        leapMonth = leapMonth(iYear); // é—°å“ªä¸ªæœˆ,1-12
        leap = false;
        // ç”¨å½“年的天数offset,逐个减去每月(农历)的天数,求出当天是本月的第几天
        int iMonth, daysOfMonth = 0;
        for (iMonth = 1; iMonth < 13 && offset > 0; iMonth++) {
            // é—°æœˆ
            if (leapMonth > 0 && iMonth == (leapMonth + 1) && !leap) {
                --iMonth;
                leap = true;
                daysOfMonth = leapDays(year);
            } else {
                daysOfMonth = monthDays(year, iMonth);
            }
            offset -= daysOfMonth;
            // è§£é™¤é—°æœˆ
            if (leap && iMonth == (leapMonth + 1)) {
                leap = false;
            }
            if (!leap) {
                monCyl++;
            }
        }
        // offset为0时,并且刚才计算的月份是闰月,要校正
        if (offset == 0 && leapMonth > 0 && iMonth == leapMonth + 1) {
            if (leap) {
                leap = false;
            } else {
                leap = true;
                --iMonth;
                --monCyl;
            }
        }
        // offset小于0时,也要校正
        if (offset < 0) {
            offset += daysOfMonth;
            --iMonth;
            --monCyl;
        }
        month = iMonth;
        day = offset + 1;
    }
    public static String getChinaDayString(int day) {
        String chineseTen[] = { "初", "十", "廿", "卅" };
        int n = day % 10 == 0 ? 9 : day % 10 - 1;
        if (day > 30) {
            return "";
        }
        if (day == 10) {
            return "初十";
        }
        else {
            return chineseTen[day / 10] + chineseNumber[n];
        }
    }
    @Override
    public String toString() {
        String m = chineseNumber[month - 1];
        if (m != null && m.trim().equals("一")) {
            m = "æ­£";
        }
        if (m != null && m.trim().equals("十一")) {
            m = "冬";
        }
        if (m != null && m.trim().equals("十二")) {
            m = "腊";
        }
        return year + cyclical() + animalsYear() + "å¹´" + (leap ? "闰" : "") + m
                + "月" + getChinaDayString(day);
    }
    public String getDate() {
        String m = chineseNumber[month - 1];
        if (m != null && m.trim().equals("一")) {
            m = "æ­£";
        }
        if (m != null && m.trim().equals("十一")) {
            m = "冬";
        }
        if (m != null && m.trim().equals("十二")) {
            m = "腊";
        }
        // cyclical() +
        return animalsYear() + "å¹´" + (leap ? "闰" : "") + m + "月"
                + getChinaDayString(day);
    }
    public static void main(String[] args) throws ParseException {
        Calendar today = Calendar.getInstance();
        today.setTime(chineseDateFormat.parse("2013å¹´2月1日"));
        Lunar lunar = new Lunar(today);
        System.out.println(lunar.toString());
        System.out.println("北京时间:" + chineseDateFormat.format(today.getTime())
                + " 农历" + lunar);
    }
}
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/util/Md5.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,120 @@
package com.vci.starter.web.util;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.security.MessageDigest;
/***
 * MD5加密
 * @author weidy
 */
public class Md5 {
    /**
     * æ—¥å¿—对象
     */
    private static Logger logger = LoggerFactory.getLogger(Md5.class);
    public Md5() {}
    /**
     * @desc å°†å­—符串转换为的MD5
     * @param v æ¥æºå­—符串
     * @return è½¬æ¢åŽçš„MD5字符串
     * @throws Exception
     */
    public static String md5(String v) {
        if (v == null) {
            return null;
        }
        try{
            MessageDigest md = MessageDigest.getInstance("MD5");
            return toHex(md.digest(v.getBytes()));
        }catch(Exception e){
            return null;
        }
    }
    /**
     * @desc ä¸¤æ¬¡MD5加密
     * @param sourceString åŠ å¯†å‰çš„å­—ç¬¦ä¸²
     * @return ä¸¤æ¬¡åŠ å¯†åŽçš„å­—ç¬¦ä¸²
     * @throws Exception
     */
    public static String twoTimesMd5(String sourceString) throws Exception {
        if(sourceString == null) {
            return null;
        }
        return md5(md5(sourceString));
    }
    /**
     * @desc å¯¹æ¯”传入的字符串生成的MD5于md5String是否相等
     * @param md5String ç”¨äºŽå¯¹æ¯”çš„md5字符串
     * @param sourceString åŠ å¯†å‰çš„å­—ç¬¦ä¸²
     * @return å¯¹æ¯”md5后的值,true表示相等
     */
    public static boolean equalMd5(String md5String, String sourceString) {
        if(md5String == null || sourceString == null) {
            return false;
        }else {
            try {
                if(md5String.equals(twoTimesMd5(sourceString))) {
                    return true;
                }else {
                    return false;
                }
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        }
    }
    /**
     * @desc md5一次后进行对比,这个主要是为登录验证密码用的,因为前台JS会先进行MD5加密一次
     * @param md5String ç”¨äºŽå¯¹æ¯”çš„md5字符串
     * @param sourceString åŠ å¯†å‰çš„å­—ç¬¦ä¸²
     * @return true表示相等
     */
    public static boolean equalOneMd5(String md5String, String sourceString) {
        if(md5String == null || sourceString == null) {
            return false;
        } else {
            try {
                String ms = md5(sourceString);
                if(md5String.equals(ms)) {
                    return true;
                }else {
                    return false;
                }
            }catch (Exception e) {
                if(logger.isErrorEnabled()) {
                    logger.error("对比md5的时候出现了错误", e);
                }
                return false;
            }
        }
    }
    /**
     *  è½¬æ¢ä¸ºhex的方式
     * @param buffer è¦è½¬æ¢çš„字节数组
     * @return è½¬æ¢åŽçš„字符串
     */
    private static String toHex(byte buffer[]) {
        StringBuffer sb = new StringBuffer(32);
        String s = null;
        for (int i = 0; i < buffer.length; i++) {
            s = Integer.toHexString((int) buffer[i] & 0xff);
            if (s.length() < 2) {
                sb.append('0');
            }
            sb.append(s);
        }
        return sb.toString();
    }
}
在上述文件截断后对比
Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/util/MessageUtils.java Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/util/VciBaseUtil.java Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/util/VciDateUtil.java Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/util/WebThreadLocalUtil.java Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/wrapper/VciParentQueryOption.java Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/wrapper/VciQueryWrapperForDO.java Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/wrapper/VciQueryWrapperOption.java Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/wrapper/VciReferFieldInfo.java Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/web/yml/YamlPropertySourceFactory.java Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/workflow/dto/WFWorkflowRuntimeDTO.java Source/plt-web/plt-web-parent/plt-web-base/src/main/java/com/vci/starter/workflow/pagemodel/WFWorkflowTaskHisVO.java Source/plt-web/plt-web-parent/plt-web-base/src/main/resources/application-web.yml Source/plt-web/plt-web-parent/plt-web/pom.xml Source/plt-web/plt-web-parent/pom.xml